我是汇编的新手,试图了解以下功能的objdump:
int nothing(int num) {
return num;
}
这是结果(Linux,x86-64,gcc 8):
push rbp
mov rbp,rsp
mov DWORD PTR [rbp-0x4],edi
mov eax,DWORD PTR [rbp-0x4]
pop rbp
ret
我的问题是:
1. edi
来自哪里?通读一些介绍性文档,我的印象是[rbp-0x4]
将包含num
。
2.从以上所述,显然edi包含自变量。但是[rbp-0x4]
起什么作用呢?为什么不只是mov eax, edi
?
谢谢!
答案 0 :(得分:3)
edi
来自哪里?...从上面看,显然edi包含参数。
这是调用约定(对于Linux和许多其他操作系统):
这些操作系统的所有编程语言都通过rdi
中的第一个参数。结果(返回值)在rax
中传递。
并且由于您的C编译器将int
解释为32位,因此仅使用rdi
和rax
的低32位-edi
和{{1} }。
Windows的编程语言在eax
中传递第一个参数...
但是
rcx
扮演什么角色?
在这里使用[rbp-0x4]
主要是历史原因。在16位代码(如1980年代和1990年代的PC中使用的代码)中,无法使用rbp
寄存器(对应于sp
)在堆栈上寻址数据。唯一允许在堆栈上轻松寻址值的寄存器是rsp
寄存器(对应于bp
)。
即使在32位或64位代码中,编写使用rbp
而不是rsp
来寻址局部变量(在堆栈上)的编译器也更加困难。
在知道C函数中的操作之前,编译器会生成汇编代码的前3条指令。编译器将值放在堆栈上,因为您可以在代码中执行类似rbp
的操作。但是,当address = &num
在寄存器中时,这是不可能的,只有当num
位于存储器中时,这是不可能的。
为什么不只是
num
?
如果告诉编译器优化代码,它将在生成第一条汇编程序指令之前先检查C函数的内容。它将发现不需要将该值放入内存中。
在这种情况下,代码确实将如下所示:
mov eax, edi