7.7.1 控制转移的分类
在一个任务中进行控制转移有以下3种情况:
(1) 段内转移,段内转移不访问描述符,不改变特权级,使用JMP/CALL/RET指令,实现段内控制转移。
(2)同一特权级内的段间转移,在同一特权级内的段间转移又可分成如下3种情况:
①访问代码段描述符的长转移指令JMP/CALL/RET和NT位=0时的IRET指令;
②访问调用门的长转移JMP/CALL指令;
③访问中断/陷阱门的INTn指令,外部中断和异常中断。
(3)特权级间的段间转移,特权级间的段间转移也有以下3种情况:
①访问调用门的长CALL指令;
②访问中断/陷阱的INT指令,外部中断和异常中断。
7.7.2任务内的控制转移
在一个任务内控制转移的示意图如图7.26所示。
1. 段内转移
从表7.6和7.7可以看到,最简单的一种情况就是段内转移。因为在转移前后,段、特权级等均不改变,故只要利用JMP或CALL指令即可实现,例如:
JMP NEARPTRTABLE[EBX] ;段内转移
JMP WORDPTR[BX] ;16位操作的段内转移
JMP DWORDPTR[EBX] ;32位操作的段内转移
如前所述,段内转移不改变CS,只改变了IP或EIP。
2. 段间直接控制转移(同一个特权级内)
由描述符所提供的段基地址及由指令给出的偏移地址共同决定转移或调用子程序的入口地址,即入口地址=段基地址+偏移量
上述过程可由图7.27来表示。
3. 利用调用门进行段间的间接控制转移(不同特权级之间或同一特权级内)在用CALL指令访问调用门时,当门内目的选择器所指定的代码段的描述
符的DPL≤CPL关系成立时,才能转移。
4. 调用门的堆栈处理
CALL指令的执行过程如下:
①将调用程序低特权级堆栈段的选择符进行0扩展,变为32位并压入转移的目的堆栈。
②将调用程序低特权级堆栈段的ESP压入新栈,即转移的目的堆栈。
③将调用门中字数域所指定的参数从调用者堆栈拷贝到转移的目的堆栈。
④将调用处的断点CS选择符进行0扩展,变为32位并压入新堆栈。
⑤将断点的EIP压入堆栈。