2017-05-24 118 views
0

我用下面的代码创建了一个简单的C++源文件。汇编语言机器代码

int main() { 
int a = 1; 
int b = 2; 
if(a < b) { 
    return 1; 
} 
else if(a > b) { 
    return 2; 
} 
else { 
    return 3; 
} 

}

我用objdump的命令来获取上述源代码的汇编代码。 并线

INT B = 2;转换为mov DWORD PTR [rbp-0x4],0x2

而其相应的机器码(十六进制格式)是c7 45 fc 02 00 00 00

我想知道如何将汇编代码转换为二进制代码。我查阅了x86-64的英特尔参考手册,但由于我是低级编程的新手,所以我无法理解。

+1

“转换”是什么意思?使用程序?手动做? – Shiro

+0

手动转换它。 –

+0

'int b = 2;'不是汇编语言。不同之处在于,C是编译语言,所以'int b = 2;'这行可以用许多不同的方式实现(甚至可以被优化器彻底删除),这取决于编译器将决定什么,如何生成机器码结果由C语言标准定义。汇编语言的方式不同,汇编程序不是这种类型的编译器,当你在Assembly'add rax,rbx'中编写时,它将被编译为这样,不会改变指令,或者被某种优化器删除,所以这更像是“1:1变革”。 – Ped7g

回答

4

你应该阅读英特尔手册,它解释了如何做到这一点。为更简单的参考,read this。 x86指令的编码方式非常简单,但可能性有点过大。

简而言之,x86指令包括以下部分,其中除了所述操作码每一个部分可能丢失:

prefix opcode operands immediate 

prefix字段可以修改指令的行为,这并不适用于你的用例。您可以在参考文献(我喜欢this one)中查找opcode,例如,mov r/m32, imm32C7 /0,这意味着:操作码是C7,两个操作数中的一个是零作为扩展操作数。该指令需要一个32位的立即的,所以指令的形式

C7 operand/0 imm32 

操作数/扩展操作码被编码为具有可选的SIB(标度指数基)字节用于一些寻址模式和一个MODR /米字节可选的8位或32位移位。你可以看看你需要什么值in the reference。因此,在你的情况下,你想编码一个存储器操作数[rbp]与一个字节的位移和寄存器操作数为0,导致modr/m字节45。所以编码是:

C7 45 disp8 imm32 

现在我们编码二进制补码中的8位移位。 -4对应FC,所以这是

C7 45 FC imm32 

最后,我们编码32位立即,你想成为2。请注意,它是在小端:

C7 45 FC 02 00 00 00 

这就是如何指令编码。

+0

因此,在你提供的[链接](http://ref.x86asm.net/geek64.html)中,我去了C7 1字节操作码,它用于** MOV **指令。但是两个操作数Evqp \t和Ivds \t的含义是什么,它们是否对应于rm32寻址和直接?感谢您的帮助 –

+0

请参阅[本页](http://ref.x86asm.net/#column_op)了解这些字段的含义。我链接的参考文献是高度浓缩的,但更难以阅读。 – fuz

+0

好,太好了。另一个问题是,你说“我想用1字节的位移(8位)[** DWORD PTR [rbp-0x4] **]对rbp寄存器进行编码”,当我看到MOD [r/m]链接](http://ref.x86asm.net/geek64.html#modrm_byte_32_64)我也看到一个32位位移的版本,你能给我一个例子吗? –