您的位置:首页 > 运维架构

push、pop及函数调用约定

2017-03-24 12:42 323 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: