我对 Printf 函数中的参数感到困惑

逆向工程 拆卸 数据库
2021-06-14 19:01:17

我正在尝试了解呼叫约定等。我用源代码创建了一个函数

#include <stdio.h>
int main() {
  int x = 9;
  printf("%d\n", x);
}

gdb 中的输出是以下屏幕截图:

上面的截图是它的拆解。

我有两个问题:

  1. 在什么地方0x405044来的呢?
  2. 0x405044esp 的内存地址中为什么会存储 的内容
2个回答

0x405044 是格式字符串的地址。您可以使用x/s 0x405044It 将这个地址存储在 esp 中打印字符串,因为它是您的第一个参数。

除了 defragger 所说的之外,还有几件事需要注意(当您正在学习调用约定时)。这是 32 位 x86 调用约定 (C) 的示例。

  • 在子程序调用之前,调用者将调用者保存的寄存器保存在堆栈上(寄存器 eax、ecx、edx - “如果需要”)
  • 然后它以倒序将子程序参数压入堆栈(在您的情况下,为 9 和“%d\n”的地址)
  • 然后调用子程序(返回地址压栈顶)
  • 返回后(返回值进入 eax),调用者移除参数,恢复堆栈并恢复调用者保存的寄存器。

现在我相信你因为“42a”和“42e”指令(mov)而感到困惑。您必须熟悉“push”指令 - 这几乎等同于 (sub esp, 4; mov [esp], reg32 - (这也会影响与 push 不同的标志))