基本使用堆栈
我目前正在学习堆栈(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