【问题标题】:How does the stack frame look like in my function?我的函数中的堆栈框架如何?
【发布时间】:2014-03-08 12:01:04
【问题描述】:

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

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. 由于函数进程只有一个参数,没有内部声明(不确定声明),那么堆栈帧从高到低,8字节为参数,8字节为返回地址。

谢谢。

【问题讨论】:

  • 这对我来说似乎是正确的。

标签: c assembly x86


【解决方案1】:

除了通过调试器之外没有其他方法可以判断。您正在使用 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作为计算器:sprax有什么区别?
如果您想知道,请联系print $sp - $rax

【讨论】:

    【解决方案2】:

    让你的编译器产生汇编输出(在 Unixy 系统上通常带有-S 标志)。使用调试/非调试标志,调试器的额外提示可能有助于参考源代码。不要给出优化标志,编译器所做的重组会导致彻底的混乱。在您的代码中添加一个简单的函数调用,以查看它是如何设置和拆除的。

    【讨论】:

      猜你喜欢
      • 2012-04-26
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      相关资源
      最近更新 更多