用汇编语言访问堆栈帧

Posted

技术标签:

【中文标题】用汇编语言访问堆栈帧【英文标题】:Accessing stack frames in assembly language 【发布时间】:2013-05-17 05:17:53 【问题描述】:

我是组装新手,然后我遇到了这个article

上面写着这段代码

void MyFunction()

  int a, b, c;
  a = 10;
  b = 5;
  c = 2;

等价于这个

push ebp     ; save the value of ebp
mov ebp, esp ; ebp now points to the top of the stack
sub esp, 12  ; space allocated on the stack for the local variables
mov [ebp -  4], 10  ; location of variable a
mov [ebp -  8], 5   ; location of b
mov [ebp - 12], 2   ; location of c

根据这个video,要访问基指针上方的堆栈值,我们应该添加。如果它低于指针,我们应该减去。鉴于上面的例子,他们从基指针中减去了一些东西来移动所需变量的位置,这与视频中的说明相反。

我错过了什么?我知道 sub esp, 12 正在为局部变量分配空间,所以我想到的是 EBP 低于该分配,所以我认为它应该是 [ebp + something] 而不是减号。

所以当他执行这个 sub esp, 12 时,堆栈就是这样的。

            ESP is here
|     2    | Ebp + 12
|     5    | Ebp + 8
|     4    | Ebp + 4
|          | Old EBP value

文章是错的,还是我误解了?

【问题讨论】:

【参考方案1】:

使用 ebp 的原因是 esp 会改变,例如将参数传递给子例程。因此,您的 ebp 将使您能够使用相同的偏移量访问相同的变量,无论 esp 在那一刻指向何处。

当你将值压入堆栈时,它的值会递减;弹出时增加。

代码减去 12 (4*3) 为 3 个 32 位(4 字节)整数腾出空间。 Ebp 指向“底部”, esp 之前所在的位置。因此,您使用负偏移量访问变量,例如ebp-4。所以你的图片是错误的:ebp+Whatever 指向你的代码不应该使用的东西。

     BEFORE

     lower address
     |
     |<--------------  esp (=ebp after mov ebp, esp)
     |
     | 
     higher address


     AFTER mov ebp, esp; sub esp, 12

     lower address
     |<--------------  esp
     |
     |
     |<--------------  ebp
     |
     | 
     higher address


     AFTER mov [ebp-4], 10 ecc.

     lower address
     | 2  <--------------  esp
     | 5
     | 10
     |<--------------  ebp
     |
     | 
     higher address

此时 [esp] 将检索 [ebp-12] 即 2。

【讨论】:

所以可以肯定地说视频中提到的内容是错误的?我已经掌握了 Stack 的概念,但是当我观看视频时,我感到很困惑。根据视频,要访问 Base 指针上方的值或任何内容,您应该向 EBP 添加一些内容。要从基指针下方访问任何内容,我们应该从 EBP 中减去。 ?? 我现在看不到视频;假设“以上”的意思是“递减地址”,答案很明显:要访问指针指向的“之前”(它是“以上”)的东西,您必须递减指针。反之亦然,您必须增加它。 (不清楚您的从下面访问任何内容的“来自”的含义...... 没关系。此外,除了那个视频,我读过的所有文章都说我需要这样做 [EBP - 不管] 以获得高于 EBP 的值。谢谢你。现在很清楚了。 :D【参考方案2】:

stack-pointer(基指针)地址正在向下“增长”,朝向地址空间中的较低地址。 例如,您的堆栈从 0x70000000 开始,当您在其上使用 push 时,esp (ebp) 将降低一个 dword -> 0x6ffffffc(如果我是正确的)。

请参阅here、here 和 here。

【讨论】:

以上是关于用汇编语言访问堆栈帧的主要内容,如果未能解决你的问题,请参考以下文章

C语言堆栈帧介绍

如何实现“无堆栈”解释语言?

在递归期间堆栈框架外观。 C vs汇编

如何使用 GDB 检查堆栈帧?

使用基于堆栈计算机的语言添加嵌套函数支持

怎么用C语言编写堆栈并能进行四则运算