函数堆栈调用

函数和函数调用过程
按照下面代码给出几个问题

#include<stdio.h>
int Sum(int a,int b)//被调用函数
{
	return a + b;
}
int main()//调用方函数
{
	int rt = 0;
	rt = Sum(10,20);
	return 0;

1.形参开不开辟内存?如果开辟,是调用方开辟还是被调用方开辟?
2.函数调用完成,怎么回退到调用方?
3.函数调用完成,怎么接着调用方继续的指令?
4.函数返回值怎么返回到调用方?
回答这些问题之前我们来看看下面这些内容
寄存器
eax、ecx、ebx、edx
ebp栈底指针寄存器
esp栈顶指针寄存器
汇编指令
mov移址指令
a = 10;
Linux AT&T
mov 0a,dword ptr[a];//从左往右看
Windows inter x86
mov dword ptr[a] ,0Ah
在汇编语言中有[a]表示该内存单元的地址
如果前面家ptr表示该内存单元
lea移地址指令
int a = 10;
int *p = &a;
lea dword ptr[p],[a];
压栈指令push 0ah; esp改变
出栈指令pop eax;
eax = pop(); esp改变
累加指令add eax,0a;
eax += 0a;
累减指令sub eax,0a;
eax -= 0a;

实参的入栈顺序:自右向左的,就可以支持可变参参数
开栈过程中第一步处理实参,为实参入栈,就是给形参开辟空间并作赋值,实参传形参的过程是一个初始化的过程,然后是下一行指令地址入栈,目的是当函数清栈完成后,能沿着被调用方的指令执行。之后进入调用方,就是ebp入栈,调用方的栈顶地址入栈,紧接着是给被调用方预留空间,并作cccc的初始化。
总结一下就是开栈过程四步
(1)压入实参,开辟形参并赋值
(2)压入下一行指令地址,就是方便被调用方函数处理完能沿着调用方下一行指令继续执行
(3)压入调用方栈底地址,方便被调用方函数处理完成能回退到调用方
(4)预留被调用方函数的活动空间,并作cccccccc的初始化
清栈过程(
(1)清理被调用方函数预留的空间
(2)出栈edp,edp回退到被调用方栈帧上
(3)下一行指令地址出栈
(4)清理形参

返回值由寄存器带出,寄存器只能处理四个字节,那么八个字节的返回值由两个寄存器带出分别为eax、edx

类型划分
1、内置类型 char short int long 指针
2、自定义类型 结构体 类 (会有大于八个字节的)做返回值的话,这样就不能用寄存器带出来了,那就应该

前提条件:非类类型的返回值规则
函数的返回值规则
<=4个字节由eax带出
<=8>4 由eax 和edx带出来
大于8由临时量带出

函数返回值 不能返回局部变量的地址
函数调用完成 栈帧清理 局部也会被清理

调用约定
函数调用过程中的一种调用规则
c:
_cdecl c语言标准调用规定
形参是调用方开辟 调用方清理
_stdcall windows标准调用约定
形参是调用方开辟 被调用方清理
_fastcall 快速调用约定
形参处理变成寄存器直接带入 没有形参开辟和清理
c++:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值