Gilt undefiniertes Verhalten für asm-Code?

Lesezeit: 4 Minuten

Eloffs Benutzeravatar
Eloff

Nehmen wir an, Sie wissen, dass Ihre Software nur auf Zweierkomplement-Maschinen läuft, auf denen das Verhalten des vorzeichenbehafteten Überlaufs gut definiert ist. Signierter Überlauf ist immer noch undefiniertes Verhalten in C und C++, und der Compiler kann Ihr gesamtes Programm durch “ret” ersetzen, einen Atomkrieg beginnen, Ihr Laufwerk formatieren oder Dämonen aus Ihrer Nase fliegen lassen.

Angenommen, Sie haben einen signierten Überlauf in Inline-ASM, ruft Ihr Programm immer noch UB auf?

Wenn ja, was ist mit separat kompiliertem und gelinktem Assembler?

  • Dies ist eine sehr interessante Frage. Ich will es auch wissen.

    – Callyalater

    1. März 2016 um 18:32 Uhr

  • Ist inline asm überhaupt Standard C oder C++? Ich weiß es ehrlich gesagt nicht. Wenn nicht, steht die ganze Frage meines Erachtens auf wackeligen Beinen.

    – Baum mit Augen

    1. März 2016 um 18:33 Uhr


  • Nun, es gibt [dcl.asm]: Das asm Deklaration wird bedingt unterstützt; seine Bedeutung ist implementierungsdefiniert.

    – NathanOliver

    1. März 2016 um 18:34 Uhr


  • Für C99 habe ich nur das Schlüsselwort asm gefunden: J.5.10 Das Schlüsselwort asm kann verwendet werden, um Assemblersprache direkt in die Ausgabe des Übersetzers einzufügen (6.8).

    – fsasm

    1. März 2016 um 18:44 Uhr


  • Viele undefinierte Verhaltensweisen werden tatsächlich durch die Implementierung definiert. “Undefiniertes Verhalten” tut es nicht bedeutet “die Implementierung muss das Verhalten so zufällig und böse wie möglich machen”.

    – Christian Hackl

    1. März 2016 um 20:29 Uhr

“Undefiniertes Verhalten” bedeutet das C resp. C++-Standards definieren nicht das Verhalten Ihres Programms. Wenn Ihr Programm eine Inline-Assemblierung enthält, sollte ziemlich klar sein, dass sein Verhalten normalerweise weder vom C- noch vom C++-Standard beschrieben wird. Ein anderer Standard könnte das Verhalten sogar definieren, aber das bedeutet immer noch nicht “definiertes Verhalten” im Kontext des C- oder C++-Standards.

Allerdings erfordert der C-Standard eine Dokumentation der unterstützten Erweiterungen. Wenn das Verhalten Ihres Programms aus der Dokumentation Ihrer Implementierung abgeleitet werden kann und Ihre Implementierung dazu führt, dass sich Ihr Programm anders verhält, ist dies ein Versagen Ihrer Implementierung, dem Standard zu entsprechen:

4. Konformität

8. Eine Implementierung muss von einem Dokument begleitet werden, das alle implementierungsdefinierten und gebietsschemaspezifischen Merkmale und alle Erweiterungen definiert.

Für C++ wurde diese Anforderung abgeschwächt:

1.4 Einhaltung der Implementierung [intro.compliance]

9 Jede Implementierung muss eine Dokumentation enthalten, die alle bedingt unterstützten Konstrukte identifiziert, die sie nicht unterstützt, und alle gebietsschemaspezifischen Merkmale definiert.

und

1.9 Programmausführung [intro.execution]

2 Bestimmte Aspekte und Operationen der abstrakten Maschine werden in dieser Internationalen Norm als implementierungsdefiniert beschrieben […] Jede Implementierung muss eine Dokumentation enthalten, die ihre Eigenschaften und ihr Verhalten in dieser Hinsicht beschreibt. […]

Ich kann keine Anforderung finden, dass Erweiterungen dokumentiert werden müssen und wenn dokumentiert, korrekt dokumentiert werden müssen. Dies würde darauf hindeuten, dass in C++, selbst wenn Ihre Implementierung das Verhalten Ihres Programms als Erweiterung definiert, es einfach zu schade ist, wenn sich herausstellt, dass die Dokumentation falsch ist.

Für den C++-Halbstandard asm Aussage (wie in den Kommentaren erwähnt, “The asm Deklaration wird bedingt unterstützt; seine Bedeutung ist implementierungsdefiniert.”), wenn Ihre Implementierung dies unterstützt, muss es dokumentiert werden, aber natürlich ist es üblich, dass Implementierungen die Inline-Assemblierung auf eine andere Weise unterstützen als vom C++-Standard angedeutet, also gibt es das nicht Sie viel mehr.

  • Ok, gemäß dem Standard ist die Implementierung definiert, was Inline asm für das Programm bedeutet. Das wirft die Frage auf, was machen beliebte Compiler eigentlich?

    – Eloff

    1. März 2016 um 19:01 Uhr

  • @Eloff Das ist eine ganz andere Frage als das, was Sie in dieser Frage gestellt haben, und es dauert zu lange, sie hier zu beantworten.

    Benutzer743382

    1. März 2016 um 19:06 Uhr

Sobald Sie sagen, dass Sie einen signierten Überlauf in Inline-Asm haben, bedeutet dies, dass Sie von einem bestimmten Compiler (oder einer Reihe von Compilern) sprechen, da in C wie in C++ die Unterstützung für die Asm-Deklaration und ihre Bedeutung vorhanden ist Compiler definiert.

Wenn der Compiler das Schlüsselwort asm definiert, indem er die direkte Einbeziehung von Assembler-Code in seine Ausgabe zulässt, und wenn der Computer einen signierten Überlauf zulässt, ist ein signierter Überlauf im Inline-asm perfekt definiert für diesen Compiler und diese Maschine: Es ist das, was der Prozessor als Ergebnis ausgeben wird. Sie sollten immer noch kontrollieren, ob dies zu einer Trap-Darstellung für eine vorzeichenbehaftete Ganzzahl führen kann, aber es ist trotzdem so definiert. Der einzige Fall, der in UB enden würde, wäre, wenn der Compiler sagt, dass eine Darstellung in einer vorzeichenbehafteten Ganzzahl ein undefiniertes Verhalten verursacht. Aber ich kenne keinen, der das tut, und Sie befinden sich bereits im Kontext einer definierten und endlichen Menge von Compilern und Maschinen.

Die separate Kompilierung eines Assemblymoduls und C- und/oder C++-Code wäre für diese Gruppe von Compilern und Maschinen gleich: Ergebnis ist Umsetzung definiert das ist nicht dasselbe wie UB.

Ein weiteres Beispiel für etwas, das explizit in den Standards (sowohl C als auch C++) implementiert ist, ist, ob char Typ signiert ist oder nicht: Wenn Sie nicht wissen, welchen Compiler Sie verwenden, können Sie sich nicht darauf verlassen, aber sobald Sie sich für eine Compiler-Implementierung entscheidendiese Implementierung muss angeben, ob sie signiert oder nicht signiert ist, und das ist sie nicht undefiniertes Verhalten, was bedeutet, dass der Compiler beispielsweise nicht den vollständigen Code durch ein ret ersetzen kann.

1433040cookie-checkGilt undefiniertes Verhalten für asm-Code?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy