堆栈框架在我的函数中看起来如何?

时间:2014-03-08 12:01:04

标签: c assembly x86

我是汇编的初学者,我很想知道堆栈帧在这里是怎样的,所以我可以通过理解而不是算法来访问参数。

P.S。:汇编函数是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); 

所以,我知道当我想访问汇编中的process函数的参数时,我必须执行以下操作:

push ebp

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

pushad

mov ebx, dword [ebp+8]

现在我也希望有人在我认为正确的事情上纠正我:

  
      
  1. 在开始时,esp指向函数的返回地址,[esp + 8]是其下的堆栈中的插槽,这是函数的参数

  2.   
  3. 由于函数进程有一个参数而没有内部声明(不确定声明),因此堆栈帧从高到低,参数为8个字节,返回地址为8个字节。

  4.   

谢谢。

2 个答案:

答案 0 :(得分:3)

除了通过调试器之外,没有办法告诉别的。您正在使用ia32约定(ebp,esp)而不是x64(rbp,rsp),但期望int /地址为64位。这是可能的,但不太可能。

编译程序(gcc -O -g foo.c),然后运行gdb a.out

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

打破进程;跑;拆卸;检查寄存器值并转储堆栈。

- 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

然后添加更多参数,第二个子程序或具有已知值的局部变量。 printf例程的单步。堆栈在那里看起来像什么?

你也可以使用gdb作为计算器: sp rax 之间的区别是什么?
如果您想知道,那就是print $sp - $rax

答案 1 :(得分:0)

勾选您的编译器以生成汇编程序输出(在Unixy系统上通常带有-S标志)。使用调试/非调试标志,调试器的额外提示可能有助于引用回源。不要给出优化标志,编译器完成的重组会导致彻底的混淆。添加一个简单的函数调用代码,看看它是如何设置和拆除的。