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)
mit0xdeadbeaf
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
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
noprefix
/prefix
Richtlinien nur Steuern, ob die Register erfordern eine%
- Präfix(*) (zumindest scheint es so, und das ist der einzige Unterschied die Dokumentation erwähnt). Wert-Literale müssen immer ein$
Präfix im AT&T-syntax, und nicht in Intel-syntax. Also Folgendes funktioniert:Wenn Sie wirklich geneigt zu verwenden, die Intel-syntax inline Assembler innerhalb von C-code kompiliert mit GCC und montiert mit GAS, vergessen Sie nicht, fügen Sie auch die folgenden nach, so dass der assembler kann grok den rest von AT&T-syntax) assembly generiert GCC:
Die Argumentation sehe ich für das Präfix/noprefix Unterscheidung ist, dass für die AT&T-syntax, die
%
Präfix ist nicht wirklich notwendig für die Register der Intel-Architektur, denn Register sind benannt. Aber für die Homogenität kann es da sein, weil einige andere Architekturen (z.B. SPARC) nummeriert eingetragen, in dem Fall die Angabe einer niedrigen Anzahl allein wäre zweideutig, ob eine Speicher-Adresse oder register gemeint war.Hier sind meine Ergebnisse:
noprefix
version emittieren, wird eine "Error: Unerwartetes token:'" when used with
Präfix`