Skip to content

Assembly functions and stacks

Assembly functions and stacks

Prerequisites :
– Knowledge of stack data structure
– Basics of assembly language

At the end of this tutorial, you should be able better understand how the stack works with different operands in assembly, and their typical use case.

The stack is a place to store temporary data, such as local variables or passing of parameters from one function to another. Keeping in mind that a stack follows a last-in first-out(LIFO) order, lets proceed to see how each operand work with the stack in the scenarios below

 

Scenario 1 : A typical function prologue

In this scenario, a new stack frame for the current function is created

 push ebp      // save the value of ebp on the stack.
 mov ebp, esp  // copy esp into ebp
 sub esp, 0x10 // size of local variables

 

Scenario 2 : A typical function epilogue

In this scenario, the stack frame is restored as the function before returning to the caller function

 mov esp, ebp // Copy ebp into esp
 pop ebp      // Restore ebp (earlier we pushed it)
 ret          // Return to caller function

 

Scenario 3 : A function call with no args

In this scenario, we will unpack the call operand in assembly

call foobar // foobar();

A call operand does two things –

push return_address_after_callee_is_done // esp - 4
jmp foobar

As you can see, the return address is saved so the called function knows where to return to in the program’s execution flow, before actually jumping to it.

ret foobar_caller // esp + 4

A ret instruction does two things

pop eip // return_address_after_callee_is_done is pop into eip; esp + 4
jmp eip 

Sometimes, you will see a ‘ret 0x8’ or ‘ret 8h’

ret 0x8 
a normal ret increases esp by 4, this further adds 8 to esp, so in total esp + 0xC. So if its 'ret 0x4' - it increases by esp by 8

Scenario 4 : A function call with args

In this scenario, we will see how the argument of a function call interacts with the stack.

Take arg1 to be a 4-byte value

  push arg1   // save arg1 on the stack . esp-4 after this operation
  call foobar // foobar(arg1);            esp-4 (see scenario 3)

foobar:
  push ebp
  mov ebp, esp
  // [ebp+0x4] will contain our return address
  // [ebp+0x8] will contain arg 1
  mov eax, [ebp+0x8]   
  pop ebp
  ret 0x4 // earlier esp-4 twice, so here esp+4 twice also

Scenario 5 : A function call with multiple args

In this scenario, we will see how the arguments of a function call interacts with the stack. (note: the calling convention assumed here is _stdcall)

Take arg1, arg2 to be a 4-byte value

push arg2   // save arg2 on the stack. esp-4 after this operation
push arg1   // save arg1 on the stack. esp-4 after this operation
call foobar // foobar(arg1, arg2);     esp-4 (see scenario 3)

foobar:
  push ebp
  mov ebp, esp
  // [ebp+0x4] will contain our return address
  // [ebp+0x8] will contain arg 1
  // [ebp+0xC] will contain arg 4
  mov eax, [ebp+0x8] 
  pop ebp
  ret 0x8 // Earlier esp-4 thrice, so now esp+8+4

 

CONCLUSION
Of course, there are a million and one ways the stack is used by different operands and in different situation, so this list is definitely not exhaustive. Nonetheless, you should be more familiar with the typical use cases of the stack now

Enjoyed the content ? Share it with your friends !
Published inProgramming

Be First to Comment

Leave a Reply

Your email address will not be published.