Wie Adresse verwenden Sie Konstanten, die in GCC inline Assembler x86

Den GCC toolchain verwendet AT&T-assembler-syntax standardmäßig, aber die Unterstützung für Intel-syntax ist über die .intel_syntax Richtlinie.

Außerdem, AT&T-und Intel-syntax sind in einer prefix und ein noprefix version, die unterscheiden sich darin, ob oder nicht Sie benötigen, um Präfix registrieren von Namen mit einem % Siegel.

Je nachdem, welche Richtlinien sind vorhanden, das format für die Adresse, die Konstanten Veränderungen.

Betrachten Sie den folgenden C-code

*(int *)0xdeadbeef = 0x1234;

Mit objdump -d wir finden, dass es kompiliert, um die folgende assembler-Anweisung

movl $0x1234,0xdeadbeef

Da es keine Register beteiligt, dies ist die korrekte syntax für beide .att_syntax prefix und .att_syntax noprefix, dh. eingebettet in C-code, dann sehen Sie so

__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");

__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");

Optional können Sie die surround-Adresse ständig mit Klammern, dh.

__asm__("movl $0x1234,(0xdeadbeef)");

funktioniert.

Beim hinzufügen ein Siegel auf einer Ebene-Adresse Konstante, der code wird nicht copile

__asm__("movl $0x1234,$0xdeadbeef"); //won't compile

Wenn rund um diesen Ausdruck mit paranthesis, der compiler sendet falschen code ohne Warnung, ie

__asm__("movl $0x1234,($0xdeadbeef)"); //doesn't warn, but doesn't work!

Diese falsch emittieren die Anweisung

movl $0x1234,0x0

Im Intel-Modus, eine Adresse, die Konstanten werden mit einem Präfix ein Segmentregister sowie der operand Größe und die PTR flag, wenn Mehrdeutigkeit möglich ist. Auf meinem Rechner (Intel dual-core-laptop mit Windows XP und aktuellen MinGW und Cygwin GCC-Versionen), das register ds wird standardmäßig verwendet.

Eckigen Klammern um die Konstanten sind optional. Die Adresse konstant ist, auch korrekt erkannt, wenn der segment-register wird ausgelassen, aber die Klammern sind vorhanden. Das weglassen der register sendet eine Warnung auf meinem system, obwohl.

In prefix - Modus die segment-register werden mit einem Präfix %, aber nur mit eckigen Klammern wird immer noch funktionieren. Dies sind die verschiedenen Möglichkeiten zu generieren die richtige Anweisung:

__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!

Wenn Sie beide Parameter weglassen segment-register und Klammern werden nicht kompiliert werden,

__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); //won't compile

Ich werde markieren Sie diese Frage als community wiki, so, wenn Sie etwas nützliches hinzufügen, fühlen Sie sich frei, dies zu tun.

  • Es ist offensichtlich nicht einfach SO in die toolchain hier, welche version(en) der gcc involviert sind? Haben Sie überprüft die Ausgabe von gcc -S zu validieren, dass das, was zugeführt wird in GNU-da ist, was Sie erwarten?
  • ok, es war mir, wer hat das vermasselt - zumindest teilweise; ersetzen ($0xdeadbeaf) mit 0xdeadbeaf scheint zu funktionieren; ich werde Bearbeiten Sie die Frage nach dem testen dieser...
  • ja, gcc -S liefert die erwarteten Ergebnisse
  • Ich antwortete in Bezug auf das Präfix. Ich sehe nicht, die Warnung, Sie sind immer mit noprefix obwohl. Welche version von gas und GCC ist es?
  • gcc/as-Versionen: cygwin: 3.4.4/2.18.50.20080625, mingw32: 3.4.5,4.3.0.20080305/2.17.50.20060824
Schreibe einen Kommentar