英特尔手册说mov
有两个变体,涉及内存和32位直接操作数:
MOV r/m32, imm32
MOV r/m64, imm32
第一个复制4个字节,第二个复制8个字节,取给定的32位直接位并将其符号扩展为64位。
在为MASM64编写汇编代码时,如何指定您想要的代码?
@ecm上面的评论给出了答案:
mov qword ptr [rsp+08h], 0 ; selects MOV r/m64, imm32
mov dword ptr [rsp+08h], 0 ; selects MOV r/m32, imm32
像往常一样重写内存操作数的大小
mov qword ptr [rdx], 123
add byte ptr [rcx], 1
movzx eax, word ptr [r8]
shl dword ptr [r9], cl
通常考虑设置内存操作数的大小,而不是直接的,因为这总是有效的,即使在movzx
或shl dword ptr [mem], 4
中,操作数不必是相同的大小(移位计数是一个字节,可以是CL)。
你没有重写任何关于immediate的内容;您仍然希望add qword ptr [mem], 4
使用sign_extended_imm8编码,将编码留给汇编器。(只有mov
和test
缺少符号扩展的字节形式,而不是来自原始8086的ALU指令。)
即使像NASM这样的汇编器接受add [rcx], word 0x0001
,我也不会这样写。
特别是在NASM中,您可以强制它使用add qword [rdi], strict qword 123
的4字节直接,这将在机器代码中使用其他东西可以重写的4字节直接。在immediate上使用dword
而不使用strict
似乎是错误的思考方式。
特别是启用了NASM的默认优化,所以你不需要像mov rax, dword -1
这样的东西来避免imm64编码,或者add dword [rdi], byte 1
来避免imm32编码。(对于nasm -O0
,如果您不建议使用非严格提示的较小编码,则将选择更长的编码,因此可以将大小与设置操作数-size分开进行。)
(NASM要求strict qword 123
对应add qword [rdi], strict qword 123
,而不是strict dword
,匹配操作数大小而不是直接宽度,这有点混乱。在我看来,它拒绝add qword [rdi], strict dword 123
是一个bug。可能该语法是在x86-64存在之前设计的,并且/或者在如何将其扩展到除字节之外的非全宽立即符的情况下犯了设计错误。