这里有一个带有main 的小代码,它调用了一个名为func 的简单函数。
我们可以使用gcc main.c -S main.s 编译这个c 代码。 main.s 应为汇编输出。
在程序集中,您可能会看到 CPU 指令:push、pop、leave、enter。这些指令负责栈帧管理。
如果您使用带有其他选项的 gcc 进行编译,您可能会注意到一些堆栈管理差异。
#include <stdio.h>
int func(void);
int func(void)
{
int i;
for(i=0;i<100;i++)
printf("%d",i);
return i;
}
int main(void)
{
return func();
}
GCC 编译器汇编输出
.file "main.c"
.section .rodata
.LC0:
.string "%d"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -4(%rbp)
jmp .L2
.L3:
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
addl $1, -4(%rbp)
.L2:
cmpl $99, -4(%rbp)
jle .L3
movl -4(%rbp), %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call func
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits
这里是函数func(objdump main.o -S)的objdump输出。 main.o 获得者:gcc main.c -o main.o
000000000040052d <func>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
40053c: eb 18 jmp 400556 <func+0x29>
40053e: 8b 45 fc mov -0x4(%rbp),%eax
400541: 89 c6 mov %eax,%esi
400543: bf f4 05 40 00 mov $0x4005f4,%edi
400548: b8 00 00 00 00 mov $0x0,%eax
40054d: e8 be fe ff ff callq 400410 <printf@plt>
400552: 83 45 fc 01 addl $0x1,-0x4(%rbp)
400556: 83 7d fc 63 cmpl $0x63,-0x4(%rbp)
40055a: 7e e2 jle 40053e <func+0x11>
40055c: 8b 45 fc mov -0x4(%rbp),%eax
40055f: c9 leaveq
400560: c3 retq
0000000000400561 <main>:
400561: 55 push %rbp
400562: 48 89 e5 mov %rsp,%rbp
400565: e8 c3 ff ff ff callq 40052d <func>
40056a: 5d pop %rbp
40056b: c3 retq
40056c: 0f 1f 40 00 nopl 0x0(%rax)