Pour la plupart des instructions, la largeur de l'opérande du registre implique la largeur de l'opérande de la mémoire, car les deux opérandes doivent avoir la même taille, par ex. mov rdx, [d]
implique mov rdx, qword [d]
parce que vous avez utilisé un registre de 64 bits.
Mais la même movsx
/ movzx
sont utilisés pour les codes d'opération source d'octet et source de mot, ce qui rend la situation ambiguë, sauf si la source est un registre (comme dans le cas de movzx eax, cl
).
movsx
/ movzx
avec une source de mémoire ont toujours besoin de la largeur de l'opérande de mémoire spécifiée explicitement.
En movsxd
est censé impliquer une taille de source de 32 bits. movsxd rcx, [c]
s'assemble avec NASM, mais apparemment pas avec YASM. YASM vous demande d'écrire dword
même s'il n'accepte pas byte
, word
ou qword
là, et il n'accepte pas movsx rcx, dword [c]
soit (c'est-à-dire qu'elle nécessite le movsxd
mnémonique pour les opérandes source 32 bits).
Dans NASM, movsx rcx, dword [c]
s'assemble pour movsxd
mais movsxd rcx, word [c]
est toujours rejeté, c'est-à-dire que dans le NASM, le simple movsx
est entièrement flexible, mais movsxd
est toujours rigide. Je recommande toujours d'utiliser dword
pour rendre explicite la largeur de la charge, au profit des humains.
movsx rax, byte [a]
movsx rbx, word [b]
movsxd rcx, dword [c]
Notez que la "taille de l'opérande" de l'instruction (déterminée par le préfixe de taille d'opérande pour qu'elle soit de 16 bits, ou par REX.W=1 pour qu'elle soit de 64 bits) est la largeur de destination pour movsx
/ movzx
. Des tailles de source différentes utilisent des opcodes différents.
Au cas où ce ne serait pas évident, il n'y a pas de movzxd
porque 32 bits mov
s'étend déjà implicitement à 64 bits. . movsxd eax, ecx
peut être codé, mais n'est pas recommandé (utilisez la fonction mov
à la place).
Dans la syntaxe AT&T, les différentes largeurs de source ont des mnémoniques différentes, comme par exemple movsb
o movsw
. La taille de destination est un suffixe comme d'habitude, vous pouvez donc écrire movsbq (%rsi), %rax
d'être explicite ou movsb (%rsi), %rax
pour permettre à l'assembleur de déduire la taille de la destination à partir de %rax
.
D'autres éléments concernant votre code source :
Les NASM/YASM vous permettent d'utiliser les segment
au lieu du mot-clé section
mais en réalité, vous donnez des noms de sections ELF, et non des noms de segments exécutables. De plus, vous pouvez mettre des données en lecture seule dans le fichier section .rodata
(qui est lié comme faisant partie du segment de texte). Quelle est la différence entre section et segment dans le format de fichier ELF ? .
Vous ne pouvez pas ret
de _start
. Ce n'est pas une fonction, c'est votre point d'entrée ELF. La première chose sur la pile est argc
n'est pas une adresse de retour valide. Utilisez ceci pour quitter proprement :
xor edi,edi
mov eax, 231
syscall ; sys_exit_group(0)
Voir le x86 pour des liens vers des guides plus utiles (et des conseils de débogage en bas de page).