Abh*_*Deb 1 binary assembly x86-64 instruction-encoding
我使用以下代码创建了一个简单的 C++ 源文件:
int main() {
int a = 1;
int b = 2;
if(a < b) {
return 1;
}
else if(a > b) {
return 2;
}
else {
return 3;
}
}
Run Code Online (Sandbox Code Playgroud)
我使用objdump命令来获取上述源代码的汇编代码。
该行int b = 2;已转换为mov DWORD PTR [rbp-0x4], 0x2.
其对应的机器码为C7 45 FC 02 00 00 00(十六进制格式)。
我想知道如何将汇编代码转换为二进制代码。我浏览了 x86-64 的英特尔参考手册,但我无法理解它,因为我是低级编程的新手。
您应该阅读英特尔手册,它解释了如何做到这一点。如需更简单的参考,请阅读此内容。x86 指令的编码方式相当简单,但可能性的数量可能有点令人难以承受。
简而言之,x86 指令由以下部分组成,其中除了操作码之外的所有部分都可能丢失:
prefix opcode operands immediate
Run Code Online (Sandbox Code Playgroud)
该prefix字段可能会修改指令的行为,这不适用于您的用例。opcode您可以在参考文献中查找(我喜欢这个),例如,mov r/m32, imm32isC7 /0的意思是:操作码是C7并且两个操作数之一为零,编码扩展操作码。该指令的形式如下
C7 /0 imm32
Run Code Online (Sandbox Code Playgroud)
操作数/扩展操作码被编码为 modr/m 字节,带有用于某些寻址模式的可选 sib(标度索引基数)字节和可选的 8 位或 32 位位移。您可以在参考中查找您需要的值。因此,在您的情况下,您希望[rbp]使用一字节位移和寄存器操作数 0 对内存操作数进行编码,从而得到 modr/m byte 45。所以编码是:
C7 45 disp8 imm32
Run Code Online (Sandbox Code Playgroud)
现在我们用二进制补码对 8 位位移进行编码。-4对应于FC,所以这是
C7 45 FC imm32
Run Code Online (Sandbox Code Playgroud)
最后,我们对您想要的 32 位立即数进行编码2。请注意,它是小尾数:
C7 45 FC 02 00 00 00
Run Code Online (Sandbox Code Playgroud)
这就是指令的编码方式。