如何构造栈段描述符

如何构造栈段描述符

本文要讨论的是:对于x86保护模式(32位),已知栈空间的起始地址和结束地址,如何定义栈段描述符?ESP的初始为多少?

为了简化问题,设定约束条件如下:
1. 栈段向下扩展
2. B=1
3. G=1
4. 分页机制关闭

问题分析:数据段描述符的格式如下
如何构造栈段描述符_第1张图片
如果你不懂各个字段的含义,可以参考我的博文:
数据段描述符和代码段描述符(一)——《x86汇编语言:从实模式到保护模式》读书笔记10

根据约束条件,G=1,B=1,AVL可以设为0,P=1,DPL根据需要来设置,TYPE=0x06(可读可写,向下扩展);所以问题简化为求基地址和段限长,只要算出这两个字段,就可以顺利构造出栈段描述符。

假设我们已经有一片连续的物理内存,要把这段内存作为栈空间。设最低端的物理地址为LA,最高端的物理地址为HA,且栈空间大小为SIZE;如下图所示:
如何构造栈段描述符_第2张图片

设有效界限(Effect Limit)为EL;有效偏移(Valid Offset)为VO;
根据《Intel Architecture Software Developer’s Manual Volume 3:System Programming》第4.3节的说明(请注意黄色的字):

于是,可以知道VO的范围:

因为基地址加上偏移值才是实际的物理地址,假设描述符中的基地址为BA,那么可以得出:

(3)式减去(2)式得到:

又根据栈空间的大小为SIZE,可得出:

把(5)代入(4)式,消去HA-LA,得到:

也就是说,知道了栈空间的大小SIZE,就能算出EL

把(5)式代入(3)式,消去HA得到:


因为是32位的处理器,所以

把(8)式代入(7)式得:

也就是说,段描述符中的基地址BA等于栈空间的最低端地址LA加上栈空间的大小。

通过上面的推导,我们得出2个重要的公式

但是,栈段描述符中填写的界限值(这里用limit表示),并非是(6)式中的EL;当G=1(粒度为4KB)时,limitEL的关系为:

当栈空间的大小是4KB的整数倍时,我们可以设

把(10)和(11)式代入(6)式,消去ELSIZE,得

于是,我们知道描述符中的界限值该如何计算。

到这里,本文还没有结束,我们还要推导ESP的初始值(用ESP_INIT表示)。
第一次压栈的时候,比如

    push eax

首先,ESP的值减去4,然后把EAX的值写入偏移为[0xFFFF_FFFC,0xFFFF_FFFF]这四个单元。所以:

最后,重复我们的结论:

【end】

你可能感兴趣的:(保护模式,栈段描述符)