Die GCC-Toolchain verwendet AT & T-Assembler-Syntax standardmäßig, aber Unterstützung für Intel-Syntax ist über die .intel_syntax
Direktive verfügbar.So verwenden Sie Adresskonstanten in GCC x86 Inline-Assembly
Zusätzlich beide AT & T und Intel-Syntax sind in einer prefix
und einer noprefix
Version, die sich darin unterscheiden, ob sie benötigen Namen mit einem %
Sigill Präfix registrieren.
Je nachdem, welche Direktiven vorhanden sind, ändert sich das Format für Adresskonstanten.
Betrachten wir die folgende C-Code
*(int *)0xdeadbeef = 0x1234;
objdump -d
Verwendung finden wir, dass es die folgenden Assemblerbefehl kompiliert
movl $0x1234,0xdeadbeef
Da es keine Register beteiligt sind, ist dies die richtige Syntax für beide .att_syntax prefix
und .att_syntax noprefix
, dh. in C-Code eingebettet, sehen sie so aus
__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");
__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");
Sie können die Adresskonstante optional mit Klammern umgeben, dh.
__asm__("movl $0x1234,(0xdeadbeef)");
wird auch funktionieren.
Wenn ein sigil auf eine Ebene Adreßkonstante hinzufügen, wird der Code Copile scheitern
__asm__("movl $0x1234,$0xdeadbeef"); // won't compile
Wenn man diesen Ausdruck mit geklam- mert umgibt, wobei der Compiler falschen Code ohne Warnung aussenden, dh
__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!
Dies wird fälschlicherweise die Anweisung emittieren
movl $0x1234,0x0
In Intel m ode muss einer Adreßkonstante ein Segmentregister sowie die Operandengröße und das Flag PTR
vorangestellt werden, wenn Mehrdeutigkeiten möglich sind. Auf meinem Computer (ein Intel Dual-Core-Laptop mit Windows XP und aktuellen Versionen von MinGW und Cygwin GCC) wird standardmäßig das Register ds
verwendet.
Eckige Klammern um die Konstante sind optional. Die Adresskonstante wird auch korrekt erkannt, wenn das Segmentregister weggelassen wird, aber die Klammern vorhanden sind. Das Auslassen des Registers gibt jedoch eine Warnung an mein System aus.
Im prefix
Modus muss dem Segmentregister das Präfix %
vorangestellt werden, aber nur die Verwendung von Klammern funktioniert weiterhin. Dies sind die verschiedenen Möglichkeiten, um die richtige Anweisung zu generieren:
__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!
__asm__(".intel_syntax prefix");
__asm__("mov DWORD PTR %ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR %ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!
Weglassen beider Segmentregister und Klammern werden
__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile
nicht kompilieren ich diese Frage markieren würde als Community Wiki, also wenn Sie Haben Sie etwas Nützliches hinzuzufügen, fühlen Sie sich frei, dies zu tun.nur
Es ist natürlich nicht * nur * AS in der Werkzeugkette hier; Welche Version (en) von gcc sind beteiligt? Haben Sie die Ausgabe von gcc-S überprüft, um zu bestätigen, dass das, was Sie erwarten, in GNU eingespeist wird? –
ok, ich war es, der versaut hat - zumindest teilweise; Ersetzen von '($ 0xdeadbeaf)' mit '0xdeadbeaf' scheint zu funktionieren; Ich werde die Frage nach dem Testen dieser ... bearbeiten – Christoph
@Charles: ja, 'gcc -S' ergibt die erwarteten Ergebnisse – Christoph