1. Function creation
1.1 Call of main function
We assume that this rectangular area is the stack area .
When a function is called, a series of actions will occur in the stack area. Next, let’s study together:
Take a simple addition function as an example:
#include <stdio.h>
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 3;
int b = 5;
int ret = 0;
ret = Add(a, b);
printf("%d\n", ret);
return 0;
}
When running this function, obviously we need to call the main function first, and then call the Add function.
However, the main function is not called directly, it is called by a function called mainCRTStartup , and this function is called by the function of __tmainCRTStartup , the logic inside is a bit cumbersome.
As shown in the picture:
1.2 esp and edp registers
Next, we need to understand two registers: esp and ebp , which are pointers to the top of the stack (esp) and the bottom of the stack (ebp) respectively , and are used to maintain the operation of the function . That is to say, the range of activities of the function depends on the distance between the two of them. The larger the space, the larger the space used when calling the function. Every time a function is created, they will open up space one by one. When the function needs to be destroyed or narrowed down , they will also adjust their positions to achieve the purpose of calling and destroying.
1.3 Open up space for the main function
Next, let's analyze the disassembly code :
int main() {
002718A0 push ebp
002718A1 mov ebp,esp
002718A3 sub esp,0E4h
002718A9 push ebx
002718AA push esi
002718AB push edi
002718AC lea edi,[ebp-24h]
002718AF mov ecx,9
002718B4 mov eax,0CCCCCCCCh
002718B9 rep stos dword ptr es:[edi]
002718BB mov ecx,27C003h
002718C0 call 0027131B
int a = 10;
002718C5 mov dword ptr [ebp-8],0Ah
int b = 20;
002718CC mov dword ptr [ebp-14h],14h
int c = 0;
002718D3 mov dword ptr [ebp-20h],0
We analyze sentence by sentence:
002718A0 push ebp
Push means to push the stack , that is to say, put ebp on the stack frame of the previous __tmainCRTStartup function
002718A1 mov ebp,esp
mov is the abbreviation of move, that is, the value of xx (behind) is assigned to xx (front), which means that the value of esp is assigned to ebp, that is, the stack top pointer of the original __tmainCRTStartup function is changed to the bottom pointer of the main function stack (this is the meaning, in fact, the register is itself, but the number has changed )
002718A3 sub esp,0E4h
sub means subtraction , subtract 0E4h from esp (this is a number) and because in the stack area, it is generally consumed from high addresses to low addresses (that is, address names and house numbers from high to low), so subtracting a number from esp is equivalent to expanding so much space to low addresses , as shown in the figure:
1.4 Initialize the inside of the main function
002718A9 push ebx
002718AA push esi
002718AB push edi
The above three are operations of pushing the stack . The three registers with different functions, ebx, esi, and edi, are pushed to the top one by one. The specific functions of these three registers will not be discussed here.
002718AC lea edi,[ebp-0E4h]
002718AF mov ecx,9
002718B4 mov eax,0CCCCCCCCh
002718B9 rep stos dword ptr es:[edi]
002718BB mov ecx,27C003h
The meaning of these five lines is: at ebp-24h, repeat 27C003 times, assign 0CCCCCCCCh, and open up a dword for each assignment, which is 4 bytes.
1.5 Create variables and assign values (in the main function)
int a = 10;
002718C5 mov dword ptr [ebp-8],0Ah
int b = 20;
002718CC mov dword ptr [ebp-14h],14h
int c = 0;
002718D3 mov dword ptr [ebp-20h],0
As mentioned earlier, mov means to assign the value of the latter to the former
, so these three lines of assembly language mean that 0Ah, which is 10 in hexadecimal; 14h, which is 20 in hexadecimal; 0, these three numbers are respectively assigned to ebp-8; ebp-14h;
- ebp-8, minus 8 is to add 2 double-byte spaces to the lower address
- ebp-14h, minus 20 is to add 5 double-byte spaces to the lower address
- ebp-20h, minus 32 is to add 8 double-byte spaces to the lower address.
As shown in the figure:
After the position in Figure 1 is found, the value will also be assigned to the corresponding space: Figure 2
1.6 Function parameter passing (Add function)
Then there is parameter passing. Here, a and b are called by value, that is, passing formal parameters . Let's take a look at his logic:
ret = Add(a, b);
00BE1850 mov eax,dword ptr [ebp-14h]
00BE1853 push eax
00BE1854 mov ecx,dword ptr [ebp-8]
00BE1857 push ecx
00BE1858 call 00BE10B4
00BE185D add esp,8
00BE1860 mov dword ptr [ebp-20h],eax
First, assign the number stored in the address of ebp-14h (b) to eax
, and then push eax onto the stack.
Similarly, assign the number stored in the address of ebp-8 (a) to ecx
, then push ecx to the stack
, then use call to call the Add function, and push the address of the next line of instruction onto the stack
(the top ebp in the figure is explained in the next paragraph)
as shown in the figure:
1.7 Add function call
Next, let's look at the logic of calling the Add function :
int Add(int x, int y)
{
00BE1760 push ebp
00BE1761 mov ebp,esp
00BE1763 sub esp,0CCh
00BE1769 push ebx
00BE176A push esi
00BE176B push edi
First, push the ebp (bottom pointer of the stack) to the top of the stack, so that the main function can be found when the function is finally destroyed;
then assign the value of esp to ebp, that is, move the bottom pointer of the stack to the same position as the top pointer of the stack ; then
subtract 0CCh from esp, and subtract the number from the top pointer of the stack, obviously to open up so much space for 0CCh ; finally, perform three push operations, esp also -4-4-4 , minus 12 in total to accommodate ebx, The three registers esi and edi. As shown in the picture:
1.8 Definition of Add function
Then let's look at the logic inside Add
int z = 0;
00BE176C mov dword ptr [ebp-8],0
z = x + y;
00BE1773 mov eax,dword ptr [ebp+8]
00BE1776 add eax,dword ptr [ebp+0Ch]
00BE1779 mov dword ptr [ebp-8],eax
The first line assigns a value to z, which is the same as the previous assignment operation, directly find the position of ebp-8, and assign 0 to it; the
key point is how to perform the addition operation:
- It can be seen that there is a register called eax, and this register is used for accumulation . It can safely bring the data back to the main function when the function is destroyed in the future ~
- ptr means a pointer, that is, its address
With this knowledge point, we can easily understand what the following three lines do: first save the number at the address of
ebp+8 (that is, the original formal parameter b) to the eax register (it was used for assignment before, but now it needs to be accumulated) and then add the number at the address of ebp+0Ch (that is, the original formal parameter a) to eax , and finally put the number stored in eax into ebp-8, and ebp-8 is not where z is located The address~ That is to say, eax puts the addition result stored by itself in z, as shown in the figure :
2. Destruction of functions
2.1 Destruction of Add function
Next, let's take a look at how the Add function is destroyed :
return z;
00BE177C mov eax,dword ptr [ebp-8]
}
00BE177F pop edi
00BE1780 pop esi
00BE1781 pop ebx
00BE1782 mov esp,ebp
00BE1784 pop ebp
00BE1785 ret
We know that ebp-8 is the position of z, so after the value stored in it is assigned to eax, because eax is a register, it will not disappear with the destruction of the function, so it can be brought back to the main function.
pop: Pop up , that is, esp+4, destroy the topmost space , and return the topmost space to the memory
. You can see that the three registers edi, esi, and ebx are popped up, and esp+4+4+4
then assigns the value of ebp to esp, that is, pulls down the pointer on the top of the stack and pulls it to the same position as the bottom pointer
of the stack
.
2.2 How to bring back the value after destruction
After returning to the function, let's take a look again. Since the function has been destroyed, how does it bring back the value of z?
00BE185D add esp,8
00BE1860 mov dword ptr [ebp-20h],eax
It can be seen that first esp directly adds 8, skipping the original formal parameters of a and b,
and then puts the value of eax in the address of ebp-20h , that is, in ret. So far, the entire process of calling and destroying the function is completed, and then there is the destruction of the main function. The reason is the same , so I will not explain it here.
write at the end
If this article is helpful to you, can you give me a little like ❤~ Your support is my biggest motivation.
The blogger is Xiaobai, with little talent and learning, and it is inevitable that there will be mistakes. Everyone is welcome to discuss and ask questions, and the blogger will correct it as soon as possible.
Thank you for watching hehe (๑•̀ㅂ•́)و✧~!