基本使用堆栈

我目前正在学习堆栈(x86)。 我知道这是根据LIFO原则运作的一堆数据。 我知道关于堆栈的基本操作是push(在栈顶添加一个值)和pop(删除一个值)。 ESP是我们现在在堆栈中的参考。 现在,我不明白:

例:

  Push 4
  Push ebx
  Push eax

以上说明将生成一个堆栈,如下所示:

 8 eax <-- ESP
 4 ebx
 0 4

ESP指向最后一个增值eax。

现在,当我们用pop操作扩展这些指令时,我们会得到如下内容:

 Push 4
 Push ebx
 Pop ebx
 Push eax

上述说明应该在下面的堆栈中(如果我是正确的)(前三条说明):

 4 (ebx)
 0 4 <-- ESP

Ebx从堆栈中移出,ESP向下移动4位。 现在执行所有指令后的堆栈:

 4  eax <-- ESP
 0 4

我希望到这里的一切都是正确的,如果不是评论是欢迎的;-)现在的指令mov edx,[ebx,+ 04],从这篇文章的第一个堆栈开始。 是以下结果:

 16 eax
 8 edx <-- ESP
 4 ebx
 0 4

它将从ebx + 4位开始,写入edx,将先前的值(eax)移动到顶部,还是将其替换为edx的eax?

第二个问题是(更一般的)如何启动,寻址和删除堆栈上的数组。

我对这个长问题表示歉意,但我想了解(基础)堆栈。 谢谢。


你的例子和假设几乎是准确的。 问题是堆栈增长下降。 所以你有地址0和4和8的地方,而不是0xF8,0xF4,0xF0等。如果你在参考手册中的说明描述中会看到类似这样的内容:

PUSH:按操作数大小减少SP(两个或四个字节值符号扩展)并将一个字从源传送到堆栈顶端(SS:SP)。

所以如果sp(esp)在你启动时指向0xFC,那么你

push 4
push ebx
push eax

然后堆栈将如下所示:

0xFC 4
0xF8 (ebx)
0xF4 (eax) <-- esp

所以访问[esp + 4]现在可能更有意义,因为它检索(ebx)值,[esp + 8]是被推送的直接4。

因此,如果反汇编或编译汇编一些带有局部变量或数组的C程序,您将会看到,在输入函数时,它们会将一些数字减去堆栈指针,足以覆盖所有局部变量,然后[esp + something]是他们如何访问内存,所以初始化或调零或任何一个简单的基于ESP的寻址到堆栈中的问题。


我希望到这里的一切都是正确的,如果不是评论是欢迎的;-)现在的指令mov edx,[ebx,+ 04],从这篇文章的第一个堆栈开始。 是以下结果:

 16 eax
 8 edx <-- ESP
 4 ebx
 0 4

它将从ebx + 4位开始,写入edx,将先前的值(eax)移动到顶部,还是将其替换为edx的eax?

mov edx, [ebx + 4]会将值移到[ebx + 4] (这是一个指针顺序,除非ebx指向堆栈,否则它将与您的当前堆栈无关(高级:它可能指向堆栈,但引用它不会以任何方式更改堆栈))转换为edx 。 这看起来不同于你的理解不止一种方式。

首先,请记住mov指令的参数用作mov DEST, SRC ,而不是其他方式。

其次,这个mov操作只会将[ebx + 4]处的值移动到edx ,因此不会以任何方式改变堆栈指针(此处为ESP )。 该堆栈将与您在此处引用的第一个堆栈保持不变。 为了清楚起见,堆栈将保持为:

 8 eax <-- ESP
 4 ebx
 0 4

并且堆栈中的值都不会以任何方式进行更改。

另外,我假设你在32位体系结构上。 在这种情况下,像eax之类的寄存器将是32位(4字节)。 请记住这些是4个BYTES而不是BITS。

你的“第二个问题”属于它自己的问题,有更多的信息。 祝你好运!


mov edx, [ebx+04]获取地址es:ebx + 04处的数据并将其放入edx。 也许你的意思是mov [ebx+04], edx ? 在这种情况下,它将覆盖地址es :ebx+4 。 假设es指向堆栈段,并且ebx等于esp,那么堆栈将如下所示:

12 edx    <-- [ebx+4]
8  edx    <-- esp = ebx
4  ebx
0  4
链接地址: http://www.djcxy.com/p/84351.html

上一篇: Basic usage stack

下一篇: C Issues with Stack of Strings