C/C++函数调用栈帧及其内存布局
编译器:vs2022
架构: amd64
应用程序:32位程序x86
1. 基础知识
1.1 函数栈帧
每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame)。
函数栈帧包括:
- 函数参数及返回地址
- 非静态局部变量及编译器自动产生的临时变量
- 函数调用上下文(寄存器)
1.2 函数调用约定
调用约定 | 参数压栈顺序 | 平衡堆栈 | 说明 |
---|---|---|---|
__cdecl | 从右往左依次入栈 | 调用者清理堆栈 | VS编译器默认方式 |
__stdcall | 从右往左依次入栈 | 自身清理堆栈 | Windows API显示指定 |
__fastcall | ECX/EDX传递前两个参数剩下的从右往左依次入栈 | 自身清理堆栈 |
1.3 寄存器
含义 | 16位 | 32位 | 64位 | |
---|---|---|---|---|
栈顶寄存器 | sp | esp | rsp | |
栈底寄存器 | bp | ebp | rbp | |
指令寄存器 | 当前指令的下一条指令的地址 | ip | eip | rip |
累积寄存器 | 累加,函数返回结果 | ax | eax | rax |
计数寄存器 | cx | ecx | rcx | |
源地址索引 | si | esi | rsi | |
目标地址索引 | di | edi | rdi |
1.4 汇编指令
指令 | 说明 |
---|---|
push | 入栈,esp变化 |
pop | 出栈,esp变化 |
call | 函数调用 1.返回地址入栈 2.跳转到目标地址 |
jump | 跳转到目标地址 eip变化 |
ret | 恢复返回地址 1. 返回地址出栈 2. 跳转到返回地址 |
lea | load effective address 加载有效地址 |
mov | 数据转移 |
nop | 空指令 |
2. 函数调用栈帧内存布局
+------------------+ low address
| param variable 1 |
+------------------+ +
| param variable 1 | |
+------------------+ |
| ... | |
+------------------+ |
| local variable 1 | |
+------------------+ | function stack frame
| local variable 2 | |
+------------------+ |
| ... | |
+------------------+ |
| ebp | |
+------------------+ v
| return address |
+------------------+ high address
3. 函数调用完整过程
- stackTest.cpp
int add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int x = 1;
int y = 2;
int z = 0;
z = add(x, y);
return 0;
}
- 反汇编(F10启动)
int main()
{
+----------+ +---------+
esp(0x00b4fc20) +----> | esp |
+----------+
| ... | invoke_main
+----------+
ebp(0x00b4fc3c) +----> | ebp |
+----------+ +---------+
00B817E0 push ebp # esp 0x00b4fc20 ebp 0x00b4fc3c => esp 0x00b4fc1c ebp 0x00b4fc3c # 保存invoke_main函数的ebp(0x00b4fc3c)
+----------+
esp(0x00b4fc1c) +----> |0x00b4fc3c| invoke_main ebp
+----------+ +---------+
0x00b4fc20 +----> | |
+----------+
| ... | invoke_main
+----------+
ebp(0x00b4fc3c) +----> | ebp |
+----------+ +---------+
00B817E1 mov ebp,esp # esp 0x00b4fc1c ebp 0x00b4fc3c => esp 0x00b4fc1c ebp 0x00b4fc1c # main函数栈帧开始
+----------+
ebp=esp(0x00b4fc1c) +----> |0x00b4fc3c| main
+----------+ +---------+
0x00b4fc20 +----> | |
+----------+
| ... | invoke_main
+----------+
0x00b4fc3c +----> | ebp |
+----------+ +---------+
00B817E3 sub esp,0E4h # esp 0x00b4fc1c ebp 0x00b4fc1c => esp 0x00b4fb38 ebp 0x00b4fc1c
+----------+ +---------+
esp(0x00b4fb38) +----> | esp |
+----------+
| ... | main
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B817E9 push ebx # esp -4 (0x00b4fb34)
00B817EA push esi # esp -4 (0x00b4fb30)
00B817EB push edi # esp -4 (0x00b4fb2c) => esp 0x00b4fb2c ebp 0x00b4fc1c
+----------+ +---------+
esp(0x00b4fb2c) +----> | edi |
+----------+
| esi |
+----------+
| ebx | main
+----------+
0x00b4fb38 +----> | |
+----------+
| ... |
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B817EC lea edi,[ebp-24h] # 初始化局部变量内存为0xCCCCCCCC
00B817EF mov ecx,9 # 初始化局部变量内存为0xCCCCCCCC
00B817F4 mov eax,0CCCCCCCCh # 初始化局部变量内存为0xCCCCCCCC
00B817F9 rep stos dword ptr es:[edi] # 初始化局部变量内存为0xCCCCCCCC
+----------+ +---------+
esp(0x00b4fb2c) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fb38 +----> | |
+----------+
| ... |
+----------+
ebp-24h(0x00b4fbf8) +----> |0xCCCCCCCC|
+----------+
(z)ebp-20h(0x00b4fbfc) +----> |0xCCCCCCCC|
+----------+ main
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(y)ebp-14h(0x00b4fc08) +----> |0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(x)ebp-8 (0x00b4fc14) +----> |0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B817FB mov ecx,0B8C000h # mov ecx,offset _0B758781_stackTest@cpp (0B8C000h)
00B81800 call 00B81320 # call @__CheckForDebuggerJustMyCode@4 (0B81320h)
int x = 1;
00B81805 mov dword ptr [ebp-8],1 # esp ebp不变 # x=1
int y = 2;
00B8180C mov dword ptr [ebp-14h],2 # esp ebp不变 # y = 2
int z = 0;
00B81813 mov dword ptr [ebp-20h],0 # esp ebp不变 # z = 0
+----------+ +---------+
esp(0x00b4fb2c) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fb38 +----> | |
+----------+
| ... |
+----------+
ebp-24h(0x00b4fbf8) +----> |0xCCCCCCCC|
+----------+
(z)ebp-20h(0x00b4fbfc) +----> |0x00000000|
+----------+ main
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(y)ebp-14h(0x00b4fc08) +----> |0x00000002|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(x)ebp-8 (0x00b4fc14) +----> |0x00000001|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
z = add(x, y);
00B8181A mov eax,dword ptr [ebp-14h] # esp ebp不变 # add函数入参 eax = y
00B8181D push eax # esp -4 (0x00b4fb28) # eax压栈
00B8181E mov ecx,dword ptr [ebp-8] # esp ebp不变 # add函数入参 ecx = x
00B81821 push ecx # esp -4 (0x00b4fb24) # ecx压栈
+----------+ +---------+
esp(0x00b4fb24) +----> |0x00000001| fun add param x(ebp-8)=1
+----------+
0x00b4fb28 +----> |0x00000002| fun add param y(ebp-14h)=2
+----------+
0x00b4fb2c +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fb38 +----> | |
+----------+
| ... | main
+----------+
ebp-24h(0x00b4fbf8) +----> |0xCCCCCCCC|
+----------+
(z)ebp-20h(0x00b4fbfc) +----> |0x00000000|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(y)ebp-14h(0x00b4fc08) +----> |0x00000002|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(x)ebp-8 (0x00b4fc14) +----> |0x00000001|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B81822 call 00B813B6 # esp ebp不变 # 调用add函数 call add (0B813B6h) # F11进入add函数(00B813B6 jmp add (0B81E70h) # esp 0x00b4fb20 ebp 0x00b4fc1c)
# call指令 1. 先把EIP压栈 push eip(0x00b81827) 2. 跳转到指定地址(0x0b813b6)
+----------+
esp(0x00b4fb20) +----> |0x00b81827| call返回后的指令地址
+----------+
0x00b4fb24 +----> |0x00000001| fun add param x(ebp-8)=1
+----------+
0x00b4fb28 +----> |0x00000002| fun add param y(ebp-14h)=2
+----------+
00B81827 add esp,8 # esp 0x00b4fb24 ebp 0x00b4fc1c => esp 0x00b4fb2c ebp 0x00b4fc1c # 销毁函数形参
+----------+
esp(0x00b4fb2c) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fb38 +----> | |
+----------+
| ... | main
+----------+
ebp-24h(0x00b4fbf8) +----> |0xCCCCCCCC|
+----------+
(z)ebp-20h(0x00b4fbfc) +----> |0x00000000|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(y)ebp-14h(0x00b4fc08) +----> |0x00000002|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(x)ebp-8 (0x00b4fc14) +----> |0x00000001|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B8182A mov dword ptr [ebp-20h],eax # mov dword ptr [z],eax # 将add函数临时保存到eax的结果赋值给变量z
return 0;
00B8182D xor eax,eax # return返回值eax=0
}
00B8182F pop edi # esp + 4 (0x00b4fb30) # edi出栈
00B81830 pop esi # esp + 4 (0x00b4fb34) # esi出栈
00B81831 pop ebx # esp + 4 (0x00b4fb38) # ebx出栈
00B81832 add esp,0E4h # esp + 0xE4 (0x00b4fc1c)
00B81838 cmp ebp,esp
00B8183A call 00B81244 # call __RTC_CheckEsp (0B81244h)
00B8183F mov esp,ebp
00B81841 pop ebp # esp 0x00b4fc1c ebp 0x00b4fc1c => esp 0x00b4fc20 ebp 0x00b4fc3c # ebp出栈
00B81842 ret # 回到invoke_main函数(main函数结束)
00B813B6 jmp add (0B81E70h) # esp 0x00b4fb20 ebp 0x00b4fc1c
int add(int x, int y)
{
+----------+
esp(0x00b4fb20) +----> |0x00b81827| 返回地址
+----------+ +---------+
| ... |
+----------+ main
ebp(0x00b4fc1c) +----> | ebp |
+----------+ +---------+
00B81E70 push ebp # esp 0x00b4fb20 ebp 0x00b4fc1c => esp 0x00b4fb1c ebp 0x00b4fc1c # 保存main函数的ebp(0x00b4fc1c)
+----------+
esp(0x00b4fb1c) +----> |0x00b4fc1c| main ebp
+----------+
0x00b4fb20 +----> |0x00b81827| 返回地址
+----------+ +---------+
| ... |
+----------+ main
ebp(0x00b4fc1c) +----> | ebp |
+----------+ +---------+
00B81E71 mov ebp,esp # esp 0x00b4fb1c ebp 0x00b4fc1c => esp 0x00b4fb1c ebp 0x00b4fb1c # add函数栈帧开始
+----------+
ebp=esp(0x00b4fb1c) +----> |0x00b4fc1c| add
+----------+
0x00b4fb20 +----> |0x00b81827| 返回地址
+----------+ +---------+
| ... |
+----------+ main
0x00b4fc1c +----> | ebp |
+----------+ +---------+
00B81E73 sub esp,0CCh # esp 0x00b4fb1c ebp 0x00b4fb1c => esp 0x00b4fa50 ebp 0x00b4fb1c
+----------+ +---------+
esp(0x00b4fa50) +----> | esp |
+----------+
| ... | add
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
00B81E79 push ebx # esp -4 (0x00b4fa4c)
00B81E7A push esi # esp -4 (0x00b4fa48)
00B81E7B push edi # esp -4 (0x00b4fa44)
+----------+ +---------+
esp(0x00b4fa44) +----> | edi |
+----------+
| esi |
+----------+
| ebx | add
+----------+
0x00b4fa50 +----> | |
+----------+
| ... |
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
00B81E7C lea edi,[ebp-0Ch] # 初始化局部变量内存为0xCCCCCCCC
00B81E7F mov ecx,3 # 初始化局部变量内存为0xCCCCCCCC
00B81E84 mov eax,0CCCCCCCCh # 初始化局部变量内存为0xCCCCCCCC
00B81E89 rep stos dword ptr es:[edi] # 初始化局部变量内存为0xCCCCCCCC
+----------+ +---------+
esp(0x00b4fa44) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fa50 +----> | |
+----------+
| ... | add
+----------+
ebp-0Ch(0x00b4fb10) +----> |0xCCCCCCCC|
+----------+
(z)ebp-8 (0x00b4fb14) +----> |0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
00B81E8B mov ecx,0B8C000h # mov ecx,offset _0B758781_stackTest@cpp (0B8C000h)
00B81E90 call 00B81320 # call @__CheckForDebuggerJustMyCode@4 (0B81320h)
int z = 0;
00B81E95 mov dword ptr [ebp-8],0 # esp ebp不变 # z=0
+----------+ +---------+
esp(0x00b4fa44) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fa50 +----> | |
+----------+
| ... | add
+----------+
ebp-0Ch(0x00b4fb10) +----> |0xCCCCCCCC|
+----------+
(z)ebp-8 (0x00b4fb14) +----> |0x00000000|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
z = x + y;
00B81E9C mov eax,dword ptr [ebp+8] # mov eax,dword ptr [x] # eax=x=1
00B81E9F add eax,dword ptr [ebp+0Ch] # add eax,dword ptr [y] # eax = eax(x) + y = 1 + 2 = 3
00B81EA2 mov dword ptr [ebp-8],eax # mov dword ptr [z],eax # z = eax = 3
+----------+ +---------+
esp(0x00b4fa44) +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fa50 +----> | |
+----------+
| ... | add
+----------+
ebp-0Ch(0x00b4fb10) +----> |0xCCCCCCCC|
+----------+
(z)ebp-8 (0x00b4fb14) +----> |0x00000003|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
return z;
00B81EA5 mov eax,dword ptr [ebp-8] # mov eax,dword ptr [z] # z赋值给eax
}
00B81EA8 pop edi # esp + 4 (0x00b4fa48) # edi出栈
00B81EA9 pop esi # esp + 4 (0x00b4fa4c) # esi出栈
00B81EAA pop ebx # esp + 4 (0x00b4fa50) # ebx出栈
+----------+
| edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
esp(0x00b4fa50) +----> | | +---------+
+----------+
| ... | add
+----------+
ebp-0Ch(0x00b4fb10) +----> |0xCCCCCCCC|
+----------+
(z)ebp-8 (0x00b4fb14) +----> |0x00000003|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fb1c) +----> | ebp | main ebp
+----------+ +---------+
00B81EAB add esp,0CCh # esp + 0xCC (0x00b4fb1c)
+----------+
ebp=esp(0x00b4fb1c) +----> |0x00b4fc1c| add
+----------+ +---------+
0x00b4fb20 +----> | |
+----------+
| ... | main
+----------+
0x00b4fc1c +----> | ebp |
+----------+ +---------+
00B81EB1 cmp ebp,esp
00B81EB3 call 00B81244 # call __RTC_CheckEsp (0B81244h)
00B81EB8 mov esp,ebp # esp 0x00b4fb1c ebp 0x00b4fb1c
00B81EBA pop ebp # esp 0x00b4fb20 ebp 0x00b4fc1c # ebp出栈
+----------+
esp(0x00b4fb20) +----> | esp |
0x00b4fb24 +----> +----------+ +---------+
| ... |
+----------+ main
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
00B81EBB ret # esp 0x00b4fb20 ebp 0x00b4fc1c => esp 0x00b4fb24 ebp 0x00b4fc1c # 回到main函数
+----------+ +---------+
esp(0x00b4fb24) +----> |0x00000001| fun add param x(ebp-8)=1
+----------+
0x00b4fb28 +----> |0x00000002| fun add param y(ebp-14h)=2
+----------+
0x00b4fb2c +----> | edi |
+----------+
| esi |
+----------+
| ebx |
+----------+
0x00b4fb38 +----> | |
+----------+
| ... | main
+----------+
ebp-24h(0x00b4fbf8) +----> |0xCCCCCCCC|
+----------+
(z)ebp-20h(0x00b4fbfc) +----> |0x00000000|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(y)ebp-14h(0x00b4fc08) +----> |0x00000002|
+----------+
|0xCCCCCCCC|
+----------+
|0xCCCCCCCC|
+----------+
(x)ebp-8 (0x00b4fc14) +----> |0x00000001|
+----------+
|0xCCCCCCCC|
+----------+
ebp(0x00b4fc1c) +----> | ebp | invoke_main ebp
+----------+ +---------+
- 内存
- esp 0x00b4fb2c ebp 0x00b4fc1c 【main函数栈帧初始化】
0x00B4FB2C 28 10 b8 00
0x00B4FB30 28 10 b8 00
0x00B4FB34 00 d0 d6 00
0x00B4FB38 48 fb b4 00
0x00B4FB3C 83 f8 80 7b
0x00B4FB40 7e ee 00 8a
0x00B4FB44 11 00 00 00
0x00B4FB48 64 fb b4 00
0x00B4FB4C 64 fb b4 00
0x00B4FB50 bc 22 81 7b
0x00B4FB54 f1 ce 64 71
0x00B4FB58 fe ff ff ff
0x00B4FB5C 6c fb b4 00
0x00B4FB60 83 f8 80 7b
0x00B4FB64 7e ee 00 8a
0x00B4FB68 11 00 00 00
0x00B4FB6C 88 fb b4 00
0x00B4FB70 88 fb b4 00
0x00B4FB74 bc 22 81 7b
0x00B4FB78 90 fb b4 00
0x00B4FB7C 22 29 81 7b
0x00B4FB80 00 45 3f 77
0x00B4FB84 9c fb b4 00
0x00B4FB88 1b 45 3f 77
0x00B4FB8C 9c fb b4 00
0x00B4FB90 83 f8 80 7b
0x00B4FB94 7e ee 00 8a
0x00B4FB98 11 00 00 00
0x00B4FB9C b8 fb b4 00
0x00B4FBA0 b8 fb b4 00
0x00B4FBA4 bc 22 81 7b
0x00B4FBA8 b8 fb b4 00
0x00B4FBAC f5 bf 7a 7b
0x00B4FBB0 00 45 3f 77
0x00B4FBB4 cc fb b4 00
0x00B4FBB8 1b 45 3f 77
0x00B4FBBC 49 ac 56 77
0x00B4FBC0 c8 fb b4 00
0x00B4FBC4 00 00 00 00
0x00B4FBC8 00 00 00 00
0x00B4FBCC e4 fb b4 00
0x00B4FBD0 22 29 81 7b
0x00B4FBD4 61 4b b2 32
0x00B4FBD8 e8 fb b4 00
0x00B4FBDC f5 bf 7a 7b
0x00B4FBE0 00 00 00 00
0x00B4FBE4 f4 fb b4 00
0x00B4FBE8 f8 fb b4 00
0x00B4FBEC c6 ff 7c 7b
0x00B4FBF0 00 00 00 00
0x00B4FBF4 00 00 00 00
0x00B4FBF8 cc cc cc cc
0x00B4FBFC cc cc cc cc # z 初始化
0x00B4FC00 cc cc cc cc
0x00B4FC04 cc cc cc cc
0x00B4FC08 cc cc cc cc # y 初始化
0x00B4FC0C cc cc cc cc
0x00B4FC10 cc cc cc cc
0x00B4FC14 cc cc cc cc # x 初始化
0x00B4FC18 cc cc cc cc
0x00B4FC1C 3c fc b4 00 # invoke_main ebp
- main函数局部变量赋值
局部变量初始化为x=0,y=2,z=0
0x00B4FBF8 cc cc cc cc
0x00B4FBFC 00 00 00 00 # z = 0
0x00B4FC00 cc cc cc cc
0x00B4FC04 cc cc cc cc
0x00B4FC08 02 00 00 00 # y = 2
0x00B4FC0C cc cc cc cc
0x00B4FC10 cc cc cc cc
0x00B4FC14 01 00 00 00 # x = 1
0x00B4FC18 cc cc cc cc
0x00B4FC1C 3c fc b4 00 # invoke_main ebp
- esp 0x00b4fa44 ebp 0x00b4fb1c 【add函数栈帧初始化】
0x00B4FA44 1c fc b4 00
0x00B4FA48 28 10 b8 00
0x00B4FA4C 00 d0 d6 00
0x00B4FA50 6b 00 54 00
0x00B4FA54 65 00 73 00
0x00B4FA58 74 00 5c 00
0x00B4FA5C 44 00 65 00
0x00B4FA60 62 00 75 00
0x00B4FA64 67 00 5c 00
0x00B4FA68 73 00 74 00
0x00B4FA6C 61 00 63 00
0x00B4FA70 6b 00 54 00
0x00B4FA74 65 00 73 00
0x00B4FA78 74 00 2e 00
0x00B4FA7C 65 00 78 00
0x00B4FA80 65 00 00 00
0x00B4FA84 f0 fa b4 00
0x00B4FA88 61 14 5e 0a
0x00B4FA8C 28 10 b8 00
0x00B4FA90 28 10 b8 00
0x00B4FA94 00 d0 d6 00
0x00B4FA98 00 00 00 00
0x00B4FA9C 00 00 00 00
0x00B4FAA0 10 fb b4 00
0x00B4FAA4 a0 fa 8d 7b
0x00B4FAA8 71 ce 64 71
0x00B4FAAC fe ff ff ff
0x00B4FAB0 1c fb b4 00
0x00B4FAB4 bc c0 80 7b
0x00B4FAB8 cd 15 5e 0a
0x00B4FABC b8 c9 80 7b
0x00B4FAC0 dd 15 5e 0a
0x00B4FAC4 28 10 b8 00
0x00B4FAC8 28 10 b8 00
0x00B4FACC 28 10 b8 00
0x00B4FAD0 00 d0 d6 00
0x00B4FAD4 40 c9 7b 7b
0x00B4FAD8 38 51 f7 00
0x00B4FADC f4 fa b4 00
0x00B4FAE0 22 29 81 7b
0x00B4FAE4 f0 fa b4 00
0x00B4FAE8 e5 05 81 7b
0x00B4FAEC 80 30 8f 7b
0x00B4FAF0 30 fb b4 00
0x00B4FAF4 28 10 b8 00
0x00B4FAF8 28 10 b8 00
0x00B4FAFC 00 d0 d6 00
0x00B4FB00 10 fb b4 00
0x00B4FB04 10 fb b4 00
0x00B4FB08 2c fb b4 00
0x00B4FB0C 2f c7 7d 7b
0x00B4FB10 cc cc cc cc
0x00B4FB14 cc cc cc cc # z 初始化
0x00B4FB18 cc cc cc cc
0x00B4FB1C 1c fc b4 00 # main ebp
- add函数局部变量赋值
局部变量初始化z=0
0x00B4FB10 cc cc cc cc
0x00B4FB14 00 00 00 00 # z = 0
0x00B4FB18 cc cc cc cc
0x00B4FB1C 1c fc b4 00 # main ebp
- add函数计算x+y赋值给z
z = x + y = 1 + 2 = 3
0x00B4FB10 cc cc cc cc
0x00B4FB14 03 00 00 00 # z = x + y = 1 + 2 = 3
0x00B4FB18 cc cc cc cc
0x00B4FB1C 1c fc b4 00 # main ebp
- main函数中z接收add函数的返回值
0x00B4FBF8 cc cc cc cc
0x00B4FBFC 03 00 00 00 # z = eax(add函数返回值)
0x00B4FC00 cc cc cc cc
0x00B4FC04 cc cc cc cc
0x00B4FC08 02 00 00 00 # y = 2
0x00B4FC0C cc cc cc cc
0x00B4FC10 cc cc cc cc
0x00B4FC14 01 00 00 00 # x = 1
0x00B4FC18 cc cc cc cc
0x00B4FC1C 3c fc b4 00 # invoke_main ebp
- main函数执行结束回到invoke_main函数
static int __cdecl invoke_main()
{
00B81F20 push ebp
00B81F21 mov ebp,esp
00B81F23 sub esp,0Ch
return main(__argc, __argv, _get_initial_narrow_environment());
00B81F26 call __get_initial_narrow_environment (0B8129Eh)
00B81F2B mov dword ptr [ebp-4],eax
00B81F2E call ___p___argv (0B812A8h)
00B81F33 mov eax,dword ptr [eax]
00B81F35 mov dword ptr [ebp-8],eax
00B81F38 call ___p___argc (0B81069h)
00B81F3D mov ecx,dword ptr [eax]
00B81F3F mov dword ptr [ebp-0Ch],ecx
00B81F42 mov edx,dword ptr [ebp-4]
00B81F45 push edx
00B81F46 mov eax,dword ptr [ebp-8]
00B81F49 push eax
00B81F4A mov ecx,dword ptr [ebp-0Ch]
00B81F4D push ecx
00B81F4E call _main (0B812D5h)
00B81F53 add esp,0Ch
}
00B81F56 mov esp,ebp
00B81F58 pop ebp
00B81F59 ret