assembly - 汇编器是否应该不满足我对 ret imm16 的请求?

标签 assembly x86 masm machine-code

据我了解,ret操作数为零的 imm16 (C2 imm16) 指令与无操作数 ret (C3) 没有什么不同它的作用。但是,当我显式给出汇编器 ret 0 时,它是否应该将其编码为 ret imm16 指令,因为我显式提供了操作数?

如果我使用 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

然后用反汇编器打开可执行文件,我看到为ret编码的指令是C3:

  00401000: 33 C0              xor         eax,eax
  00401002: C3                 ret

我可以通过硬编码字节来手动执行 C2 指令:

.386
.MODEL FLAT, STDCALL
.CODE
    stdMain PROC
        xor eax, eax
        db 0c2h, 0, 0 ; ret imm16=0
    stdMain ENDP
END

现在我在反汇编输出中看到了 C2 指令:

  00401000: 33 C0              xor         eax,eax
  00401002: C2 00 00           ret         0

汇编器这样“优化”是否正确?

最佳答案

您不需要 3 个单独的 db 行;一个带有 3 个操作数的 db 是等效的:

db  0c2h, 0, 0     ; ret  imm16=0

Is it correct for an assembler to 'optimize' like that?

一般来说,可以接受的是,汇编器可以使用具有完全相同的架构效果和相同助记符的最短指令编码。

例如NASM 会将 mov rax, 123 优化为 mov eax, 123,尽管其他一些(如 YASM 或 GAS)默认情况下不会这样做。 (GAS 有一个 -Os 选项,GCC 默认情况下不会传递给它)。此外,NASM 会将 lea eax, [rax*2 + 123] 优化为 lea eax, [rax + rax + 123],除非您使用 [NOSPLIT 123 + rax *2]spend more code size on a disp32 for the benefit of avoiding a slower 3 component LEA .

NASM 不会将 xor rax,rax 优化为 xor eax,eax;我想它不会使用 XOR 检查归零惯用法(两个规则相同)。

NASM 有一个 -O0 选项来不优化,但这非常糟糕,例如mov rax, -1 是 10 个字节 (imm64),而不是 7 (sign_extended_imm32),add ecx, 123 使用 imm32,jmp foo即使标签在附近,也会使用 rel32 而不是 rel8。 (这曾经是旧 NASM 版本中的默认设置。 https://nasm.us/doc/nasmdoc2.html#section-2.1.24 )


MSVC 在 asm 列表中总是将 ret 发出为 ret 0,因此,如果您曾经汇编过这样的代码,您肯定希望汇编器将其优化为正常ret显然,MS 认为这种优化是正常的依赖。

当你想要 ret 时,编写或发出 ret 0 似乎是一个愚蠢的设计,但这就是 MSVC 所做的。 (并不是说 MSVC 通过将 asm 提供给 MASM 来工作;除非您要求 asm 列表,否则它会直接发出机器代码。)

NASM 确实会将 ret 0 汇编为 ret imm16=0,因此您可能更喜欢使用它。我知道只要我有选择,我都会选择 NASM 而不是 MASM;简单的语法和关于内存操作数的魔法规则意味着操作数的大小,有时 [] 没有任何意义......

关于assembly - 汇编器是否应该不满足我对 ret imm16 的请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61996121/

相关文章:

c++ - 可以捕获写入地址(x86 - linux)

x86 - 如何制作汇编程序?

assembly - x86 程序集 - $ 未显示正确的地址

visual-studio - masm 指令选项序言 :none has no effect

delphi - 如何在内联汇编中访问delphi开放数组参数

c - 为什么使用返回值时0会被移入堆栈?

c - 测试状态位

assembly - .data MASM 指令的内联汇编等效项

在 Linux/x86-84 上传递大对象的 C++ 调用约定

assembly - “PUSH”指令的操作可以用其他指令执行吗?