在使用CALL指令通过调用门向内层转移时,不仅特权级发生变换,控制转移到一个新的代码段,而且也切换到内层的堆栈段。从本教程第五篇的任务状态段TSS的格式可见,TSS中包含有指向0级、1级和2级堆栈的指针。在特权级发生向内层变换时,根据变换到的特权级使用TSS中相应的堆栈指针对SS及ESP寄存器进行初始化,建立起一个空栈。 在建立起内层堆栈后,处理器先把外层堆栈的指针SS及ESP寄存器的值压入内层堆栈,以使得相应的向外层返回可恢复原来的外层堆栈。然后,从外层堆栈复制以双字为单位的调用参数到内层堆栈中,调用门中的DCOUNT字段值决定了复制参数的数量。这些被复制的参数是主程序通过堆栈传递给子程序的实参,在调用之前被压入外层堆栈。通过复制栈中的参数,使内层的子程序不需要考虑堆栈的切换,而容易地访问主程序传递过来的实参。最后,调用的返回地址被压入堆栈,以便在调用结束时返回。下图为在向内层变换时,建立内层堆栈,并从外层堆栈复制2个双字参数到内层堆栈的示意图。图中每项是双字,可见的段寄存器内的选择子被扩展成32为存入堆栈,高16位为0。对于16位的使用调用门的段也是如此。 需要注意的是,无论是否通过调用门,只要不发生特权级变换,就不会切换堆栈
|