汇编程序是否应该不满足我对 ret imm16 的请求?
Should the assembler not honor my request for ret imm16?
我明白 ret
imm16
(C2 imm16
) 操作数为零的指令与无操作数的 ret
(C3
) 没有什么不同在其效果中。但是,当我明确给出 assembler ret 0
时,由于我明确提供了操作数,它不应该将其编码为 ret imm16
指令吗?
如果我 assemble 下面的代码与 VS2019 附带的 ml.exe 版本和命令 ml file.asm /link /SUBSYSTEM:CONSOLE /ENTRY:stdMain
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
ret 0
stdMain ENDP
END
然后用 disassembler 打开可执行文件,我看到为 ret
编码的指令是 C3
:
00401000: 33 C0 xor eax,eax
00401002: C3 ret
我可以通过硬编码字节来手动执行 C2
指令:
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
db 0c2h, 00, 00
stdMain ENDP
END
现在我在 disassembled 输出中看到 C2
指令:
00401000: 33 C0 xor eax,eax
00401002: C2 00 00 ret 0
这样 assembler 到 'optimize' 是正确的吗?
您不需要 3 行单独的 db
行;一个有 3 个操作数的 db
等价于:
db 0c2h, 0, 0 ; ret imm16=0
Is it correct for an assembler to 'optimize' like that?
一般来说是的,assemblers 可以使用具有完全相同架构效果和相同助记符的指令的最短编码。
例如NASM 会将 xor rax,rax
优化为 xor eax,eax
,即使其他一些(如 YASM 或 GAS)不会。另外 NASM 会优化 lea eax, [rax*2 + 123]
到 lea eax, [rax + rax + 123]
除非你使用 [NOSPLIT 123 + rax*2]
到 .
MSVC 始终将 ret
作为 ret 0
发出ret
. 显然这个优化是 MS 认为正常依赖的优化。
当你想要 ret
时编写或发出 ret 0
似乎是一个愚蠢的设计,但这就是 MSVC 所做的。 (并不是说 MSVC 通过将 asm 提供给 MASM 来工作;它直接发出机器代码,除非您要求 asm 列表。)
NASM 确实发生在 assemble ret 0
到 ret imm16=0
之间,因此您可能更喜欢使用它。我知道只要有选择,我就会选择 NASM 而不是 MASM;简单的语法和不受关于内存操作数的神奇规则暗示操作数大小,有时 []
没有任何意义...
我明白 ret
imm16
(C2 imm16
) 操作数为零的指令与无操作数的 ret
(C3
) 没有什么不同在其效果中。但是,当我明确给出 assembler ret 0
时,由于我明确提供了操作数,它不应该将其编码为 ret imm16
指令吗?
如果我 assemble 下面的代码与 VS2019 附带的 ml.exe 版本和命令 ml file.asm /link /SUBSYSTEM:CONSOLE /ENTRY:stdMain
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
ret 0
stdMain ENDP
END
然后用 disassembler 打开可执行文件,我看到为 ret
编码的指令是 C3
:
00401000: 33 C0 xor eax,eax
00401002: C3 ret
我可以通过硬编码字节来手动执行 C2
指令:
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
db 0c2h, 00, 00
stdMain ENDP
END
现在我在 disassembled 输出中看到 C2
指令:
00401000: 33 C0 xor eax,eax
00401002: C2 00 00 ret 0
这样 assembler 到 'optimize' 是正确的吗?
您不需要 3 行单独的 db
行;一个有 3 个操作数的 db
等价于:
db 0c2h, 0, 0 ; ret imm16=0
Is it correct for an assembler to 'optimize' like that?
一般来说是的,assemblers 可以使用具有完全相同架构效果和相同助记符的指令的最短编码。
例如NASM 会将 xor rax,rax
优化为 xor eax,eax
,即使其他一些(如 YASM 或 GAS)不会。另外 NASM 会优化 lea eax, [rax*2 + 123]
到 lea eax, [rax + rax + 123]
除非你使用 [NOSPLIT 123 + rax*2]
到
MSVC 始终将 ret
作为 ret 0
发出ret
. 显然这个优化是 MS 认为正常依赖的优化。
当你想要 ret
时编写或发出 ret 0
似乎是一个愚蠢的设计,但这就是 MSVC 所做的。 (并不是说 MSVC 通过将 asm 提供给 MASM 来工作;它直接发出机器代码,除非您要求 asm 列表。)
NASM 确实发生在 assemble ret 0
到 ret imm16=0
之间,因此您可能更喜欢使用它。我知道只要有选择,我就会选择 NASM 而不是 MASM;简单的语法和不受关于内存操作数的神奇规则暗示操作数大小,有时 []
没有任何意义...