汇编分为两种:
1.inter x86:从右往左
2.AT&T unix:从左往右
函数调用堆栈
源代码:
反汇编代码:
ebp:栈底指针 esp:栈顶指针,在栈上开辟内存,通过ebp指针的偏移量来访问数据
10: int a = 10;
002E143E mov dword ptr [ebp-8],0Ah ,将a入栈,
11: int b = 20;
002E1445 mov dword ptr [ebp-14h],14h ,将b入栈
12: int ret = 0;
002E144C mov dword ptr [ebp-20h],0 ,将ret入栈
压栈
调用函数:
1.压入形参变量的地址和值,
2.压入函数调用返回后要执行的指令的地址
被调用函数:
1.压入调用函数的栈底指针,把栈底指针寄存器指向被调用函数的栈底
2.开辟被调用函数的栈帧大小,并初始化为CC
清栈
被调用函数
1.清理被调用函数开辟的栈帧大小
2.回退栈底指针到调用函数的栈底
3.把回退到调用函数要执行的指令地址给pc寄存器
调用函数:
1.清理形参变量的内存
2.函数的返回值
1.4 eax 值
2.8 eax edx
3.>8开辟一个临时量(调用方函数栈帧)
eax 带出临时量的地址
循环拷贝到接收返回值的变量的地址空间
3.函数的调用约定
_cdecl c的调用约定
_stdcall Windows下的标准调用约定
_fastcall快速调用约定
_thiscall C++的成员函数调用约定
三种调用约定的区别:
1.符号的生成方式
ld合并符号表
main:符号表 _cdecl ?sum@@YAHHH@Z *UND* gobal
符号解析
test: _stdcall ?sum@@YGHHH@Z .text gobal
_fastcall ?sum@@YIHHH@Z
2.参数的压栈方式
3.函数的形参清理
_cdecl 调用方开辟 调用方清理
_stdcall调用方开辟 被调用方清理
_fastcall
<= 8
寄存器带值 不需要形参变量的清理
> 8
前2个形参寄存器带值 不需要形参变量的清理
后面的和stdcall调用方式一样