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 = 0018FF44h00401021 mov ebp,esp // ebp保存栈顶0,ebp=esp=0018FF44h00401023 sub esp,48h // esp -= 48h开辟了一段栈空间,留待后面保存局部变量,此时esp=0018FF44h-48h=0018FEFCh00401026 push ebx 00401027 push esi00401028 push edi // ebx、esi和edi压栈,esp = 0018FEFCh - 4*3 = 0018FEF0h00401029 lea edi,[ebp-48h] // lea指令将ebp-48h作为偏移地址保存在edi中,edi=0018FEFCh,即栈中ebx的上面0040102C mov ecx,12h 00401031 mov eax,0CCCCCCCCh00401036 rep stos dword ptr [edi] // 将eax重复保存在以edi开始的栈空间里,重复次数为ecx次,向高地址方向,共覆盖12h*4=48h个地址,即栈中保存ebx的地址以上到ebp指向的地址这一段全部填充为cch9: int i = 4;00401038 mov dword ptr [ebp-4],4 // 保存变量i10: int j = 5;0040103F mov dword ptr [ebp-8],5 // 保存变量j11: m = fun(i, j);00401046 mov eax,dword ptr [ebp-8] // 将j保存在eax中00401049 push eax // eax压栈, esp=0018FEF0h-4=0018FEECh0040104A mov ecx,dword ptr [ebp-4] // 将i保存在ecx中0040104D push ecx // ecx压栈,esp=0018FEECh-4=0018FEE8h0040104E call @ILT+0(_fun) (00401005) // 以上实际上是为形参分配内存,顺序从右到左,此步进行函数跳转00401053 add esp,8 // 形参的地址回收,esp=0018FEE8h+8=0018FEF0h00401056 mov [_m (00424a30)],eax // 返回值存放在静态变量m中12: return 0;0040105B xor eax,eax // 返回值置为013: }0040105D pop edi0040105E pop esi0040105F pop ebx00401060 add esp,48h00401063 cmp ebp,esp00401065 call __chkesp (004010d0)0040106A mov esp,ebp0040106C pop ebp0040106D ret |
The assembly code understanding of the fun function
| 123456789101112131415161718192021222324252627 |
15: int fun(int a, int b)16: {00401090 push ebp00401091 mov ebp,esp00401093 sub esp,44h00401096 push ebx00401097 push esi00401098 push edi00401099 lea edi,[ebp-44h]0040109C mov ecx,11h004010A1 mov eax,0CCCCCCCCh004010A6 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] // 返回值存放在eax20: }004010BB pop edi // 现场恢复004010BC pop esi004010BD pop ebx004010BE mov esp,ebp // 当前函数栈空间回收,以后可重新分配,esp=0018FEE8h004010C0 pop ebp // ebp恢复为0018FF44h004010C1 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