我刚开始学习汇编,我和我的朋友对下面命令中到底发生了什么有不同的想法:推送1234 h我们的问题是:第一个数字(12)将进入堆栈的哪个位置?ss:[sp-2]?保安司:[保安司-4]?
rxztt3cl1#
假设你使用的是x86硬件(因为你指定了sp寄存器),字节将从高位(最高有效位)到低位(最低有效位)被压入。在这种情况下,它将压入字节12h,然后是字节34h。由于x86堆栈指针在你压入项时减小,内存布局看起来像这样:
sp
12h
34h
[sp+1] = 12h [sp] = 34h
如果将[sp]作为一个单词(两个字节)访问,则会得到原始值:
[sp] = 1234h
tvokkenx2#
信不信由你,但你们两个都可能是对的。字节顺序取决于机器的endianness。
nwlls2ji3#
在真实的模式下(看起来像是在为它编写程序),首先计算地址,公式非常简单:
address = (segment<<4)+offset
然后将此地址减去您尝试推送的元素的大小(word:2个字节,dword:4个字节,qword:第三步是在结果位置上写入数据。因此,如果SS是0x30并且SP是0xFF,则:
word
dword
qword
SS
0x30
SP
0xFF
address = (0x30<<4)+0xFF = 0x3FF
2
position = 0x3FF - 2 = 0x3FD
byte SS:[SP] = 0x34
byte SS:[SP+1] = 0x12
SP-x
SP+x
LGDT
SS!=0
SS*8
ESP*granularity+base < limit
base_of_segment+ESP
3条答案
按热度按时间rxztt3cl1#
假设你使用的是x86硬件(因为你指定了
sp
寄存器),字节将从高位(最高有效位)到低位(最低有效位)被压入。在这种情况下,它将压入字节12h
,然后是字节34h
。由于x86堆栈指针在你压入项时减小,内存布局看起来像这样:如果将[sp]作为一个单词(两个字节)访问,则会得到原始值:
tvokkenx2#
信不信由你,但你们两个都可能是对的。字节顺序取决于机器的endianness。
nwlls2ji3#
在真实的模式下(看起来像是在为它编写程序),首先计算地址,公式非常简单:
然后将此地址减去您尝试推送的元素的大小(
word
:2个字节,dword
:4个字节,qword
:第三步是在结果位置上写入数据。因此,如果SS
是0x30
并且SP
是0xFF
,则:address = (0x30<<4)+0xFF = 0x3FF
1.元素是单词,所以我们减去
2
:position = 0x3FF - 2 = 0x3FD
1.在结果位置写入数据(作为C指针):一米十纳米一x一米十一纳米一x
因此,
byte SS:[SP] = 0x34
和byte SS:[SP+1] = 0x12
。请注意,堆栈向下增长/扩展,因此不会有SP-x
,而是SP+x
。在保护模式下,事情有点复杂(我在这里只写使用段寄存器的过程):
1.首先,处理器获取全局描述符表描述符(由
LGDT
指令加载)的地址。1.处理器将段寄存器的值与GDT的大小进行比较(如果大于,则抛出异常)。它还检查段寄存器是否未指向空描述符(
SS!=0
)1.然后,处理器获取指向GDT条目的指针,并计算从GDT开始的偏移量(使用
SS*8
)。1.处理器必须检查一些事项:
4.1.段是否存在?4.2.我们是否有足够的权限访问段?4.3.是否为代码段?4.4.是否可写?4.5.是否为
ESP*granularity+base < limit
4.6.是否为系统段?1.然后通过
base_of_segment+ESP
计算地址。1.之后,它继续类似于真实的模式。