我是汇编的初学者,我很想知道堆栈帧在这里是怎样的,所以我可以通过理解而不是算法来访问参数。
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]
现在我也希望有人在我认为正确的事情上纠正我:
在开始时,esp指向函数的返回地址,[esp + 8]是其下的堆栈中的插槽,这是函数的参数
- 醇>
由于函数进程有一个参数而没有内部声明(不确定声明),因此堆栈帧从高到低,参数为8个字节,返回地址为8个字节。
谢谢。
答案 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
标志)。使用调试/非调试标志,调试器的额外提示可能有助于引用回源。不要给出优化标志,编译器完成的重组会导致彻底的混淆。添加一个简单的函数调用代码,看看它是如何设置和拆除的。