编译链接运行原理---函数堆栈调用

首先先提出下面五个问题:

(1)形参开辟内存吗?由谁开辟?

(2)形参的入栈顺序?

(3)返回值如何带出?

(4)被调用方结束后如何知道回退到调用方栈帧上?

(5)函数调用完成如何知道执行下一行指令?

要解决这些问题,我们就要从汇编的角度切入。通过汇编代码能够使我们更加清晰地掌握函数的堆栈调用。 汇编分为两种形式inter x86 (从右向左看) 和 AT&T unix(从左向右看),我们学习的主要是inter x86下的汇编代码。

1、先来了解一下反汇编的一些指令

  • 移值:mov

int a = 20;

inter x86 (从右向左看) mov dword ptr [a] , 14h;

AT&T unix(从左向右看)mov 14h , dword ptr [a];

都是指将十六进制的20 放在dword ptr [a]中;

  • 移地址:led

led eax ,[ebp-4]   将ebp-4的地址传送到eax中;

  • 压栈:push

push 10;  将10压入栈中

  • 出栈:pop

pop eax ; ==> eax = pop();

  • 累加指令:add

add eax, 4; ==> eax+=4;

  • 累减指令:sub

sub eax, 4; ==> eax-=4;

2、寄存器

存储数据:eax、ebx、ecx、edx.

ebp:栈底指针寄存器

esp:栈顶指针寄存器

pc:下一行指令寄存器

举例:

进入Debug版本查看该程序的InterX86反汇编代码如下:    

有反汇编代码解释可以回答问题

(1)形参开辟内存吗?由谁开辟?

         形参开辟内存,由于这是在main函数的栈帧上,所以是由被调用方开辟。

(2)形参的入栈顺序?

形参的入栈顺序是自右向左。

(3)返回值如何带出?

<=4字节返回值由eax寄存器带出;

4字节<返回值<=8字节时,由eax和ebx寄存器共同带出;

>8字节,由临时量带出。

这是sum函数调用返回值之后的一些操作:

(4)函数调用完成后如何知道回退到调用方栈帧上?

call指令会把调用方的下一行指令地址压栈,在压入调用方栈底地址。在跳转到被调用方函数栈帧。pop ebp就是将压入的栈底指针弹出,会退到main函数栈帧上。

(5)函数调用完成如何知道执行下一行指令?

当调用结束时回退到调用方栈底,再执行ret指令,1、pop pc将值 pop出并赋值个PC寄存器,即弹出下一行指令地址,2、add esp 8 销毁形参。

总结:

开栈:

  • 压入实参为形参始化自右向左;
  • 压入下一行指令地址;
  • 压入调用方栈底地址;
  • 跳转到被调用方栈帧;
  • 被调用方开辟活动空间并初始化。

清栈:

  • 栈开辟空间清空;
  • 弹出调用方栈底地址;
  • 回退到调用方栈底;
  • 将下一行指令存放进PC;
  • 清理形参内存。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值