X86保护模式 八操作系统类指令
通常在操作系统代码中使用,应用程序中不应用这些指令
指令分为三种:实模式指令,任何权级下使用的指令、实模式权级0下可执行的指令和仅在保护模式下执行的指令
一 实模式和任务特权级下可执行的指令
1.存储全局和中断描述符表寄存器指令
利用存储描述符表寄存器指令能把描述符表寄存器的内容保存到指定的存储单元。与GDT与IDT被所有任务共享不同,LDT是每个任务私有的。所以存储局部描述符表寄存器的LDTR的指令不在所列
a)
存储全局描述符表寄存器指令
SGDT QWORD PTR DST
其中DST为48位存储器操作数
将全局描述符表寄存器GDTR的内容存储到存储单元DST。GDTR中的16位界限存入DST的低字,GDTR中的32位基地址存入DST的高双字,不影响标志位。
b)存储中断描述符表寄存器指令
SIDT QWORD PTR DST
Dst位48位 将IDTR寄存器的内容存储到存储器单元DST。IDTR的16位界限存入DST的低字,IDTR中的32位基地址存入DST的高双字。不影响标志位。
2.存储机状态字指令
SMSW DST
DST可以是16位的存储器操作数或寄存器。该指令的功能是把机器状态字存储到DST 不影响标志位
80386 如果需要存储机器状态字 最好使用存储CR0寄存器的指令
二 实模式及权级0下可执行的指令
下列指令涉及设置关键的寄存器,所以只能在实模式和保护模式的权级0下执行。
在保护模式下,如果当前权级cpl不为0,将产生错误码为0的通用保护故障。
a 清任务切换标志指令
CLTS
每当任务切换时,cr0中的任务切换标志TS被自动置为1,功能将ts标志清0.
仅影响TS标志,对其他标志没有影响。
B 暂停指令
HLT
使cpu暂停执行。暂停之后,只有在接受一个已经启用的中断或让系统复位,才能重新启动,不影响标志位。
C 装载全局描述符表和中断描述符表寄存器的指令
1.装载全局描述符表寄存器
LGDT QWORD PTR SRC
SRC为48位
将存储器中的伪描述符装入到全局描述符表寄存器GDTR中。伪描述符src的结构如前文所述结构类型PDESC所示,低字是以字节为单位的段界限,高双字是段基地址。不影响标志位。
2.装载中断描述符表寄存器
LIDT QWORD PTR SRC
将存储器中的伪描述符装入到中断描述符表寄存器IDTR中。低字以字节为单位的段界限,高双字是段基地址。不影响标志位
D 装载机器状态字
LMSW DST
DST是16位 的存储器操作数或寄存器 ,将DST的内容装载到机器状态字。不影响标志位。
pe位置1 便进入保护模式。
e 控制寄存器数据传送指令
MOV DST,SRC
控制寄存器和32位通用寄存器之间的数据传送 ,两个操作数可以是三个寄存器和任一32位通用寄存器,但不能同时是控制寄存器,不影响标志位
f 调试寄存器数据传送指令
同上,调试寄存器与32位通用寄存器之间的数据传送,可以是调试寄存器和任一32位通用寄存器,但不能同时是调试寄存器。 不影响标志位
386中的6个调试寄存器:DR0 DR1 DRW DR3 DR6 DR7
g 测试寄存器数据传送指令
同e中的指令相同,实现测试寄存器和32位通用寄存器之间的数据传送, 2个测试寄存器是TR6和TR7
三 只能在保护模式下执行的指令
在实模式下执行,会引起非法操作码故障,向量号为6
1.装载和存储局部描述符表寄存器指令
a 装载局部描述符表寄存器指令
LLDT SRC
操作数可以是16位通用寄存器或存储单元,将src中的内容作为指示局部描述符表LDT的选择子装入到LDTR寄存器。不影响标志位。
SRC给定的选择子应该指示GDT中的类型为LDT的描述符。但LRC也是一个空选择子,表示暂时不使用局部描述符表LDT。
若CPL不为0,那么执行该指令将产生出错码位0的通用保护故障。若被装载的选择子不指示GDT中的描述符,或者描述符类型不是LDT描述符,那么产生通用保护故障,错误码由该选择构成
LDTR有两部分,指示LDT的选择子装入LDTR可见部分时,描述符中的信息也被保存到高速缓冲寄存器。
b 存储局部描述符表寄存器指令
SLDT DST
dst为16位 寄存器或存储单元,将局部描述符表寄存器LDTR的内容存储到存储单元DST中。不影响标志位
2.装载和存储任务寄存器指令
任务寄存器TR指示当前任务状态段TSS,随着任务的切换,TR的内容也随之改变,如果任务嵌套,那么tr的原值作为链接字保存到新任务的TSS中。但有时候需要直接地装载后者保存TR,这就需要使用装载TR指令和存储TR指令。
a 装载任务寄存器可指令
LTR SRC
SRC为16位通用寄存器或者存储器单元。将src作为指示tss描述符的选择子装载到任务寄存器TR。把TSS的选择子装入到TR的可见部分。cpu自动把选择子索引的描述符中的段基地址等信息保存到不可见的高速缓冲寄存器中。所以src表示的选择子不能为空,必须索引位于GDT中的描述符,并且描述符类型必须是可用TSS,该加载的TSS被处理器自动标为"忙",不影响标志位。
如果cpl不为0,会产生错误码为0的通用保护故障。
如果被加载的选择子不指示GDT中的可用TSS描述符,那么产生通用保护故障,错误码由选择构成。
b 存储任务寄存器指令
STR DST
将tr所示的指示当前任务TSS描述符的选择子存储到DST ,不影响标志位
3.调整申请特权级指令
ARPL OPRD1,OPRD2
OPRD1可以是16位通用寄存器或存储的单元,oprd2是16位通用寄存器。将两个操作数看作两个选择子,用oprd2的申请特权级rpl去检查oprd1的rpl。
选择子oprd1和oprd2的rpl分别由他们的最低2个位规定。如果oprd1的rpl小于oprd2的rpl,那么零标志ZF被置1,并把op2的rpl值赋予op1的rpl (使两个数的最低2位相等),否则,零标志zf被清0.op1和op2都可以为空选择子。影响ZF标志。
4.装载存取权指令
LAR OP1,OP2
OP1 16位或32位通用寄存器,op2是16位通用寄存器或存储单元,也可以是32位通用寄存器或存储单元,两个操作数尺寸需要一致,把op2看作选择子,32位中仅适用低16位。
如果op2所指示的描述符满足下面的条件,zf被置1 并将描述符内的属性字段装入op1,否则zf清0,op1保持不变。
a 在描述符表的范围内
b 是存储段描述符或系统段描述符或任务门描述符或调用门描述符
c cpl和op2的rpl都不大于dpl
在满足条件的情况下,装入到op1的由op2所指示的描述符中的属性字段是指描述符的高4字节和00fxff00h相与的结果,其中x表示第16位到第19位无定义。如果使用16位操作数,那么只有高4字节中的低字被装入到op1,即装入到op1的属性字段不包括g位和avl位等,只影响zf标志位
5.装载段界限指令
LSL OP1,OP2
OP1可以是16位或32位通用寄存器 op2可以是16位或32位的寄存器或存储单元
将op2看成选择子 ,如果op2所指示的描述符满足如下条件,那么zf置1,并把描述符内的界限字段装入op1,否则zf清0,op1不变
a 在描述符表的范围内
b 是存储段描述符或系统段描述符,而非门描述符
c cpl和op2的rpl都不大于dpl
满足条件时,装入到op1的有op2所指示的描述符中的界限字段以字节为单位,如果描述符中的界限字段以4k字节为单位g=1,那么装入到op1时左移12位,空出的低位全部填写成1.如果指令使用16位操作数,那么只有段界限的低16位被装入到op1,影响zf标志位
6.读写检验指令
利用读检验指令和写检验指令可以分别检查在当前权级上指定的段能否读或写,从而避免引起不必要的异常
a 读检验
VERR oprd
op可以是16位或32位通用寄存器或存储器单元 将op内容作为一个选择子 使用32位中的低16位,判断当前特权级上该选择子指示的段是否刻度,如果该选择子指示一个合法的存储段描述符,并且在当前权级上刻度所描述的段,那么ZF被置为1,否则被清0,只影响zf标志位。
b 写检验
VERW OPRD
同上,检验选择子指向的段是否可写。
实例:显示关键寄存器内容的实例 实例八
;名称:ASM8.ASM
;功能:显示关键寄存器内容及说明操作系统类指令的使用
;编译:TASM ASM8.ASM
;连接:TLINK ASM8.OBJ
;----------------------------------------------------------------------------
INCLUDE 386SCD.INC
;----------------------------------------------------------------------------
GDTSeg SEGMENT PARA USE16 ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
GDT LABEL BYTE
;空描述符
DUMMY Desc <>
;规范段描述符及选择子
Normal Desc <0ffffh,,,ATDW,,>
Normal_Sel = Normal-GDT
;----------------------------------------------------------------------------
EFFGDT LABEL BYTE
;临时任务代码段描述符及选择子
TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel = TempCode-GDT
;缓冲区段描述符及选择子
Buffer Desc <BufferLen-1,BufferSeg,,ATDW,,>
Buffer_Sel = Buffer-GDT
;测试描述符1及选择子
Test1 Desc <1111h,,,92h,87h,>
Test1_Sel = Test1-GDT
TestR_Sel = Test1-GDT+RPL3
;测试描述符2及选择子
Test2 Desc <2222h,,,82h,17h,>
Test2_Sel = Test1-GDT
;----------------------------------------------------------------------------
GDNum = ($-EFFGDT)/(SIZE Desc) ;需特殊处理的描述符数
GDTLen = $-GDT ;全局描述符表长度
;----------------------------------------------------------------------------
GDTSeg ENDS ;全局描述符表段定义结束
;----------------------------------------------------------------------------
BufferSeg SEGMENT PARA USE16 ;缓冲区数据段
;----------------------------------------------------------------------------
GDTR_V PDesc <> ;存放GDTR
IDTR_V PDesc <> ;存放IDTR
;----------------------------------------------------------------------------
MSW_V DW 0 ;存放机器状态字
LDTR_V DW 0 ;存放LDTR选择子
TR_V DW 0 ;存放TR选择子
CR0_V DD 0 ;存放控制寄存器CR0
CR3_V DD 0 ;存放控制寄存器CR3
DR7_V DD 0 ;存放调试寄存器DR7
Test_RPL DW 0
;----------------------------------------------------------------------------
Test1_SLD DD 0 ;演示用变量
Test1_ARD DD 0
Test1_SLW DW 0
Test1_ARW DW 0
Test1_RF DW 0
Test1_WF DW 0
;----------------------------------------------------------------------------
Test2_SLD DD 0 ;演示用变量
Test2_ARD DD 0
Test2_SLW DW 0
Test2_ARW DW 0
Test2_RF DW 0
Test2_WF DW 0
;----------------------------------------------------------------------------
BufferLen = $
BufferSeg ENDS
;----------------------------------------------------------------------------
TempCodeSeg SEGMENT PARA USE16 ;临时代码段
ASSUME CS:TempCodeSeg,DS:BufferSeg
;----------------------------------------------------------------------------
Virtual PROC FAR
mov ax,Buffer_Sel
mov ds,ax
mov eax,cr0 ;存储CR0
mov CR0_V,eax
mov eax,cr3 ;存储CR3
mov CR3_V,eax
mov eax,DR7 ;存储DR7
mov DR7_V,eax
str TR_V ;存储TR
sldt LDTR_V ;存储LDTR
mov Test_RPL,Test1_Sel
mov ax,TestR_Sel
arpl Test_RPL,ax ;说明调整申请特权及指令
mov bx,0
mov ax,Test1_Sel
Lab1: mov edx,0
mov cx,0
lsl edx,eax ;说明装载段界限指令
lsl cx,ax
mov Test1_SLD[bx],edx
mov Test1_SLW[bx],cx
mov edx,0
mov cx,0
lar edx,eax ;说明装载存取权指令
lar cx,ax
mov Test1_ARD[bx],edx
mov Test1_ARW[bx],cx
mov Test1_RF[bx],0
verr ax ;说明读检验指令
jnz Lab2
mov Test1_RF[bx],1
Lab2: mov Test1_WF[bx],0
verw ax ;说明写检验指令
jnz Lab3
mov Test1_WF[bx],1
Lab3: add bx,16
mov ax,Test2_Sel
cmp bx,32
jb Lab1
;准备返回实方式
mov ax,Normal_Sel
mov ds,ax
mov eax,cr0
and al,11111110b
mov cr0,eax ;返回实方式
JUMP16 <SEG Real>,<OFFSET Real>
Virtual ENDP
;----------------------------------------------------------------------------
TempCodeSeg ENDS
;----------------------------------------------------------------------------
RCodeSeg SEGMENT PARA USE16
ASSUME CS:RCodeSeg,DS:BufferSeg
;----------------------------------------------------------------------------
VGDTR PDesc <GDTLen-1,>
;----------------------------------------------------------------------------
Start PROC
mov ax,BufferSeg
mov ds,ax
sgdt GDTR_V
sidt IDTR_V
smsw MSW_V
;准备转入保护方式
push cs
pop ds
cld
call InitGDT
mov bx,OFFSET VGDTR
lgdt [bx]
cli
mov eax,cr0
or al,1
;转入保护方式
mov cr0,eax
JUMP16 <TempCode_Sel>,<OFFSET Virtual>
Real: ;回到实方式
sti
;为了简单,略去了显示相关变量内容的部分代码
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
InitGDT PROC
push ds
mov ax,GDTSeg
mov ds,ax
mov cx,GDNum
mov si,OFFSET EFFGDT
InitG: mov ax,[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR [si].BaseL,ax
mov BYTE PTR [si].BaseM,dl
mov BYTE PTR [si].BaseH,dh
add si,SIZE Desc
loop InitG
pop ds
mov bx,16
mov ax,GDTSeg
mul bx
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
ret
InitGDT ENDP
;----------------------------------------------------------------------------
RCodeSeg ENDS
END Start
五 特权指令
保护方式下,只有当权级cpl=0,才可执行的指令,如果cpl不等于0,引起通用保护异常
装入GDTR IDTR LDTR TR 和MSW的指令都是特权指令,而存储上述寄存器的指令不是特权指令,这表示保护模式下任何程序可以获得这些寄存器的值,但是只有特权级0的程序才能改变这些寄存器的值,设置和存储控制寄存器及调试寄存器的指令都是特权指令。