Parameter Stack for Function C alls (Detailed)

Posted by saad|_d3vil on Sat, 05 Mar 2022 01:19:36 +0100


In earlier learning, we learned that when a function passes a value to call a parameter, it uses a parameter.

A parameter is a temporary copy of an argument, and changes to the parameter do not affect the values in the argument.

Pass-by and Address Calls 👉 Click on me

Today let's take a look at the argument stack of function calls in assembly language

1. What is a stack area?

A stack is a data structure.

In memory, there are three zones: stack, stack, and static.

Heap areas are mainly used for dynamic memory management and have been described in previous blogs.

Detailed Dynamic Memory Management 👉 Click on me

The stack is the space allocated by the compiler to run the function.

Unlike heap space, which needs to be allocated manually, this part of space is managed automatically by the compiler, and stack frames of functions are created and destroyed automatically.

1.1 small knowledge point of stack area

  • Stack areas are used from high to low addresses
  • Use of stack areas follows FIFO, LIFO
  • Stack area placement is from high address to low address placement: push stack
  • Delete from low to high: pop out of stack

2. Knowledge Points

//Code used this time
#include <stdio.h>
int Add(int x, int y)
	int z = 0;
	z = x + y;
	return z;

int main() 
	int a = 10;
	int b = 20;

	int c = Add(a, b);
	printf("%d\n", c);
	return 0;

2.1 Register

Common registers are eax, ebx, ecx, edx, among which ebp and esp are more special

The two registers, ebp and esp, store addresses that maintain the function stack frame

  • eax/ebx/ecx/edx: Universal register, keep temporary data
  • ebp: stack low pointer
  • esp: stack top pointer
  • eip: Instruction register that holds the address of the next instruction for the current instruction

2.2 Main function call

Each function call creates a space in the stack

We know that the main function is the entry to the program

In fact, the main function is also called by other functions

  • mainCRTStartup function call_u tmainCRTStartup
  • _u The tmainCRTStartup function calls the main function

The compiler first opens up a portion of space at the high memory address for mainCRTStartup and u tmainCRTStartup functions, which call the main function.

In VS2019, press F10 to debug, after the small yellow arrow appears, right-click to go to disassembly to open the display interface of assembly language in debugging

3. Explain item by item

3.1 Start with main

Let's start with the first part of the code, explaining it sentence by sentence

push  ebp//Open up space at the top of the stack to store the corresponding value of the ebp register
mov  ebp,esp//Pass the value of esp into ebp (that is, move the ebp pointer to where it was originally pointed)
sub  esp,0E4h//Subtract the contents of the ESP by 0E4h (move the ESP to the location of the original esp-0E4h)
push ebx//Place ebx on top of stack
push esi//Place esi on top of stack
push edi//Place edi on top of stack

  • lea:load effecticve address Load valid address
  • dword:double word - 4 bytes
lea  edi,[ebp-24h]//Put the ebp-24h address in edi
mov  ecx,9//Put 9 in ecx, corresponding to decimal 36
mov  eax,0CCCCCCCCh//Put 0CCCCCCh into eax
rep stos  dword ptr es:[edi]//Initialize all data for edi down ecx address to 0CCCCCCh

Press F10 down, after rep step, you can see that 36 bytes of data have been initialized to 0CCCCCCh

Continue running to see how the compiler initializes variables a and b

  • VS2019 is a small-end storage

	int c =Add(a,b);
mov    eax,dword ptr [b]//Put the contents of b into eax
push   eax  //Place eax on top of stack
mov    ecx,dword ptr [a]//Put the contents of a into ecx
push   ecx  //Place ecx on top of stack
call   _Add (01A10B4h) //Place this address at the top of the stack (the address of the next instruction under the call instruction) 

This last call is critical and will be used later

3.2 Call Add

Press F11 to enter the Add function

push    ebp//Move ebp up
mov     ebp,esp//Put esp content into EBP (mobile ebp)
sub     esp,0CCh//esp+0CCh (opens up space for Add)
push    ebx//Place ebx on top of stack
push    esi//Place esi on top of stack
push    edi//Place edi on top of stack
lea      edi,[ebp-0Ch]//ebp-0Ch space  
mov      ecx,3//3 Save in ecx  
mov      eax,0CCCCCCCCh//Save in eax  
rep stos  dword ptr es:[edi]//Spatial initialization of esp down 0ch
mov      ecx,offset _6A27082D_test@c (024C003h)  
call     @__CheckForDebuggerJustMyCode@4 (024131Bh)

Continuing down, the register initializes the data at the Z address to zero

mov    eax,dword ptr [x]//Put the value of x into eax
add    eax,dword ptr [y]//Add the value of y to eax, which is x+y   
mov    dword ptr [z],eax//Put the value of eax into the variable z

	return z;
mov    eax,dword ptr [z]//Put the value of parameter z into eax 

pop     edi//Delete stack pop esi//pop directive created for edi puts ESI value into ESI (equal to unchanged) pop ebx//every pop, ESP adds ESP once to high displacement, 0CCh//esp address+0CCh, that is, the stack space CMP ebp exiting Add program, esp//compares ESP value with ebp

call        __RTC_CheckEsp (0241244h)  mov         esp,ebp//ebp is assigned to esp, where ESP and ebp are the same

pop         ebp//Eject ebp  

When the pop-up command is executed here

  • Assigns the start address of the main function pointed to by ebp to the ebp pointer
  • Move the esp pointer one bit higher

The final result is that esp and ebp restart maintaining the stack space of the main function as shown in the following figure

3.3 Return to main function


Call_mentioned earlier The Add (01A10B4h) command is very important. In fact, when the ret command is executed, the esp pointer points to the address of the next command for the call command stored on the top of the stack, and this address is also pop ped away.

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-yj4OazoR-1646413319866)(.../.../.../.../AppData/Roaming/Typora/typora-user-images/image-20220304235511090.png)]

Back in the debugging interface, you can see that the small yellow arrow does point to the next call instruction

This command means to add 8 bytes to the esp, that is, to move 8 bytes high.

In fact, this command is destroying our parameters

mov      dword ptr [c],eax//Put the value in eax into variable c  

Here eax stores the return value of the Add function

Here we can draw a conclusion:

The return value of a custom function is returned to the main function through the register, an intermediate "variable".

  • Put the return value in register A first
  • The main function takes the return value from register A and places the variable that accepts the return value.

Continuing down, you can see printf ('%d\n', c); After the statement, the compiler again put the value of variable C back to eax

In fact, this is where the printf function runs:

  • Put the variable to be printed in eax first
  • Push eax on top of stack
  • offset string "%d\n" (guess is data type check)
  • _ Printf: execute the printf function

add  esp,8//Give esp+8 bytes

I was confused about this part and debugged the discovery again

  • The push eax directive takes esp four bytes to the low address
  • The offset string'%d\n'directive also lowered esp by four bytes

After executing this command, esp returns to the address before printf was executed

3.4 End Procedure

	return 0;xor    eax,eax//The xor directive is xor--the role here is unclear}pop edi//stack--esp corresponds to moving pop esi//pop ebx//  

add    esp,0E4h//esp+0E4h (exit space for main function) CMP ebp, esp//compare EBP and ESP  

call   __RTC_CheckEsp (0241244h)  
mov    esp,ebp//Copy ebp values to esp 
//The esp and ebp values are still the same at this point    

pop    ebp//ebp stacking--esp and ebp separation
ret//End of main function  

4. Summary of assembly language in this blog

  • mov: Data transfer instructions

  • push: the data is stacked while the esp stack top register moves down

  • pop: data pops up to the specified location, while the esp stack top register moves up

  • sub: subtraction

  • add: addition

  • Call: function call. 1. Push the return address; 2. Going to the objective function

  • jump: Modify the eip, go to the target function, and call

  • ret: Reply with the return address, press in the eip, similar to the pop eip directive

  • cmp (comparison): Performs an implicit subtraction operation that subtracts the source operand from the destination operand without modifying any operands

  • Xor: Performs (bitwise) logical exclusive or (XOR) operations between the corresponding bits of two operands and stores the results in the target operand

Partial assembly instructions reference: C Language Chinese Network

5. Conclusion

By the time this blog was completed, it was already Saturday at 00:54 🌛

I've been writing for so long unconsciously since 19:20 on Friday

This part of the function call stack is a bit obscure. Writing this blog is a bit of a clarification.

Come on.

Can't stand it anymore, go to sleep

Ironically, several roommates are still fighting a 300 million Mouse gun battle dream...

Topics: C