0

我刚开始学习组装,我的朋友和我对以下命令中究竟发生了什么有了不同的想法:

推 1234h

我们的问题是:第一个数字(12)将在堆栈中的哪个位置?
ss:[sp-2]?
ss:[sp-4]?

*sp =堆栈指针

4

3 回答 3

2

假设您正在谈论 x86 硬件(因为您指定了ss寄存器),字节将被推高顺序(最重要)到最低顺序(最不重要)。在这种情况下,它将推送 byte 12h,然后是 byte 34h。由于 x86 堆栈指针在您推送项目时会减少,因此内存布局将如下所示:

[sp+1] = 12h
[sp]   = 34h

如果您将 [sp] 作为一个单词(两个字节)访问,您将获得原始值:

[sp] = 1234h
于 2013-07-12T13:27:06.413 回答
1

信不信由你,但你们俩都可能是对的。字节顺序取决于您机器的字节顺序。

于 2013-07-12T10:34:01.860 回答
0

在实模式下(看起来你正在尝试为它编写程序),首先计算地址。公式很简单:

address = (segment<<4)+offset

然后这个地址减去你试图推送的元素的大小(word:2字节,dword:4字节,qword:8字节)。第三步是在结果位置上写入数据。因此,如果SS0x30SP 0xFF,那么:

  1. address = (0x30<<4)+0xFF = 0x3FF
  2. 元素是单词,所以我们减去2position = 0x3FF - 2 = 0x3FD
  3. 将数据写入结果位置(作为 C 指针):*(unsigned char*)position = LOBYTE(0x1234), *((unsigned char*)position+1) = HIBYTE(0x1234).

所以,byte SS:[SP] = 0x34byte SS:[SP+1] = 0x12。请注意,堆栈会向下增长/扩展,因此不会有SP-x, 但是SP+x.

在保护模式下,事情有点复杂(我将在这里只写使用段寄存器的过程):

  1. 首先,处理器获取全局描述符表描述符的地址(由LGDT指令加载)。

  2. 处理器将段寄存器的值与 GDT 的大小进行比较(如果更大,则抛出异常)。它还检查段寄存器是否没有指向空描述符(SS!=0

  3. 然后处理器获取指向 GDT 条目的指针,并计算从 GDT 开始的偏移量(使用SS*8)。
  4. 处理器必须检查一些事情:

    4.1。分段存在吗?4.2. 我们是否有足够的权限访问段?4.3. 是代码段吗?4.4. 可写吗?4.5. 是ESP*granularity+base < limit 4.6。是系统段吗?

  5. 然后它通过 计算地址base_of_segment+ESP

  6. 之后它继续类似于实模式。

于 2013-07-18T06:59:39.610 回答