TheNotMe
TheNotMe

Reputation: 1058

How does the stack frame look like in my function?

I am a beginner at assembly, and I am curious to know how the stack frame looks like here, so I could access the argument by understanding and not algorithm.

P.S.: the assembly function is process

#include <stdio.h>
# define MAX_LEN 120     // Maximal line size

extern int process(char*);

int main(void) {
  char buf[MAX_LEN];   
  int str_len = 0;

  printf("Enter a string:");  
  fgets(buf, MAX_LEN, stdin);
  str_len = process(buf); 

So, I know that when I want to access the process function's argument, which is in assembly, I have to do the following:

push ebp

mov ebp, esp ; now ebp is pointing to the same address as esp

pushad

mov ebx, dword [ebp+8]

Now I also would like someone to correct me on things I think are correct:

  1. At the start, esp is pointing to the return address of the function, and [esp+8] is the slot in the stack under it, which is the function's argument

  2. Since the function process has one argument and no inner declarations (not sure about the declarations) then the stack frame, from high to low, is 8 bytes for the argument, 8 bytes for the return address.

Thank you.

Upvotes: 0

Views: 388

Answers (2)

vonbrand
vonbrand

Reputation: 11831

Tickle your compiler to produce assembler output (on Unixy systems usually with the -S flag). Play around with debugging/non-debugging flags, the extra hints for the debugger might help in refering back to the source. Don't give optimization flags, the reorganizing done by the compiler can lead to thorough confusion. Add a simple function calling into your code to see how it is set up and torn down too.

Upvotes: 0

Aki Suihkonen
Aki Suihkonen

Reputation: 20087

There's no way to tell other than by means of debugger. You are using ia32 conventions (ebp, esp) instead of x64 (rbp, rsp), but expecting int / addresses to be 64 bit. It's possible, but not likely.

Compile the program (gcc -O -g foo.c), then run with gdb a.out

 #include <stdio.h>
 int process(char* a) {  printf("%p", (void*)a); }
 int main()
 {
      process((char *)0xabcd1234);
 }

Break at process; run; disassemble; inspect registers values and dump the stack.

- break process
- run
- disassemble
- info frame
- info args
- info registers
- x/32x $sp - 16   // to dump stack +-16 bytes in both side of stack pointer

Then add more parameters, a second subroutine or local variables with known values. Single step to the printf routine. What does the stack look like there?

You can also use gdb as calculator: what is the difference in between sp and rax ?
It's print $sp - $rax if you ever want to know.

Upvotes: 3

Related Questions