web-dev-qa-db-fra.com

Qu'est-ce que l'instruction callq?

J'ai un code assembleur GNU pour l'architecture x86_64 généré par un outil et il y a ces instructions:

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

Je ne trouve pas de documentation sur l’instruction "callq".

J'ai consulté http://support.AMD.com/TechDocs/24594.pdf qui correspond au "Manuel du programmeur d'architecture AMD64, volume 3: instructions générales et instructions système", mais ne décrit que les instructions CALL near et far.

J'ai consulté la documentation de gnu assembler https://sourceware.org/binutils/docs/as/index.html mais je n'ai pas trouvé la section détaillant les instructions prises en charge.

Je comprends que c’est un appel à une fonction, mais j’aimerais connaître les détails. Où puis-je les trouver?

14
user10607

C'est juste call . Utilisez le désassemblage de la syntaxe Intel si vous souhaitez pouvoir rechercher des instructions dans les manuels Intel/AMD.

Le suffixe q de taille opérande s'applique techniquement (il envoie une adresse de retour 64 bits et traite le protocole RIP comme un registre 64 bits), mais il n’ya aucun moyen de le remplacer par des préfixes d’instruction. i.e. calll et callw ne sont pas encodables en mode 64 bits, il est donc gênant que certains outils de syntaxe de AT & T l’affiche sous la forme callq au lieu de call. Ceci s'applique bien sûr à retq également.

Différents outils sont différents en mode 32 vs. 64 bits. ( Godbolt )

  • gcc -S: toujours callret. Agréable.
  • clang -S: callq/retq et calll/retl. Au moins, c'est toujours agaçant.
  • objdump -d: callq/retq (64 bits explicite) et call/ret (implicite pour 32 bits). Incohérent et un peu stupide parce que 64 bits n'a pas le choix de taille d'opérande, mais 32 bits. (Pas un choix utile, cependant: callw tronque EIP à 16 bits.)

    Par contre, la taille d'opérande par défaut (sans préfixe REX.W) pour les instructions la plupart en mode 64 bits est toujours égale à 32. Mais add $1, (%rdi) a besoin d'un suffixe de taille opérande; l'assembleur ne choisira pas 32 bits pour vous si rien n'implique un. OTOH, Push est implicitement pushq, même si pushw $1 et pushq $1 sont codables ( et utilisables en pratique ) en mode 64 bits.


D'après le manuel de référence du jeu d'instructions d'Intel (lien ci-dessus):

Pour un absolu de quasi-appel, un décalage absolu est spécifié indirectement dans un registre à usage général ou un emplacement de mémoire (r/m16, r/m32 ou r/m64). L'attribut opérand-size détermine la taille de l'opérande cible (16, 32 ou 64 bits). _/En mode 64 bits, la taille de l'opérande pour le proche appel (et toutes les branches proches) est forcée à 64 bits.

pour rel32 ... Comme pour les décalages absolus, l'attribut opérand-size détermine la taille de l'opérande cible (16, 32 ou 64 bits). En mode 64 bits, l'opérande cible sera toujours 64 bits car la taille de l'opérande est forcée à 64 bits pour les branches proches.

En mode 32 bits, vous pouvez coder un call rel16 de 16 bits qui tronque EIP en 16 bits, ou un call r/m16 qui utilise une adresse absolue de 16 bits. Mais comme le dit le manuel, la taille de l'opérande est fixée en mode 64 bits.

22
Peter Cordes

callq fait référence à un appel pouvant être déplacé dans des bibliothèques partagées/dynamiques. L'idée est Push 0, puis appuyez sur le symbole de pour rechercher puis appeler une fonction afin de la rechercher lors du premier appel. Dans la table déplaçable du programme, il remplace l'appel à l'emplacement actuel de la fonction lors du premier appel de la fonction. Les appels suivants font référence à la table de relocalisation créée au moment de l'exécution. 

0
Shawn Miller