it-swarm.com.de

Was ist eine Callq-Anweisung?

Ich habe etwas gnu-Assembler-Code für die x86_64-Architektur, die von einem Tool generiert wurde, und es gibt folgende Anweisungen:

movq %rsp, %rbp  
leaq str(%rip), %rdi
callq puts
movl $0, %eax

Ich kann keine tatsächliche Dokumentation in der Anweisung "callq" finden.

Ich habe mir http://support.AMD.com/TechDocs/24594.pdf angesehen. Dies ist "AMD64 Architecture Programmer's Manual Volume 3: Allzweck- und Systemanweisungen", aber es werden nur nahe und ferne Anweisungen von CALL beschrieben.

Ich habe mir die Dokumentation für gnu assembler https://sourceware.org/binutils/docs/as/index.html angeschaut, konnte aber den Abschnitt nicht finden, der die unterstützten Anweisungen enthält.

Ich verstehe, dass es sich um einen Aufruf einer Funktion handelt, aber ich würde gerne die Details erfahren. Wo finde ich sie?

14
user10607

Es ist nur call . Verwenden Sie die Zerlegung der Intel-Syntax, wenn Sie Anweisungen in den Intel/AMD-Handbüchern nachschlagen möchten.

Das Operandengrößen-Suffix q ist technisch anwendbar (es sendet eine 64-Bit-Rückgabeadresse und behandelt RIP als 64-Bit-Register), aber es gibt keine Möglichkeit, es mit Befehlspräfixen zu überschreiben. Das heißt, calll und callw sind im 64-Bit-Modus nicht codierbar. Daher ist es nur ärgerlich, dass einige AT & T-Syntax-Tools es als callq anstelle von call anzeigen. Dies gilt natürlich auch für retq.

Verschiedene Tools unterscheiden sich im 32-Bit-Modus. ( Godbolt )

  • gcc -S: immer callret. Nett.
  • clang -S: callq/retq und calll/retl. Zumindest ist es ständig nervig.
  • objdump -d: callq/retq (explizites 64-Bit) und call/ret (implizit für 32-Bit). Inkonsistent und irgendwie dumm, weil 64-Bit keine Wahl der Operandengröße hat, 32-Bit jedoch. (Keine nützlich -Option, jedoch: callw schneidet EIP auf 16 Bits ab.)

    Andererseits ist die Standardoperandengröße (ohne Präfix REX.W) für most-Anweisungen im 64-Bit-Modus immer noch 32. Aber add $1, (%rdi) benötigt ein Suffix für die Operandengröße. Der Assembler wählt nicht 32-Bit für Sie aus, wenn nichts darauf hindeutet. OTOH, Push ist implizit pushq, auch wenn pushw $1 und pushq $1 beide im 64-Bit-Modus codierbar sind ( und in der Praxis verwendbar ).


Aus Intels Anweisungshandbuch (oben verlinkt):

Bei einem absoluten Annäherungsaufruf wird ein absoluter Offset indirekt in einem Universalregister oder einem Speicherplatz (r/m16, r/m32 oder r/m64) angegeben. Das Operandengrößenattribut bestimmt die Größe des Zieloperanden (16, 32 oder 64 Bit). _/Im 64-Bit-Modus wird die Operandengröße für Near-Call (und alle Near-Branches) auf 64 Bit gesetzt.

für rel32 ... Wie bei absoluten Offsets bestimmt das Attribut Operandengröße die Größe des Zieloperanden (16, 32 oder 64 Bit). Im 64-Bit-Modus ist der Zieloperand immer 64-Bit, da die Operandengröße für nahe Verzweigungen auf 64-Bit gezwungen wird.

Im 32-Bit-Modus können Sie ein 16-Bit call rel16 codieren, das EIP auf 16 Bit abschneidet, oder ein call r/m16, das eine absolute 16-Bit-Adresse verwendet. Wie jedoch im Handbuch heißt, ist die Operandengröße im 64-Bit-Modus festgelegt.

22
Peter Cordes

callq bezieht sich auf einen verschiebbaren Aufruf in gemeinsam genutzten Bibliotheken/dynamischen Bibliotheken. Die Idee ist Push 0, dann Push das Symbol von, um zu suchen, dann eine Funktion aufzurufen. In der verschiebbaren Tabelle des Programms ersetzt es den Aufruf der tatsächlichen Position der Funktion beim ersten Aufruf der Funktion. Nachfolgende Aufrufe beziehen sich auf die Umsetztabelle, die zur Laufzeit erstellt wurde. 

0
Shawn Miller