WEB开发网
开发学院软件开发汇编语言 汇编教程:控制转移(2) 阅读

汇编教程:控制转移(2)

 2009-02-16 09:36:49 来源:WEB开发网   
核心提示:2.堆栈切换在使用CALL指令通过调用门向内层转移时,不仅特权级发生变换,汇编教程:控制转移(2)(3),控制转移到一个新的代码段,而且也切换到内层的堆栈段,(8)临时代码段,16位段,从本教程第五篇的任务状态段TSS的格式可见,TSS中包含有指向0级、1级和2级堆栈的指针

2.堆栈切换
  在使用CALL指令通过调用门向内层转移时,不仅特权级发生变换,控制转移到一个新的代码段,而且也切换到内层的堆栈段。从本教程第五篇的任务状态段TSS的格式可见,TSS中包含有指向0级、1级和2级堆栈的指针。在特权级发生向内层变换时,根据变换到的特权级使用TSS中相应的堆栈指针对SS及ESP寄存器进行初始化,建立起一个空栈。

在建立起内层堆栈后,处理器先把外层堆栈的指针SS及ESP寄存器的值压入内层堆栈,以使得相应的向外层返回可恢复原来的外层堆栈。然后,从外层堆栈复制以双字为单位的调用参数到内层堆栈中,调用门中的DCOUNT字段值决定了复制参数的数量。这些被复制的参数是主程序通过堆栈传递给子程序的实参,在调用之前被压入外层堆栈。通过复制栈中的参数,使内层的子程序不需要考虑堆栈的切换,而容易地访问主程序传递过来的实参。最后,调用的返回地址被压入堆栈,以便在调用结束时返回。下图为在向内层变换时,建立内层堆栈,并从外层堆栈复制2个双字参数到内层堆栈的示意图。图中每项是双字,可见的段寄存器内的选择子被扩展成32为存入堆栈,高16位为0。对于16位的使用调用门的段也是如此。

需要注意的是,无论是否通过调用门,只要不发生特权级变换,就不会切换堆栈。

3.向外层返回
  与使用CALL指令通过调用门向内层变换相反,使用RET指令实现向外层返回。段间返回指令RET从堆栈中弹出返回地址,并且可以采用调整ESP的方法,跳过相应的在调用之前压入堆栈的参数。返回地址的选择子指示要返回的代码段的描述符,从而确定返回的代码段。选择子的RPL确定返回后的特权级,而不是对应描述符的DPL,这是因为,段间返回指令RET可能使控制返回到一致代码段,而一致代码段可以在DPL规定的特权级以外的特权级执行。需要注意的是,RET指令所使用的返回地址的选择子只能使用代码段描述符,而不能使用任何系统段描述符或门描述符,当然,更不能使用数据段描述符,否则会引起异常。与CALL指令相对应,RET指令也不能向内层返回。

段间返回指令完成返回的步骤如下:

(1)RET指令先从堆栈中弹出返回地址。如果弹出地址的选择子的RPL规定相对于CPL更外层的特权级,那么就引起向外层返回。

(2)为向外层返回,跳过内层堆栈中的参数,再从内层栈中弹出指向外层堆栈的指针,并装入SS及ESP,以恢复外层堆栈。

(3)调整ESP,跳过在相应的调用之前压入到外层堆栈的参数。即返回指令不但弹出内层栈的参数,而且也弹出外层栈的参数。

(4)然后,检查数据段寄存器DS、ES、FS及GS,以保证寻址的段在外层是可访问的,如果段寄存器寻址的段在外层是不可访问的,那么装入一个空选择子,以避免在返回时发生保护空洞。

(5)返回外层继续执行。

上述五步是对带立即数的段间返回指令而言的,立即数规定了堆栈中要跳过的参数的字节数。对于无立即数的段间返回指令缺少第二步和第三步。若RET指令不需要向外层返回,那么就只有(1)和(5)两步。对于有通过堆栈传递参数的子程序,必须使用带立即数的返回指令返回,否则返回时会装载错误的外层栈指针。

若不使用带立即数的返回指令,可以在返回前把外层栈的栈指针存入内层栈中的用于保存返回地址上方两个双字的区域中,由外层返回的过程可知,这可正确恢复外层栈的指针,但在外层程序中,必须人为调整外层栈指针,以便废除在外层栈中压入的参数。在使用C调用约定的程序中可使用此方法。但这会增加代码的长度和处理时间,使代码效率变低。正因为如此,在 Windows 9X下,新增加了一种STDCALL的调用约定,它正是为了适应Intel系列处理器的体系结构而产生的。

<四>演示任务内特权级变换的实例(实例四)
  下面给出一个演示任务内特权级变换的实例。该实例演示在任务内通过调用门从外层特权级变换到内层特权级;也演示通过段间返回指令从内层特权级变换到外层特权级;还演示通过调用门的无特权级变换的转移。实例使用了任务状态段TSS,这是因为任务内特权级变换时要使用的内层堆栈指针存放在TSS中。

1.实现步骤
  该实例的实现步骤为:

(1)实方式下初始化;

(2)切换到保护模式;

(3)设置TR和LDTR。由于在任务内发生特权级变换时要切换堆栈,而内层堆栈的指针存放在当前任务的TSS中,所以在进入保护模式后设置任务状态段寄存器TR。由于演示任务使用了局部描述符表,所以设置LDTR;

(4)经调用门进入32位过渡代码段;

(5)建立返回3级演示代码段的环境;

(6)利用RET指令转移到3级的演示代码段。为了演示外层程序通过调用门调用内层程序,要使CPL>0。实例先通过段间返回指令RET从特权级0变换到特权级3的演示代码段。在特权级3下,通过调用门调用1级的子程序。随着执行段间返回指令RET,又回到3级的演示代码段;

(7)在3级的演示代码段中,经调用门转移到0级的32位过渡代码段;

(8)直接转0级的临时代码段;

(9)准备返回实模式;

(10)切换回实模式;

(11)实模式下的恢复工作。

2.源程序组织和清单
  实例四由如下部分组成:

(1)全局描述符表GDT。GDT含有演示任务的TSS段描述符和LDT段描述符,此外还含有临时代码段的描述符、规范数据段描述符和视频缓冲区段描述符。

(2)演示任务的LDT段。它含有除临时代码段外的其它代码段的描述符和演示任务各级堆栈段描述符,还含有3个调用门。

(3)演示任务的TSS段。

(4)演示任务的0级、1级和3级堆栈段。

(5)显示子程序段。32位代码段,特权级1。

(6)演示代码段。32位代码段,特权级3。

(7)过渡代码段。32位段,特权级0。

(8)临时代码段。16位段,特权级0。

上一页  1 2 3 4  下一页

Tags:汇编 教程 控制

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接