2017-10-13 87 views
0

比方说,我在由ç编译器生成的对象文件运行objdump -d,我得到这个拆卸:如何解释disassembed C代码

0000000000400b5e <main>: 
400b5e: 55 push %rbp 
400b5f: 48 89 e5 mov %rsp,%rbp 
400b62: bf 50 0a 49 00 mov $0x490a50,%edi 
400b67: e8 04 0b 00 00 callq 401670 <_IO_puts> 
400b6c: 5d pop %rbp 
400b6d: c3 retq 
400b6e: 66 90 xchg %ax,%ax 

我不知道如何解释这里的一切。走线:

400b62: bf 50 0a 49 00 mov $0x490a50,%edi 

我得到什么mov声明是干什么的,但到底是什么的400b62是什么意思? bf 50 0a 49 00是什么意思?我无法在互联网上找到任何解释如何阅读这些内容的内容。

+0

'BF 50 0A 49 00'是机器代码'$ MOV 0x490a50,%edi'。通常,助记符都对齐到一个共同的列,所以这很容易看到。 – fuz

+0

你最好使用[编译器选项创建一个程序集文件](https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-cc-source-in- GCC)。它将用相应的C语句,变量和文字标注汇编代码。 – Barmar

回答

4

400b62是指令的地址。 bf 50 0a 49 00是构成指令的字节。在这种情况下,它在400b62处的指令将寄存器%edi设置为0x490a50。这里的bf代表“set edi”,50 0a 49 00代表0x490a50的小字节顺序(如Intel处理器)的字节。

如果你想能够读取每一个指令,它需要一个比特解码,但可以做到的。根据我的经验,最好的参考是Intel® 64 and IA-32 Architectures Software Developer Manuals,但它们并不适合心脏病。

+0

这可能是一个愚蠢的问题,但它是什么意思“构成指令的字节”? –

+0

@KingHenryV,看到我的扩展答案。 – DocMax

+2

@KingHenryV CPU不执行文本源代码,它只能理解指令操作码,在x86 CPU明白'bf'为'MOV EDI,imm32'指令,所以它也将读取下四个字节来获取'imm32'数据。来自不同供应商的每个CPU都有不同的指令和操作码,这就是x86 Assembly与ARM Assembly不同的原因。为了执行你的源代码,你必须首先用汇编将它编译成这些指令操作码(机器码),然后CPU才能执行你的程序。 – Ped7g

2

开始使用汇编语言底漆,如https://speakerdeck.com/vsergeev/x86-assembly-primer-for-c-programmers这是很好的,如果你已经知道C.

在你的代码,要紧的是

mov $0x490a50,%edi 
callq 401670 <_IO_puts> 

对x86-64的前6个参数被传递通过寄存器 rdi, rsi, rdx, rcx r8, r9。 (edirdi的一半),因此它将一个参数传递给一个待调用的函数,然后调用该函数。

解码名称(_IO_puts)表明您正在处理puts的实现,这意味着0x490a50是传递给它的字符串的内存地址的十六进制表示形式。

原有的主可能会是这样的:

#include <stdio.h> 
int main() { puts("hello world"); } 
+1

'0x490a50'是内存地址('const char *'),位于“字符串的十六进制表示”下。我想象的是将8个“char”值直接存储在“rdi”中,而不是存储器中,这不是情况'puts'。 – Ped7g

+1

@ Ped7g我的头会自动将字符串衰减为指针。 C已经宠坏了我。无论如何,我现在已经修复了答案的文字。 – PSkocik