编译器在这个汇编代码中做了什么?
我想了解一下C编译器编译为汇编时会做什么。 我编译成汇编的代码是这样的:
void main() {
int x = 10;
int y = 10;
int a = x + y;
}
其中产生以下程序集:
.Ltext0:
.globl main
main:
.LFB0:
0000 55 pushq %rbp
0001 4889E5 movq %rsp, %rbp
0004 C745F40A movl $10, -12(%rbp)
000b C745F80A movl $10, -8(%rbp)
0012 8B45F8 movl -8(%rbp), %eax
0015 8B55F4 movl -12(%rbp), %edx
0018 01D0 addl %edx, %eax
001a 8945FC movl %eax, -4(%rbp)
001d 5D popq %rbp
001e C3 ret
不过,我在理解这段代码中特别的内容时遇到了一些麻烦。 我了解所有的标签和一些装配。 这是我认为它的作用:
任何人都可以澄清这个大会的某些观点,也许编译器在选择-8,-12的理由,为什么它选择了一些其他寄存器的eax和edc,为什么它推动和弹出rbp等?
推rbp? - 这是一个堆栈框架还是什么?
是。 编译器为局部变量创建一个堆栈帧。 push %rbp
/ movq %rsp, %rbp
是执行此操作的标准方法。 它允许轻松访问局部变量。
将10移入堆栈? 偏移量为-12? 为什么12,为什么是负面的?
在这种情况下,编译器选择使用从变量x
-12(%rbp)
到-9(%rbp)
的堆栈的4字节( int
大小)部分。
一旦创建了堆栈框架,您就可以访问具有负偏移量的局部变量,以及具有正偏移量的函数参数:
------------------------------------------------------
| R |
New stack (locals) | B | Old stack (parameters)
| P |
------------------------------------------------------
^
RBP is updated to point here as well so you get negative offsets (to the left) for locals and positive offsets (to the right) for parameters.
请注意,由于存储的RBP也占用空间以及函数的返回地址,因此您需要将16个字节添加到任何参数偏移量。 (32位系统为8个字节)
通常,在使用本地变量进行任何工作之前,必须更新RSP
,如下所示: subq $12, %rsp
。 离开函数时,使用addq $12, %rsp
或leave
。 本示例更新堆栈指针以显示我们在堆栈上使用了12个字节。 当你完成它们时,你只需恢复堆栈指针。 在你的例子中,虽然没有这个需要,因为这个函数没有其他地方变量用于堆栈。
将10移入堆栈,但这次是-8而不是-12
再次,引用一个局部变量,除了这次,编译器选择了从-8(%rbp)
到-5(%rbp)
的变量y
开始的4字节部分。
在这种情况下, pop %rbp
将函数结尾处的堆栈恢复为输入前的堆栈:
------------------------------------------------------
| R |
New stack (locals) | B | Old stack (parameters)
| P |
------------------------------------------------------
^
RSP points here, so a `pop %rbp` will restore both RSP and RBP
编译器可能首先尝试使用EAX
和EDX
因为EAX
是为数学运算设计的,而EDX
是为通用数据操作而设计的。 你经常会发现他们在操作中配对。
要理解编译器生成的程序集,您必须了解堆栈帧。 SP是堆栈指针,BP指向当前堆栈帧,它用于寻址局部变量(因此将值“10”移动到[bp-12]和[bp-8]。然后将其加载到第一个可用注册一个加法(在这种情况下是ax和dx)并执行加法。最后,它恢复旧的堆栈并返回。
链接地址: http://www.djcxy.com/p/72413.html上一篇: What does the compiler do in this assembly code?
下一篇: Are all programs eventually converted to assembly instructions?