3 votes

yasm movsx, movsxd taille invalide pour l'operande 2

J'essaie d'assembler le code ci-dessous en utilisant yasm. J'ai mis des commentaires 'ici' où yasm rapporte l'erreur "error : invalid size for operand 2". Pourquoi cette erreur se produit-elle ?

segment .data
    a db 25
    b dw 0xffff
    c dd 3456
    d dq -14

segment .bss
    res resq 1

segment .text
    global _start

_start:
    movsx rax, [a] ; here
    movsx rbx, [b] ; here 
    movsxd rcx, [c] ; here
    mov rdx, [d]
    add rcx, rdx
    add rbx, rcx
    add rax, rbx
    mov [res], rax
    ret

1voto

Peter Cordes Points 1375

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).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X