控制转移文档格式.docx
- 文档编号:3220278
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:55
- 大小:40.13KB
控制转移文档格式.docx
《控制转移文档格式.docx》由会员分享,可在线阅读,更多相关《控制转移文档格式.docx(55页珍藏版)》请在冰点文库上搜索。
调整RPL。
(4)把目标代码段描述符内的有关内容装载到CS高速缓冲寄存器。
(5)判断目标地址指针内的偏移是否越出代码段的界限。
目标地址指针内的偏移必须不超过目标代码段界限。
(6)装载CS段寄存器和指令指针寄存器EIP;
CPL存入CS内选择子的RPL字段。
上述步骤只是对转移过程的简单说明,实际的动作还要复杂。
在把目标代码段描述符内的有关内容转载到CS高速缓冲寄存器时,还要进行如下保护检测,其中的DPL表示目标代码段描述符的特权级:
(1)对于非一致代码段,要求CPL=DPL,RPL<
=DPL;
对于一致代码段,要求CPL>
=DPL。
(2)代码段必须存在,即描述符中的P位必须是1。
通常描述符特权级DPL规定了对应段的特权级。
如果描述符描述的是数据段,那么DPL就规定了访问该数据段的最外层特权级;
如果描述符描述的是代码段,那么DPL就规定了执行该代码段所需要的CPL。
但从上述装载CS高速缓冲寄存器时进行的保护检测可见,对于一致代码段,却要求CPL>
=DPL,也就是说,一致代码段描述符中的DPL规定了可以转移到一致代码段的最内层特权级。
于是,3级的程序可以转移到任何一致的代码段,而0级的程序只允许转移到DPL等于0的一致代码段。
一致代码段描述符内DPL的这种解释,正好与正常的DPL的解释相反。
一致的可执行段是一种特别的段。
这种存储段,为在多个特权级执行的程序,提供对子例程的共享支持,而不要求改变特权级。
例如,通过把数值库例程放在一致的代码段中,可以使不同级执行的程序共享数值库例程。
这样,任何特权级的程序可以使用段间调用指令,调用库中的例程,并在调用者所具有的特权级执行该例程。
3.任务内无特权级变换的转移
所谓任务内无特权级变换的转移指:
在转移到新的代码段时,当前特权级CPL保持不变。
利用段间转移指令JMP、段间调用指令CALL和段间返回指令RET可实现任务内无特权级变换的转移。
利用INT指令和IRET指令也可实现任务内无特权级变换的转移。
(1)利用段间直接转移指令JMP或CALL
在执行段间转移指令JMP时,如果指令内所含指针指示一个代码段,那么就直接开始上述向目标代码段转移的步骤;
在执行段间调用指令CALL时,如果指令内所含指针指针指示一个代码段,那么就把返回地址指针压栈,然后就直接开始上述向目标代码段转移的步骤。
顺利通过这几步(不调整RPL)后,就完成了任务内无特权级变换的转移。
由此可见,利用段间直接转移指令JMP或调用指令CALL可方便地进行任务内无特权级变换的转移,但不能进行任务内特权级变换的转移。
(2)利用段间返回指令RET
在执行段间返回指令RET时,如果从堆栈中弹出的目标地址指针指示一个代码段,并且选择子符合RPL=CPL的条件,那么就开始上述向目标代码段的转移步骤。
顺利通过这几步后,就完成了任务内无特权级变换的转移。
通常情况下,段间返回指令RET与段间调用指令CALL对应。
在利用段间调用指令CALL以任务内无特权级变换的方式转移到某个子程序后,在子程序内利用段间返回指令RET以任务内无特权级变换的方式返回主程序。
由于调用时无特权级变换,所以返回时也无特权级变换,如果真是如此,那么必须能够满足条件RPL=CPL。
(3)利用调用门和其它途径
如何利用调用门实行和其它方法实现任务内无特权级变换的转移将在后面的文章中介绍。
4.装载数据段和堆栈段寄存器时的特权检测
上面简单地说明了把选择子装入代码段寄存器CS时为实现保护而进行的检测,下面也简单地说明在把选择子装入数据段寄存器和堆栈段寄存器时要进行的检测。
在把选择子装入数据段寄存器DS、ES、FS或GS时,要进行如下检测:
(1)选择子不能为空;
(2)选择子指定的描述符必须是数据段描述符、可读可执行的代码段或一致可读的可执行代码段的描述符;
(3)对于数据段和可读可执行代码段,要求CPL<
=DPL,RPL<
(4)对应的段必须存在。
若装入的选择子不满足上述要求,则会产生异常。
在把选择子装入堆栈段寄存器SS时要进行如下检测:
(2)选择子指定的描述符必须是可读写的数据段描述符;
(3)要求CPL=DPL=RPL;
(4)对应段必须存在。
若装入的选择子不满足上述条件,则在装入SS时就会引起异常。
二>
演示任务内无特权级变换转移的实例(实例三)
在实例二中,32位代码段到16位代码段的转移就是任务内无特权级转移的例子。
下面再给出一个用于演示任务内无特权级变换转移的实例。
该实例使用了段间转移指令JMP、段间调用指令CALL和段间返回指令RET实现同一任务内相同特权级的转移。
该实例还建立并使用了局部描述符表LDT。
1.实现步骤和源程序
实现步骤如下:
(1)实模式下的初始化,包括对GDT和演示任务LDT的初始化,装载GDTR;
(2)从实模式切换到保护模式,处于0特权级;
(3)装载LDTR,并设置堆栈;
(4)利用段间转移指令JMP实现从代码段K到同级代码段L的转移;
(5)利用段间调用指令CALL调用同级代码段C中的子程序D显示字符串信息;
(6)利用段间调用指令CALL调用同级代码段C中的子程序H把十六进制数转换成对应的ASCII码;
(7)再利用段间调用指令CALL调用同级代码段C中的子程序D显示字符串信息;
(8)利用段间转移指令JMP实现从代码段L到代码段K的转移;
(9)从保护模式切换到实模式;
(10)在实模式下结束程序。
该实例的逻辑功能是用十六进制数的形式显示代码段L的段界限的值。
源程序如下:
;
名称:
ASM3.ASM
功能:
演示任务内无特权级变换的转移
编译:
TASMASM3.ASM
连接:
TLINKASM3.OBJ
----------------------------------------------------------------------------
INCLUDE386SCD.INC
GDTSegSEGMENTPARAUSE16'
GDT'
;
全局描述符表数据段(16位)
GDTLABELBYTE;
全局描述符表
DUMMYDesc<
>
空描述符
NormalDesc<
0ffffh,,,ATDW,,>
规范段描述符
CodeKDesc<
0ffffh,,,ATCE,,>
代码段K的描述符
LDTableDesc<
LDTLen-1,,,ATLDT,,>
局部描述符表段的描述符
GDTLen=$-GDT;
全局描述符表长度
Normal_Sel=Normal-GDT;
规范段描述符选择子
CodeK_Sel=CodeK-GDT;
代码段K的选择子
LDT_Sel=LDTable-GDT;
局部描述符表段的选择子
GDTSegENDS;
全局描述符表段定义结束
LDTSegSEGMENTPARAUSE16'
LDT'
局部描述符表数据段(16位)
LDTLABELBYTE;
局部描述符表
代码段L的描述符
CodeLDesc<
CodeLLen-1,CodeLSeg,,ATCE,,>
代码段C的描述符
CodeCDesc<
CodeCLen-1,CodeCSeg,,ATCE,,>
显示缓冲区段描述符
VideoBufDesc<
0ffffh,0b800h,,ATDW,,>
LDT别名段描述符(DPL=3)
ToLDTDesc<
LDTLen-1,LDTSEG,,ATDR+DPL3,,>
显示信息缓冲区数据段描述符(DPL=3)
MDataDesc<
MDataLen-1,MDataSeg,,ATDW+DPL3,,>
堆栈段描述符
StackSDesc<
TopOfS-1,StackSeg,,ATDWA,,>
LDTLen=$-LDT;
LDT所占字节数
LDNum=($-LDT)/(SIZEDesc);
LDT含描述符项数
CodeL_Sel=CodeL-LDT+TIL;
代码段L的选择子
CodeC_Sel=CodeC-LDT+TIL;
代码段C的选择子
Video_Sel=VideoBuf-LDT+TIL;
显示缓冲区选择子
ToLDT_Sel=ToLDT-LDT+TIL;
LDT别名段选择子
MData_Sel=MData-LDT+TIL+RPL3;
显示信息数据段选择子
Stack_Sel=StackS-LDT+TIL;
堆栈段选择子
LDTSegENDS;
局部描述符表段定义结束
MDataSegSEGMENTPARAUSE16'
MDATA'
显示信息缓冲区数据段
MessageDB'
Value='
0
BufferDB80DUP(0)
MDataLen=$
MDataSegENDS;
显示缓冲区数据段结束
StackSegSEGMENTDWORDUSE16'
STACK'
堆栈段
DW512DUP(?
)
TopOfS=$
StackSegENDS;
堆栈段结束
CodeCSegSEGMENTPARAUSE16'
CODEC'
任务代码段C
ASSUMECS:
CodeCSeg
显示信息子程序
入口参数:
fs:
si指向要显示的以0结尾的字符串,es:
di指向显示缓冲区
DispMsgPROCFAR
movah,01001110b
Disp1:
moval,BYTEPTRfs:
[si]
incsi
oral,al
jzDisp2
movWORDPTRes:
[di],ax
incdi
jmpDisp1
Disp2:
ret
DispMsgENDP
把AL寄存器低4位二进制数(一位16进制数)转换成ASCII码
HToASCIIPROCFAR
andal,00001111b
addal,90h
daa
adcal,40h
HToASCIIENDP
CodeCLen=$
CodeCSegENDS;
代码段C定义结束
CodeLSegSEGMENTPARAUSE16'
CODEL'
CodeLSeg
Virtual2PROCFAR
movax,Video_Sel;
设置显示缓冲区指针
moves,ax
movdi,1986
movax,MData_Sel;
设置提示信息缓冲区指针
movfs,ax
movsi,OFFSETMessage
CALL16CodeC_Sel,DispMsg;
显示提示信息
movax,ToLDT_Sel;
把演示任务的LDT的别名
movgs,ax;
段的描述符选择子装入GS
movdx,WORDPTRgs:
CodeL.LimitL
movsi,OFFSETBuffer;
取代码段L的段界限值
movcx,4;
并转成对应可显示字符串
Vir:
roldx,4
moval,dl
CALL16CodeC_Sel,HToASCII
movBYTEPTRfs:
[si],al
loopVir
movWORDPTRfs:
[si],'
H'
movsi,OFFSETBuffer
CALL16CodeC_Sel,DispMsg
JUMP16CodeK_Sel,Virtual3
CodeLLen=$
Virtual2ENDP
CodeLSegENDS
CodeKSegSEGMENTPARAUSE16'
CODEK'
CodeKSeg
Virtual1PROCFAR
movax,LDT_Sel
LLDTax;
加载局部描述符表寄存器LDTR
movax,Stack_Sel
movss,ax;
建立演示任务堆栈
movsp,OFFSETTopOfS
JUMP16CodeL_Sel,Virtual2
Virtual3:
movax,Normal_Sel
movgs,ax
movss,ax
moveax,cr0
andal,11111110b
movcr0,eax
JUMP16<
SEGReal>
<
OFFSETReal>
CodeKLen=$
Virtual1ENDP
CodeKSegENDS
============================================================================
RDataSegSEGMENTPARAUSE16;
实方式数据段
VGDTRPDesc<
GDTLen-1,>
GDT伪描述符
SPVarDW?
用于保存实方式下的SP
SSVarDW?
用于保存实方式下的SS
RDataSegENDS
RCodeSegSEGMENTPARAUSE16
RCodeSeg
StartPROC
ASSUMEDS:
GDTSeg
-----------------
movax,GDTSeg
movds,ax
初始化全局描述符表
movbx,16
movax,CodeKSeg
mulbx
movCodeK.BaseL,ax
movCodeK.BaseM,dl
movCodeK.BaseH,dh
movax,LDTSeg
movLDTable.BaseL,ax
movLDTable.BaseM,dl
movLDTable.BaseH,dh
设置GDT伪描述符
RDataSeg
movax,RDataSeg
movWORDPTRVGDTR.Base,ax
movWORDPTRVGDTR.Base+2,dx
初始化演示任务LDT
cld
callInit_MLDT
保存实方式堆栈指针
movSSVar,ss
movSPVar,sp
装载GDTR
lgdtQWORDPTRVGDTR
cli
切换到保护方式
oral,1
CodeK_Sel>
OFFSETVirtual1>
Real:
又回到实方式
lsssp,DWORDPTRSPVar
sti
movax,4c00h
int21h
StartENDP
Init_MLDTPROC
pushds
movcx,LDNum
movsi,OFFSETLDT
InitL:
movax,[si].BaseL
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 控制 转移