【问题标题】:Allocating variables on the stack in x86 assembly. rbp and rsp vs esp and ebp在 x86 程序集的堆栈上分配变量。 rbp 和 rsp 与 esp 和 ebp
【发布时间】:2017-07-18 06:11:27
【问题描述】:

我最近一直在学习汇编,并决定反汇编一些我自己的可执行文件来学习。我注意到在线资源经常引用 esp 和 ebp、堆栈和基指针。我写了这个程序:

int comp(int a, int b) {
    return a == b;
}
int main() {
    int a = 1;
    int b = 2;
    comp(a, b); 
}

而在 Radare 2 中,这会分解为:

0x0040050e    55           push rbp
|           0x0040050f    4889e5       mov rbp, rsp
|           0x00400512    4883ec10     sub rsp, 0x10
|           0x00400516    c745f801000. mov dword [rbp-0x8], 0x1
|           0x0040051d    c745fc02000. mov dword [rbp-0x4], 0x2
|           0x00400524    8b55fc       mov edx, [rbp-0x4]
|           0x00400527    8b45f8       mov eax, [rbp-0x8]
|           0x0040052a    89d6         mov esi, edx
|           0x0040052c    89c7         mov edi, eax
|           0x0040052e    e8c3ffffff   call sym.comp
|              sym.comp(unk)
|           0x00400533    b800000000   mov eax, 0x0
|           0x00400538    c9           leave
\           0x00400539    c3           ret

为什么要使用 rbp 和 rsp?这只是我的编译器喜欢做事的方式吗?还有,为什么是 rbp-value 在栈上创建空间,不应该是 rbp+value 来分配更多空间吗?

【问题讨论】:

  • 这只是 32 位 (esp,ebp) 与 64 位 (rsp,rbp)
  • 你能解释为什么它的基指针 - 一个值而不是加法吗?我认为 ebp 是堆栈的底部。
  • 我不明白你的意思,但是 ebp/rbp(通常)标记了当前函数的新堆栈帧的开始(顶部地址)。
  • rbp+value 是函数参数,当使用堆栈时(不在 64b ABI 中,sym.comp 的参数在 ediesi 中,不在堆栈中)。 rbp-value 是局部变量(由sub rsp,<bytes_to_allocate> 分配)...[rbp+0] = 旧rbp[rbp+8] 是返回地址。
  • 如果在没有开启优化的情况下进行编译,编译器经常会生成愚蠢的代码。你期待什么?

标签: assembly x86 reverse-engineering ida


【解决方案1】:

您正在为 64 位编译,所以 rbprsp 只是 32 位 ebpesp 变量的 64 位等价物。即使在 64 位代码中,您也经常会看到尽可能使用 32 位 (e**) 寄存器 - 但您通常不会看到 rsprbp 的情况1 因为它们持有几乎总是需要为 64 位的指针。

由于rbp 指向堆栈帧的底部(即函数入口处的堆栈顶部)并且x86 上的堆栈向下增长(朝向较低地址),因此本地参数将在相对于rbp 的负地址访问。


1 您可能偶尔会在 64 位代码中看到 ebp,但这只是因为编译器已将其从通常的帧指针职责中解脱出来,只是将其用作另一个 GP 寄存器。

【讨论】:

    猜你喜欢
    • 2012-12-20
    • 1970-01-01
    • 2015-10-07
    • 2017-04-24
    • 2020-12-28
    • 2011-07-25
    • 2015-02-03
    • 2011-08-23
    相关资源
    最近更新 更多