【发布时间】:2020-02-21 10:53:33
【问题描述】:
考虑以下用 x86-assembly 编写的函数
foo:
rep
nop
ret
使用 NASM 组装代码并用gdb 反汇编我们有:
(gdb) disas foo
Dump of assembler code for function foo:
0x0000000000000610 <+0>: pause ;pause ????
0x0000000000000612 <+2>: ret
0x0000000000000613 <+3>: nop WORD PTR cs:[rax+rax*1+0x0]
0x000000000000061d <+13>: nop DWORD PTR [rax]
End of assembler dump.
它使用了原始程序集中没有出现的pause 指令。为什么它会这样工作?这是 NASM 有意记录的行为吗?所以如果一些早期的 x86 cpus 没有pause,我们可以只使用rep nop?
【问题讨论】:
-
是的,Intel 选择了
rep nop作为pause的编码,所以它可以在不检查CPU 支持的情况下使用;较旧的 CPU 将其解码为nop。阅读手册暂停。 felixcloutier.com/x86/pause -
@PeterCordes 手动输入
rep甚至没有指定它与nop一起使用。正是可以在INS、OUTS、MOVS、LODS和STOS指令中添加REP前缀,在CMPS和SCAS指令中可以添加REPE、REPNE、REPZ和REPNZ前缀。 所以这就是我将rep nop视为 NASM 的一个功能的原因。 -
@PeterCordes 此外,有人指出 F3H 前缀为以下指令定义,其余未定义:F3H 为字符串和输入/输出指令的 REP/REPE/REPZ。 F3H 是 POPCNT、LZCNT 和 ADOX 的强制前缀。没有提到
nop。 -
有人删除了我的第二条评论,IDK 为什么。我说当我用谷歌搜索
rep nop pause时,链接的副本是第一个命中,它充分说明了这种情况。无论如何,rep不是nop的有效前缀,这就是为什么它被不将其识别为另一条指令编码的一部分的 CPU 忽略。以F3作为强制前缀的指令列表并不详尽;它缺少tzcnt和pause,并且还用作 HLE 的xreleaseprefix(同样是因为无法识别它的 CPU 会忽略它)。 -
你告诉 NASM 输出一个 REP 前缀字节,即值为 0xF3 的字节,后跟一个 NOP 操作码字节,即值为 0x90 的字节。您告诉 NASM 输出字节序列
F3 90,这就是它所做的。 NASM 在任何时候都没有考虑这是否是一个有效的指令序列。它没有将repnop从无效指令序列更改为有效指令序列。它只是碰巧是一个,无论你是否愿意。
标签: assembly x86 gdb x86-64 nasm