函数的堆栈调用

一、研究问题与答案

1.形参开辟内存吗?由谁开辟?

答案:开辟内存;并且由调用方开辟;

2.形参的入栈顺序

答案:从右向左入栈,(解决可变参数的问题);实参与形参匹配类型是从左向右匹配;

3.返回值由谁带出?

答案:一般由寄存器带出;

4.被调用方结束,如何知道回退到调用方栈帧上?

答案:调用方栈底指针的地址保存到被调用方栈底指针;

5.函数调用结束,如何知道应该执行下一条指令?

答案: 将下一条指令的地址进行压栈处理;

二、了解一些汇编指令

在了解函数的堆栈调用时,首先必须熟知以下汇编语句:
1.mov 做移植处理
例:mov, dword ptr[ebp(栈底指针)-4(偏移量)] (位置), 0ah(值);
2.lea  移地址
例:eax ,[ebp-4];
3.push  压栈
例:push 0ah;
4.pop   出栈 将栈顶元素拿出放到eax中;
例:pop eax(寄存器);==> eax = pop();
5.add  +=
例:add eax ,0ah ;==> eax+=0ah;
6.sub  -=
例: sub eax,0ah;==>eax-=0ah;
7.call  禁止相对位移调用指令;压入下一行指令地址,jmp到被调用方函数;
8.ret   返回值指令
9.寄存器:
eax ebx ecx  edx 存数据
ebp  栈底指针寄存器
esp  栈顶指针寄存器
pc   下一条指令寄存器

三、函数堆栈调用的步骤

1.形参初始化;
2.压入下一行指令地址;
3.压入调用方栈底指针寄存器的值;
4.移动ebp到被调用方栈底;
5.开辟局部变量所要的栈帧并初始化为cccccccc;

了解开栈的步骤: 

    1、压入实参,形参初始化    自右向左

   2、压入下一行指令地址:为了在退栈的时候,沿调用方跳到下一行指令中进行执行

   3、压入调用方栈底地址   回退到调用方

  4、调转到被调用方函数栈帧

  5、被调用方开辟 活动空间并初始化为cccccccc

四、调用约定

什么是调用约定呢?调用约定约定什么?常见的调用约定有那些呢?
1、定义:
    函数的调用方和被调用方对于函数如何调用需要有一个明确的约定,只用双方都遵守同样的约定,函数才能被正确的调用,这样的约定称为调用约定也叫调用惯例;
2.约定内容

  •     函数符号的生成
  •     形参的入栈顺序,(从右向左)
  •     形参的开辟和清理方式;

3.常见的调用约定

  •     C标准的调用约定     --cdecl

    <调用方开辟形参并清理>
    <生成的函数符号为:?函数名@@YA返回值类型 参数类型 参数类型 @Z>

  •     Windows的调用约定   --stdcall

    <形参由调用方开辟,被调用方清理>
    <生成的函数符号为:?函数名@@YG返回值类型 参数类型 参数类型 @Z>

  •     快速调用约定        --fastcall    

    <最多使用两个寄存器来带入实参,其他参数和--stdcall的处理方式一样>
    <生成的函数符号为:?函数名@@YI返回值类型 参数类型 参数类型 @Z>

  •     成员方法的调用约定  --thiscall
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值