1. What is a "stack"
The concept of "stack" refers to its access rules.
The definition of "stack" is that the last thing deposited is always the first to be removed.
As shown in the figure below, we put an integer data 18
and then put an integer data 20.
Note that the order we put in is 18 20 , but when the data is taken out, 20 comes out first, and 18 comes out later.
It's like when we put apples into a barrel, the last one put in is the first one to come out.
This is the main feature that distinguishes the stack from other structures, that is, "last in first out" (last in first out).
2. Implementation of "stack" in memory
在各种计算机系统中,最常见的栈实现方式如图所示。
它是由一段连续内存空间和一个寄存器(栈指针)组成。
栈指针是一个寄存器,它始终指向栈的顶部(即最近被压入的元素)。
每个被压入栈中的元素,在内存空间里占据一个独立的位置。
We put the data into the stack (an apple on top of another apple).
First, we push (PUSH) data 18, and the stack pointer TOP moves to point to the last pushed value.
We call popping (pop) data out of the stack (removing one apple from another).
In the above figure, we push the stack three times, pop the stack twice, and move the TOP pointer down twice to point to the last pushed value.
3. Creation and destruction of function stack frames
1. Let's understand the concept of registers first
2. Let's take the following code as an example
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d", c);
}
Each function call creates a space on the stack area.
Which function is being called, ebp and esp maintain the function stack frame of which function
Enter the main function, ebp and esp maintain the function stack frame of the main function
We press F10, right-click to go to the disassembly, you can see the following code
Since the main function is called by __tmainCRTStartup,
first allocate the function stack frame of __tmainCRTStartup.
Observe the disassembly, the first line has push ebp,
we push ebp into the stack, sep moves up to point to ebp, and
we look at the next line
mov ebp,esp
mov is to give the following value to the front,
esp stores the address, so ebp moves up to the position of esp
sub esp,0e4h
The esp address is reduced by 0e4h and moved up to a certain position at the low address as shown in the
figure below:
and the space between them is opened up for the main function.
We continue to go down:
Encounter three pushes, push three elements on top.
Continue down:
lea edi ebp-04eh
lea is Load effective address
eh, so familiar 04eh
mov ecx 39h
mov eax 0CCCCCCCCh
rep stos dword ptr es :[edi]
To initialize the 39h double word from just edi down to 0CCCCCCCCh,
we continue:
Place a at ebp-8 is
verified, and b and a are separated by two bytes
At this point, we understand how local variables are created.
First we create a function stack frame for the function call, find some space in the function stack frame, and put the variables in it.
Continue down:
mov eax,dword ptr [ebp-14h]
push eax
ebp-14h, isn't that b?
Put the value of b into eax and
push eax on the stack. The
same is true: the
call instruction calls the function, and pushes the address of the next instruction on the stack.
Enter the Add function
and perform the same processing, you can get:
give the value of ebp+8 to eax, isn't this the a that was pushed on the stack before?
Sum the value of ebp+12 and the value of ebp+8 to eax, this is not a+b Finally , pop
the value of ebp-8 (z) into register eax three times
mov esp,ebp
Assign ebp to esp, esp points to ebp
pop ebp
After pop, ebp returns to the bottom of the function stack frame of the main function,
esp moves down one bit, and returns to the top of the function stack frame of the main function
This space is in turn maintained by esp and ebp.
right
ret returns the address of the instruction following the call instruction.
add esp,8
At this point, esp+8, the space of a and b is destroyed
and z is passed out.