Prior Knowledge
- Static variables are stored in static storage, local variables are stored in dynamic storage (stacks), code is stored in code area
- Register, EBP points to the bottom, esp points to the top of the stack, the EIP points to the next instruction that is executing the instruction, three registers are stored in the address, 32-bit system, the address is 4 bytes is a DWORD
- All statements written in the function definition are compiled into instructions (drive CPU)
Experiment Code
123456789101112131415 |
#include <stdio.h>
int fun(
int a,
int b);
int m = 10;
int main()
{
int i = 4;
int j = 5;
m = fun(i, j);
}
int fun(
int a,
int b)
{
int c = 0;
c = a + b;
return c;
}
|
This code contains two functions, so you can test function calls, and also include static variables, local variables, return values, etc.
Experimental testTest Tool: VC6.0the source code and the corresponding assembly are as followsregisters and memory status are as follows EBP Stack Top initial value is 0018ff84h,esp initial to 0018ff48hThe role of ESP and EBP in stacks
There are two statements at the beginning of each function
There are also two statements before the function returns
Each run a function to open a new stack of space, so-called open stack space is moving the EBP stack, before moving EBP, save the upper level of the stack of functions through the push EBP, and then use EBP point to the stack top of the function stack, that is, the current function to open the stack, and then to the local variable address assignment and save the site , the ESP moves to the low address, and when the function call ends, ESP refers back to the top of the stack (mov esp,ebp) of the current function, and then the stack top address of the upper function is stored in EBP (pop ebp). Therefore, the top of the stack of each function holds the top-level address of the upper function, which can be used to return the stack of functions at the end of the current function, and to maintain the stack through EBP and ESP and the stack stack operation.
Analysis
The assembly code corresponding to the main function is as follows
123456789101112131415161718192021222324252627282930313233343536 |
7:
int main()
8: {
00401020 push ebp
// ebp初始为0018FF84h压栈,压栈后esp = 0018FF48h - 4 = 0018FF44h
00401021 mov ebp,esp
// ebp保存栈顶0,ebp=esp=0018FF44h
00401023 sub esp,48h
// esp -= 48h开辟了一段栈空间,留待后面保存局部变量,此时esp=0018FF44h-48h=0018FEFCh
00401026 push ebx
00401027 push esi
00401028 push edi
// ebx、esi和edi压栈,esp = 0018FEFCh - 4*3 = 0018FEF0h
00401029 lea edi,[ebp-48h]
// lea指令将ebp-48h作为偏移地址保存在edi中,edi=0018FEFCh,即栈中ebx的上面
0040102C mov ecx,12h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
// 将eax重复保存在以edi开始的栈空间里,重复次数为ecx次,向高地址方向,共覆盖12h*4=48h个地址,即栈中保存ebx的地址以上到ebp指向的地址这一段全部填充为cch
9:
int i = 4;
00401038 mov dword ptr [ebp-4],4
// 保存变量i
10:
int j = 5;
0040103F mov dword ptr [ebp-8],5
// 保存变量j
11: m = fun(i, j);
00401046 mov eax,dword ptr [ebp-8]
// 将j保存在eax中
00401049 push eax
// eax压栈, esp=0018FEF0h-4=0018FEECh
0040104A mov ecx,dword ptr [ebp-4]
// 将i保存在ecx中
0040104D push ecx
// ecx压栈,esp=0018FEECh-4=0018FEE8h
0040104E call @ILT+0(_fun) (00401005)
// 以上实际上是为形参分配内存,顺序从右到左,此步进行函数跳转
00401053 add esp,8
// 形参的地址回收,esp=0018FEE8h+8=0018FEF0h
00401056 mov [_m (00424a30)],eax
// 返回值存放在静态变量m中
12:
return 0;
0040105B xor eax,eax
// 返回值置为0
13: }
0040105D pop edi
0040105E pop esi
0040105F pop ebx
00401060 add esp,48h
00401063 cmp ebp,esp
00401065 call __chkesp (004010d0)
0040106A mov esp,ebp
0040106C pop ebp
0040106D ret
|
The assembly code understanding of the fun function
123456789101112131415161718192021222324252627 |
15:
int fun(
int a,
int b)
16: {
00401090 push ebp
00401091 mov ebp,esp
00401093 sub esp,44h
00401096 push ebx
00401097 push esi
00401098 push edi
00401099 lea edi,[ebp-44h]
0040109C mov ecx,11h
004010A1 mov eax,0CCCCCCCCh
004010A6 rep stos dword ptr [edi]
// 以上理解同main函数,ebp压栈时保存的地址是0018FF44h,即main函数栈开始开始的地方,然后ebp指向当前函数栈开始的地方
17:
int c = 0;
004010A8 mov dword ptr [ebp-4],0
// 为c分配地址,并赋值
18: c = a + b;
004010AF mov eax,dword ptr [ebp+8]
// 获得第一个参数
004010B2 add eax,dword ptr [ebp+0Ch]
// 与第二个参数求和
004010B5 mov dword ptr [ebp-4],eax
// 结果保存在c中
19:
return c;
004010B8 mov eax,dword ptr [ebp-4]
// 返回值存放在eax
20: }
004010BB pop edi
// 现场恢复
004010BC pop esi
004010BD pop ebx
004010BE mov esp,ebp
// 当前函数栈空间回收,以后可重新分配,esp=0018FEE8h
004010C0 pop ebp
// ebp恢复为0018FF44h
004010C1 ret
// 返回,等待执行函数调用的下一条指令
|
Memory condition when calling the fun function
Local Variables I and J are saved at the beginning of the 48h space ( high Address ), near the bottom of the stack, such as before calling the fun function, press the parameter from right to left , such asperform a jump when the call fun functionReferenceExperimental code from the national hkust Yang Lixiang Teacher's Open source compiler source code Analysis course
Example analysis of memory structure of C program runtime