push、pop及函数调用约定

push:
把一个32位的操作数压入堆栈中。这个操作导致esp被减4。esp被形象地称为栈顶。我们认为顶部是地址小的区域,那么,压入堆栈中数据越多,这个堆栈也就越堆越高,esp也就越来越小。在32位平台,esp每次减少4字节。

pop:
相反,esp被加4,一个数据出栈。pop的参数一般是一个寄存器,栈顶的数据被弹出到这个寄存器中。

call 的本质相当于push+jmp ;ret 的本质相当于pop+jmp;

函数调用约定:
1)_cdecl C 调用 规则
参数从右到左进入堆栈
在函数返回后,调用 者要负责清除堆栈,所以这种调用常会生成较大的可执行程序。
2)_stdcall又称为WINAPI,其调用 规则
参数从右到左进入堆栈
被调用的函数在返回前自行清理堆栈,所以生成的代码比cdecl小
3)pascal调用规则主要用在win16函数库中,现在基本不用
参数从左到右进入堆栈
被调用的函数在返回前自行清理堆栈
不支持可变参数的函数调用 。

在Windows中,不管哪种调用 方式都是返回值放在eax中,然后返回。外部从eax中得到返回值。



#include "stdafx.h"


int main()
{
01371650 push ebp
01371651 mov ebp,esp
01371653 sub esp,0C0h
01371659 push ebx
0137165A push esi
0137165B push edi
0137165C lea edi,[ebp-0C0h]
01371662 mov ecx,30h
01371667 mov eax,0CCCCCCCCh
0137166C rep stos dword ptr es:[edi]
return 0;
0137166E xor eax,eax
}

void myfunction(int a, int b)
{
00CA1650 push ebp ;保护ebp,并把esp放入esp中。此时esp=ebp
00CA1651 mov ebp,esp ;
00CA1653 sub esp,0CCh ;把esp往上移动一个范围,等于在堆栈中放出一片新的空间用来存储局部变量
00CA1659 push ebx ;保存三个寄存器
00CA165A push esi
00CA165B push edi
00CA165C lea edi,[ebp-0CCh] ;lea把内容的地址,也就是ebp-0cch加载到edi中。目的是把保存局部变量的区域从ebp-0cch开始的区域,初始化成0cccccccch
00CA1662 mov ecx,33h
00CA1667 mov eax,0CCCCCCCCh ;
00CA166C rep stos dword ptr es:[edi] ;写入0cch指令
int c = a + b;
00CA166E mov eax,dword ptr [a]
00CA1671 add eax,dword ptr [b]
00CA1674 mov dword ptr [c],eax
}
00CA1677 pop edi ;恢复edi、esi、ebx
00CA1678 pop esi
00CA1679 pop ebx
00CA167A mov esp,ebp ;恢复原来的ebp和esp,让上一个调用的函数正常使用
00CA167C pop ebp
00CA167D ret
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在汇编语言中更改函数调用约定通常涉及到规定参数、返回值和返回地址等放置的位置,以及如何管理栈的操作。以下是一些关键点: 1. **了解调用约定**:调用约定是一组规则,它们定义了在函数调用发生时,调用者(caller)和被调用者(callee)应如何协作。这包括参数的传递方式、返回值的处理以及栈的管理等方面。 2. **参数传递**:在不同的调用约定中,参数可以通过寄存器或栈来传递。例如,在System V AMD64调用约定中,前几个参数通常会通过特定的寄存器传递,而超出的部分则通过栈传递。 3. **栈的使用**:栈在函数调用中扮演着重要角色,它遵循先进后出的原则。在函数调用过程中,栈被用来存储局部变量、参数以及返回地址等信息。使用pushpop指令对栈空间执行数据的压入和弹出操作。 4. **返回值处理**:调用约定还规定了函数返回值的处理方式。有些调用约定要求返回值存放在特定的寄存器中,而有些则通过栈来传递返回值。 5. **调用者和被调用者的协作**:在C/C++中,CDECL是一种默认的调用约定,它规定函数调用者负责将参数压入栈中,并在调用后清理栈。而被调用函数通过栈顶指针ESP来访问这些参数。 6. **特定平台的约定**:不同的平台和架构可能有不同的调用约定。例如,在32位系统上,存在多种调用约定,如cdecl、stdcall、fastcall等。而在64位体系架构下,现代编译器通常会遵循System V AMD64调用约定。 要更改函数调用约定,你需要根据目标平台和编译器的规定来调整汇编代码。这可能涉及到修改函数的prologue和epilogue代码,以及调整参数传递和返回值处理的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蚂蚁_CrkRes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值