如何通过操作码或反汇编查找使用的指令形式?
How to look up what form of an instruction is used, by opcode or disassembly?
https://uops.info/ and Agner Fog's instruction tables, and even Intel's own manuals, list various forms of the same instruction. For example add m, r
(in Agner's tables) or add (m64, r64)
on uops.info, or ADD r/m64, r64
in Intel's manual (https://www.felixcloutier.com/x86/add).
等网站
这是我 运行 在 godbolt
上的一个简单示例
__thread int a;
void Test() {
a+=5;
}
添加的是add DWORD PTR fs:0xfffffffffffffffc,0x5
。它以操作码 64 83 04 25
.
开头
有几种方法可以编写我的真实代码,但我想查找这可能需要多少个周期以及其他信息。我到底如何找到对该指令的引用?我尝试 https://uops.info/table.html 输入“添加”并检查我的架构。但我不知道哪个条目是正在使用的指令。
目前在这种特定情况下,我猜测操作码是 Add m64, r64 但我不知道在地址前使用 fs:
是否有任何惩罚,或者是否有办法查看操作码所以我可以确认我正在查看正确的参考资料
http://ref.x86asm.net/coder64.html has an opcode map, but with a bit of experience you won't need one most of the time. Especially when you have disassembly, you can just check the manual entry for that mnemonic (https://www.felixcloutier.com/x86/add), 看看它是哪个可能的操作码 (83 /0 add r/m32, imm8
).
显然,它有一个 32 位操作数大小 (dword ptr
) 的内存目标,而源是一个立即数(数字常量)。由于 2 个不同的原因,这排除了 , r64
注册源。因此,即使不查看机器代码,也肯定是 add r/m32, imm
带有 imm8 或 imm32。任何理智的汇编程序当然会选择 imm8 作为适合有符号 8 位整数的小常量。
一般同一条指令的不同编码方式并无特殊,所以源码级的汇编/反汇编就可以了,只要明白什么是寄存器,什么是内存就可以了, 什么是立即数。
但也有一些特殊情况,例如Agner Fog 的指南指出,使用短格式编码旋转 1 比 rol reg, imm8
慢,即使 imm8=1,因为旋转 1 的标志更新特殊情况实际上取决于操作码,而不是立即计数。 (英特尔的文档显然假定您的汇编程序将始终选择按常数 1 旋转的缩写形式。关于“屏蔽计数”的部分可能仅适用于按 cl
旋转。https://www.felixcloutier.com/x86/rcl:rcr:rol:ror#flags-affected。我还没有测试过最近,我不能 100% 确定我在更新 OF 时是否记得正确(但 SPAZO 组中的其他标志始终保持不变),但 IIRC 这就是为什么旋转 1(2 微指令)和 cl(3 微指令)是慢,相对于英特尔上的其他立即计数(1 uop)旋转)。
或 https://github.com/travisdowns/uarch-bench/wiki/Intel-Performance-Quirks. Specifically I mean - 即使在 Haswell / Skylake 上,adc al,0
(使用没有 modrm 字节的短格式)是 2 微指令,等效的 adc eax, 12345
也是如此。但是 adc edx, 12345
在非特殊情况下是 1 uop。)然后您必须检查机器代码,或者知道您的汇编器将如何选择对给定指令进行编码。 (尺寸优化)。
顺便说一句,使用具有非零基数的段会增加 1 个地址生成周期的延迟,IIRC,但这并不是显着的吞吐量损失。 (当然,除非它是延迟链的一部分的吞吐量瓶颈......)
查看 Intel x86 手册 CPU 大约有 6000 页,我确定它在那里,哈哈
https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf
也可以查看这个网站 http://ref.x86asm.net/coder64.html size 只需搜索 64(操作码显示为灰色),如您所见,64 与 ADD 操作码无关,它只是一个 FS:[]段覆盖前缀,83 是 ADD Opcode
这里是你的操作码是如何工作的,就像我在 IDA 反汇编程序中模拟的那样。
在 ASM 中看起来像这样
https://uops.info/ and Agner Fog's instruction tables, and even Intel's own manuals, list various forms of the same instruction. For example add m, r
(in Agner's tables) or add (m64, r64)
on uops.info, or ADD r/m64, r64
in Intel's manual (https://www.felixcloutier.com/x86/add).
这是我 运行 在 godbolt
上的一个简单示例__thread int a;
void Test() {
a+=5;
}
添加的是add DWORD PTR fs:0xfffffffffffffffc,0x5
。它以操作码 64 83 04 25
.
有几种方法可以编写我的真实代码,但我想查找这可能需要多少个周期以及其他信息。我到底如何找到对该指令的引用?我尝试 https://uops.info/table.html 输入“添加”并检查我的架构。但我不知道哪个条目是正在使用的指令。
目前在这种特定情况下,我猜测操作码是 Add m64, r64 但我不知道在地址前使用 fs:
是否有任何惩罚,或者是否有办法查看操作码所以我可以确认我正在查看正确的参考资料
http://ref.x86asm.net/coder64.html has an opcode map, but with a bit of experience you won't need one most of the time. Especially when you have disassembly, you can just check the manual entry for that mnemonic (https://www.felixcloutier.com/x86/add), 看看它是哪个可能的操作码 (83 /0 add r/m32, imm8
).
显然,它有一个 32 位操作数大小 (dword ptr
) 的内存目标,而源是一个立即数(数字常量)。由于 2 个不同的原因,这排除了 , r64
注册源。因此,即使不查看机器代码,也肯定是 add r/m32, imm
带有 imm8 或 imm32。任何理智的汇编程序当然会选择 imm8 作为适合有符号 8 位整数的小常量。
一般同一条指令的不同编码方式并无特殊,所以源码级的汇编/反汇编就可以了,只要明白什么是寄存器,什么是内存就可以了, 什么是立即数。
但也有一些特殊情况,例如Agner Fog 的指南指出,使用短格式编码旋转 1 比 rol reg, imm8
慢,即使 imm8=1,因为旋转 1 的标志更新特殊情况实际上取决于操作码,而不是立即计数。 (英特尔的文档显然假定您的汇编程序将始终选择按常数 1 旋转的缩写形式。关于“屏蔽计数”的部分可能仅适用于按 cl
旋转。https://www.felixcloutier.com/x86/rcl:rcr:rol:ror#flags-affected。我还没有测试过最近,我不能 100% 确定我在更新 OF 时是否记得正确(但 SPAZO 组中的其他标志始终保持不变),但 IIRC 这就是为什么旋转 1(2 微指令)和 cl(3 微指令)是慢,相对于英特尔上的其他立即计数(1 uop)旋转)。
或 https://github.com/travisdowns/uarch-bench/wiki/Intel-Performance-Quirks. Specifically I mean adc al,0
(使用没有 modrm 字节的短格式)是 2 微指令,等效的 adc eax, 12345
也是如此。但是 adc edx, 12345
在非特殊情况下是 1 uop。)然后您必须检查机器代码,或者知道您的汇编器将如何选择对给定指令进行编码。 (尺寸优化)。
顺便说一句,使用具有非零基数的段会增加 1 个地址生成周期的延迟,IIRC,但这并不是显着的吞吐量损失。 (当然,除非它是延迟链的一部分的吞吐量瓶颈......)
查看 Intel x86 手册 CPU 大约有 6000 页,我确定它在那里,哈哈 https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf
也可以查看这个网站 http://ref.x86asm.net/coder64.html size 只需搜索 64(操作码显示为灰色),如您所见,64 与 ADD 操作码无关,它只是一个 FS:[]段覆盖前缀,83 是 ADD Opcode
这里是你的操作码是如何工作的,就像我在 IDA 反汇编程序中模拟的那样。
在 ASM 中看起来像这样