Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何通过操作码或反汇编查找所使用的指令形式?_Assembly_X86 64_Disassembly_Machine Code_Micro Architecture - Fatal编程技术网

Assembly 如何通过操作码或反汇编查找所使用的指令形式?

Assembly 如何通过操作码或反汇编查找所使用的指令形式?,assembly,x86-64,disassembly,machine-code,micro-architecture,Assembly,X86 64,Disassembly,Machine Code,Micro Architecture,像和Agner Fog的指令表这样的网站,甚至Intel自己的手册,都列出了同一指令的各种形式。例如,在Agner的表中添加m、r,或在uops.info中添加m64、r64,或在英特尔手册中添加r/m64、r64 下面是一个我在godbolt上运行的简单示例 __thread int a; void Test() { a+=5; } add是add DWORD PTR fs:0xFFFFFFFFFFFC,0x5。它以操作码64 83 04 25开始 有几种方法可以编写真正的代码,但我

像和Agner Fog的指令表这样的网站,甚至Intel自己的手册,都列出了同一指令的各种形式。例如,在Agner的表中添加m、r,或在uops.info中添加m64、r64,或在英特尔手册中添加r/m64、r64

下面是一个我在godbolt上运行的简单示例

__thread int a;
void Test() {
    a+=5;
}
add是add DWORD PTR fs:0xFFFFFFFFFFFC,0x5。它以操作码64 83 04 25开始

有几种方法可以编写真正的代码,但我想查找这可能需要多少个周期以及其他信息。我怎么才能找到这个指令的参考?我试着输入add并检查我的架构。但我不知道哪个条目是正在使用的指令

现在,在这个特定的例子中,我猜测操作码是,但我不知道使用fs是否有任何惩罚:在地址之前,或者是否有一种方法可以查看操作码,这样我就可以确认我正在查看正确的参考文件,它有一个操作码映射,但是有一点经验的话,大多数时候你都不需要。特别是当您进行反汇编时,您只需检查该助记符的手动输入,并查看它是83/0 add r/m32、imm8中的哪些可能的操作码

显然,它有一个32位操作数大小的dword ptr内存目标,源是一个立即数常量。这排除了r64寄存器源,原因有两个。因此,即使不看机器代码,它也肯定会添加r/m32、imm和imm8或imm32。任何理智的汇编器当然都会选择imm8作为适合有符号8位整数的小常量

一般来说,编码同一条指令的不同方式并不特殊,因此源代码级的汇编/反汇编是可以的,只要您了解什么是寄存器,什么是内存,什么是立即数

但也有一些特殊情况,例如Agner Fog的指南注释,使用短格式编码按1旋转比rol reg、imm8慢,即使imm8=1,因为按1旋转的标志更新特殊情况实际上取决于操作码,而不是立即计数。英特尔的文档显然假设您的汇编程序总是选择按常量1旋转的简短形式。有关遮罩计数的部分仅适用于按cl旋转。我最近没有测试过这个,我不能100%确定我是否正确地记住了OF何时更新,但SPAZO组中的其他标志始终保持不变,但IIRC这就是为什么按12 uop和cl 3 uop旋转速度慢,而Intel上的其他立即计数1 uop旋转速度慢的原因

或者。具体地说,我的意思是——即使在Haswell/Skylake上,adc al,使用不带modrm字节的缩写形式的0也是2 uops,等效的adc eax也是12345。但adc edx,12345是使用非特殊情况的1 uop。然后,您必须检查机器代码,或者知道您的汇编器将如何选择对给定指令进行编码。优化大小

顺便说一句,使用一个非零基址的段会给地址生成(IIRC)增加1个延迟周期,但不会对吞吐量造成重大损失。当然,除非它所属的延迟链上的吞吐量瓶颈…

有一个操作码映射,但有一点经验,大多数情况下你不需要。特别是当您进行反汇编时,您只需检查该助记符的手动输入,并查看它是83/0 add r/m32、imm8中的哪些可能的操作码

显然,它有一个32位操作数大小的dword ptr内存目标,源是一个立即数常量。这排除了r64寄存器源,原因有两个。因此,即使不看机器代码,它也肯定会添加r/m32、imm和imm8或imm32。任何理智的汇编器当然都会选择imm8作为适合有符号8位整数的小常量

一般来说,编码同一条指令的不同方式并不特殊,因此源代码级的汇编/反汇编是可以的,只要您了解什么是寄存器,什么是内存,什么是立即数

但也有一些特殊情况,例如Agner Fog的指南注释,使用短格式编码按1旋转比rol reg、imm8慢,即使imm8=1,因为按1旋转的标志更新特殊情况实际上取决于操作码,而不是立即计数。英特尔的文档显然假设您的汇编程序总是选择按常量1旋转的简短形式。有关遮罩计数的部分仅适用于按cl旋转。我最近没有测试过这个,我不能100%确定我是否正确地记住了OF何时更新,但SPAZO组中的其他标志始终保持不变,但IIRC这就是为什么按12 uop和cl 3 uop旋转速度慢,而Intel上的其他立即计数1 uop旋转速度慢的原因

或者。具体地说,我的意思是——即使在Haswell/Skylake上,adc al,使用不带modrm字节的缩写形式的0也是2 uops,等效的adc eax也是12345。但是adc edx,123 45是使用非特殊情况的1 uop。然后,您必须检查机器代码,或者知道您的汇编器将如何选择对给定指令进行编码。优化大小


顺便说一句,使用一个非零基址的段会给地址生成(IIRC)增加1个延迟周期,但不会对吞吐量造成重大损失。当然,除非它是延迟链的一部分,否则吞吐量瓶颈…

看看英特尔x86 CPU手册,它大约有6000页长,我肯定它就在那里

此外,请检查此站点大小仅搜索64它显示为灰色的操作码,正如您可以看到的,64与添加操作码无关它只是一个FS:[]段覆盖前缀,83是添加操作码

下面是我在IDA反汇编程序中模拟的操作码的工作方式。

在ASM中看起来像这样

看看英特尔x86CPU手册,它大约有6000页长,我肯定它在那里,哈哈

此外,请检查此站点大小仅搜索64它显示为灰色的操作码,正如您可以看到的,64与添加操作码无关它只是一个FS:[]段覆盖前缀,83是添加操作码

下面是我在IDA反汇编程序中模拟的操作码的工作方式。

在ASM中看起来像这样

我不知道为什么,但我有一个坏习惯,认为r=立即。好像R代表操作数。这非常有帮助,谢谢。我不知道为什么,但我有一个坏习惯,认为r=立即。好像R代表操作数。这很有帮助,谢谢。我得说这和另一个答案一样有帮助。Stackoverflow请允许我接受两个答案。我不建议使用超大的all-in-1 PDF,因为它太大了。第2卷作为其自己的PDF是可用的,并有一个索引。有链接。但是,是的,英特尔的第二卷手册是在线HTML网站用来提取insn集合引用的工具,但是原始PDF有关于如何读取条目的介绍材料,以及包含操作码映射的附录。通常你不需要这些,只需要指令引用,这就是为什么scrape不包括它们,但是当你这样做的时候,英特尔有它们。我得说这和另一个答案一样有用。Stackoverflow请允许我接受两个答案。我不建议使用超大的all-in-1 PDF,因为它太大了。第2卷作为其自己的PDF是可用的,并有一个索引。有链接。但是,是的,英特尔的第二卷手册是在线HTML网站用来提取insn集合引用的工具,但是原始PDF有关于如何读取条目的介绍材料,以及包含操作码映射的附录。通常情况下,您不需要这些,只需要指令引用,这就是为什么scrape不包含它们的原因,但当您这样做时,Intel会包含它们。