从C语言到汇编编译代码的理解,从汇编代码理解函数调用过程

如何理解函数调用过程?本文把一个简单的C语言程序汇编成目标代码,然后用objdump目标文件反编译成的汇编代码,从而一窥函数调用过程,希望对你有所启发。

C语言源码:

#include

int static add(int a, int b)

{

return a+b;

}

int main()

{

int x = 5;

int y = 10;

int u = add(x, y);

return 1;

}

~

经过编译:gcc -g -c add.c,生成目标代码add.o

查看目标文件(生成汇编代码): objdump -d -S add.o

add.o: file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:

_main:

; { //这是注释(ps)

0: 55 pushq %rbp

1: 48 89 e5 movq %rsp, %rbp

4: 48 83 ec 10 subq $16, %rsp

8: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)

; int x = 5;

f: c7 45 f8 05 00 00 00 movl $5, -8(%rbp)

; int y = 10;

16: c7 45 f4 0a 00 00 00 movl $10, -12(%rbp)

; int u = add(x, y);

1d: 8b 7d f8 movl -8(%rbp), %edi

20: 8b 75 f4 movl -12(%rbp), %esi

23: e8 00 00 00 00 callq 0 <_main>

28: be 01 00 00 00 movl $1, %esi

2d: 89 45 f0 movl %eax, -16(%rbp)

; return 1;

30: 89 f0 movl %esi, %eax

32: 48 83 c4 10 addq $16, %rsp

36: 5d popq %rbp

37: c3 retq

38: 0f 1f 84 00 00 00 00 00 nopl (%rax,%rax)

_add:

; {

40: 55 pushq %rbp

41: 48 89 e5 movq %rsp, %rbp ;当前函数的栈指针

44: 89 7d fc movl %edi, -4(%rbp) ;把寄存器的参数移动到栈上

47: 89 75 f8 movl %esi, -8(%rbp) ;把寄存器的参数移动到栈上

; return a+b;

4a: 8b 75 fc movl -4(%rbp), %esi

4d: 03 75 f8 addl -8(%rbp), %esi

50: 89 f0 movl %esi, %eax

52: 5d popq %rbp

53: c3 retq

从上面可以看出:

1、目标文件(.o)的地址是从0开始的 (还没有在虚拟地址空间中分配地址,ld的时候才分配)

2、函数开始地址是4字节对齐的。

3、X86架构指令长度是变长的(ARM指令是定长的4字节)。

4、名字修饰,符号名称是通过下划线+函数名得到。

程序调用过程

调用方:

先把参数保存在寄存器edi和esi中(通过寄存器传参数)

调用callq

处理返回值eax

其中,callq做了两件事情:

1) 保存下一条指令的地址,用于函数返回继续执行

2) 跳转到子函数的地址

被调用方:

上一个函数的帧指针rbp入栈

栈指针rsp保存到帧指针

从寄存器(edi和esi)取出参数到栈中

运算

把计算结果保存在eax

弹出帧指针(还原前一个函数的rbp)

函数返回,取下一跳指令继续执行

特别说明:

上面函数传参和返回参数传递是通过寄存器传递的,还可以通过栈和内存区域传递,具体可以参考C语言调用惯例。

一个函数的帧结构中包含哪些数据?

1、上一个栈帧寄存器保存在栈中的值

2、本函数用的临时变量

3、调用子函数传的参数

4、调用子函数后返回时继续执行的(返回地址)

栈帧结构:

b74cc728bb67

栈帧示意

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值