操作系统类指令
本文介紹操作系統類指令。其中的某些指令始于286。通常只在操作系統代碼中使用這些指令, 而不在應用程序中使用這些指令。這是把它們稱為操作系統類指令的原因。為了保證操作系統 的安全,保護模式下的80386支持四個特權級。相應地,這些操作系統類指令也可分為三種:實 模式和任何特權級下可執行的指令、實模式及特權級0下可執行的指令和僅在保護模式下執行的 指令。這里下載本文源代碼。
<一>實模式和任何特權級下可執行的指令
1.存儲全局和中斷描述符表寄存器指令
全局描述符表GDT和中斷描述符表IDT包含著系統的重要數據,對應的兩個描述符表寄存 器GDTR和IDTR含有這兩張表的定位信息。利用存儲描述符表寄存器指令能把描述符表寄存器 的內容保存到指定的存儲單元。這樣,訪問這些存儲單元就可獲得描述符表的定位信息。 與GDT和IDT被所有任務共享不同,LDT是每個任務私有的,所以存儲局部描述符表寄存器LDTR的 指令不在所列。
(1)存儲全局描述符表寄存器指令
存儲全局描述符表寄存器指令的格式如下:
SGDT QWORD PTR DST
其中操作數DST是48位(6字節)的存儲器操作數。該指令的功能是把全局描述符表寄存器GDTR的 內容存儲到存儲單元DST。GDTR中的16位界限存入DST的低字,GDTR中的32位基地址存入DST的 高雙字。該指令對標志沒有影響。
(2)存儲中斷描述符表寄存器指令
存儲中斷描述符表寄存器指令的格式如下:
SIDT QWORD PTR DST
其中操作數DST是48位(6字節)的存儲器操作數。該指令的功能是把中斷描述符表寄存器IDTR的 內容存儲到存儲單元DST。IDTR中的16位界限存入DST的低字,IDTR中的32位基地址存入DST的 高雙字。該指令對標志沒有影響。
2.存儲機器狀態字指令
存儲機器狀態字指令的格式如下:
SMSW DST
其中操作數DST可以是16位(字)的存儲器操作數或寄存器。該指令的功能是把機器狀態字的 內容存儲到DST。該指令對標志沒有影響。
80386有此指令是為了包含80286的指令集,以便與其兼容。由于80386的控制寄存器CR0的低16位 等同于80286的機器狀態字,所以,在為80386編程時,如果需要存儲機器狀態字,那么最好使用 存儲CR0寄存器的指令。
<二>實模式及特權級0下可執行的指令
下列指令涉及設置關鍵的寄存器,所以只能在實模式和保護模式的特權級0下執行。為了從初始 時的實模式轉入保護模式,必須做基本的準備工作。例如,設置妥全局描述符表寄存器GDTR等。 這是允許下列指令在實模式下工作的原因。
在保護模式下,如果當前特權級(CPL)不為0,執行這些指令將引起錯誤碼為0的通用保護故障。 在虛擬8086方式下,因為其CPL為3,所以執行這些指令也將會引起出錯碼為0的通用保護故障。
1.清任務切換標志指令
每當任務切換時,控制寄存器CR0中的任務切換標志TS被自動置1。這樣安排的原因已在前文中 說明過。清任務切換標志指令的功能是把TS標志清0,該指令的格式如下:
CLTS
該指令僅影響TS標志,對其它標志沒有影響。
2.暫停指令
暫停指令的格式如下:
HLT
該指令使處理器暫停執行。暫停之后的系統,只有在接受一個已經啟用的中斷或讓系統復位, 才能重新啟動。該指令對標志沒有影響。
3.裝載全局描述符表和中斷描述符表寄存器的指令
(1)裝載全局描述符表寄存器指令
裝載全局描述符表寄存器指令的格式如下:
LGDT QWORD PTR SRC
其中操作數SRC是48位(6字節)的存儲器操作數。該指令的功能是把存儲器中的偽描述符裝入到 全局描述符表寄存器GDTR中。偽描述符SRC的結構如前文所述結構類型PDESC所示,低字是以字 節為單位的段界限,高雙字是段基地址。該指令對標志沒有影響。
(2)裝載中斷描述符表寄存器指令
裝載中斷描述符表寄存器指令的格式如下:
LIDT QWORD PTR SRC
其中操作數SRC是48位(6字節)的存儲器操作數。該指令的功能是把存儲器中的偽描述符裝入到 中斷描述符表寄存器IDTR中。偽描述符SRC的結構如前文所述結構類型PDESC所示,低字是以字 節為單位的段界限,高雙字是段基地址。該指令對標志沒有影響。
4.裝載機器狀態字指令
裝載機器狀態字指令的格式如下:
LMSW DST
其中操作數DST可以是16位(字)的存儲器操作數或寄存器。該指令的功能是把DST的內容裝載到 機器狀態字。該指令對標志沒有影響。
將PE位置為1,便進入保護模式。在80286中,沒有控制寄存器,為進入保護模式需要通過該指 令把MSW中的PE位置為1。如果的確是這樣,那么LMSW指令后面必須緊跟一條轉移指令。
80386有此指令是為了包含80286的指令集,以便與其兼容。由于80386的控制寄存器CR0的低16位 等同于80286的機器狀態字,所以,在為80386編程時,如果需要裝載機器狀態字,那么最好使用 控制寄存器傳送指令。
5.控制寄存器數據傳送指令
控制寄存器數據傳送指令的一般格式如下:
MOV DST,SRC
控制寄存器數據傳送指令實現80386的控制寄存器和32位通用寄存器之間的數據傳送。所以,操 作數SRC和DST可以是80386使用的三個控制寄存器和任一32位通用寄存器,但不能同時是控制寄 存器。該指令對標志沒有影響。
6.調試寄存器數據傳送指令指令
調試寄存器數據傳送指令的一般格式與上面的控制寄存器數據傳送指令的格式相同。功能是實 現80386的調試寄存器和32位通用寄存器之間的數據傳送。操作數SRC和DST可以是80386使用 的6個調試寄存器和任一32位通用寄存器,但不能同時為調試寄存器。該指令不影響標志。
80386可使用的6個調試寄存器記為:DR0、DR1、DRW、DR3、DR6和DR7。其它說明與控制寄存器 數據傳送指令相同。
7.測試寄存器數據傳送指令
測試寄存器數據傳送指令的一般格式與上面的控制寄存器數據傳送指令的格式相同。功能 是實現80386的測試寄存器和32位通用寄存器之間的數據傳送。80386使用的2個測試寄存器 是TR6和TR7。其它說明與控制寄存器數據傳送指令相同。
<三>只能在保護模式下執行的指令
下面介紹的指令只能在保護模式下執行,如果在實模式下執行這些指令,將引起非法操作碼 故障(向量號為6)。
1.裝載和存儲局部描述符表寄存器指令
(1)裝載局部描述符表寄存器指令
裝載局部描述符表寄存器指令的格式如下:
LLDT SRC
其中,操作數SRC可以是16位通用寄存器或存儲單元。該指令的功能是把SRC中的內容作為 指示局部描述符表LDT的選擇子裝入到LDTR寄存器。該指令不影響標志。
操作數SRC給定的選擇子應該指示GDT中的類型為LDT的描述符。但LRC也可是一個空選擇子, 如果這樣的話,表示暫時不使用局部描述符表LDT。
若CPL不為0,那么執行該指令將產生出錯碼為0的通用保護故障。若被裝載的選擇子不指 示GDT中的描述符,或者描述符類型不是LDT描述符,那么產生通用保護故障,錯誤碼由該 選擇子構成。
象段寄存器那樣,LDTR也有兩部分。在把指示LDT的選擇子裝入到LDTR可見部分時,處理器 自動把選擇子所索引的LDT描述符中的段基地址等信息保存到不可見的高速緩沖寄存器中。
(2)存儲局部描述符表寄存器指令
存儲局部描述符表寄存器指令的格式如下:
SLDT DST
其中,操作數DST可以是16位通用寄存器或存儲單元。該指令的功能是把局部描述符表寄存器LDTR的內容存儲到存儲單元DST中,也即把指向當前任務LDT的選擇子存儲到DST中。該指令不 影響標志。
2.裝載和存儲任務寄存器指令
任務寄存器TR指示當前任務狀態段TSS。隨著任務的切換,TR的內容也隨之改變;如果任務嵌 套,那么TR的原值作為鏈接字保存到新任務的TSS中。但有時候需要直接地裝載或者保存TR, 這就需要使用裝載TR指令和存儲TR指令。
(1)裝載任務寄存器指令
裝載任務寄存器指令的格式如下:
LTR SRC
其中,操作數SRC可以是16位通用寄存器或存儲單元。該指令的功能是將SRC作為指示TSS描述符 的選擇子裝載到任務寄存器TR。由前文可知,TR分為兩部分,即程序員可見部分和不可見的高 速緩沖寄存器部分。在把TSS的選擇子裝入到TR可見部分時,處理器自動把選擇子所索引的描述 符中的段基地址等信息保存到不可見的高速緩沖寄存器中。所以,SRC表示的選擇子不能為空, 必須索引位于GDT中的描述符,并且描述符類型必須是可用TSS,該加載的TSS被處理器自動標為"忙"。該指令對標志沒有影響。
若CPL不為0,那么執行該指令將產生錯誤碼為0的通用保護故障。若被加載的選擇子不指示GDT中 的可用TSS描述符,那么產生通用保護故障,錯誤碼由該選擇子構成。
(2)存儲任務寄存器指令
存儲任務寄存器指令的格式如下:
STR DST
其中,操作數DST可以是16位通用寄存器或存儲單元。該指令的功能是把TR所含的指示當前任 務TSS描述符的選擇子存儲到DST。該指令不影響標志。
3.調整申請特權級指令
調整申請特權級指令的格式如下:
ARPL OPRD1,OPRD2
其中,操作數OPRD1可以是16位通用寄存器或存儲單元,操作數OPRD2是16位通用寄存器。該指 令把操作數OPRD1和OPRD2視為兩個選擇子,用OPRD2的申請特權級(RPL)去檢查OPRD1的RPL。選 擇子OPRD1和OPRD2的RPL分別由它們的最低2個位規定。如果OPRD1的RPL小于OPRD2的RPL,那么 零標志ZF被置1,并把OPRD2的RPL值賦予OPRD1的RPL(使兩個操作數的最低2位相等);否則,零 標志ZF被清0。OPRD1和OPRD2都可為空選擇子。該指令只影響ZF標志。
4.裝載存取權指令
裝載存取權指令的格式如下:
LAR OPRD1,OPRD2
其中,操作數OPRD1可以是16位或32位通用寄存器,操作數OPRD2是16位通用寄存器或存儲單 元,也可以是32位通用寄存器或存儲單元。操作數OPRD1和OPRD2的尺寸必須一致。該指令把 操作數OPRD2視為選擇子(當為32位時,僅使用低16位),如果OPRD2所指示的描述符滿足如下 條件,那么零標志ZF被置1,并把描述符內的屬性字段裝入OPRD1;否則,ZF清0,OPRD1保持 不變。
(1)在描述符表的范圍內;
(2)是存儲段描述符或系統段描述符或任務門描述符或調用門描述符;
(3)CPL和OPRD2的RPL都不大于DPL。
在滿足條件的情況下,裝入到OPRD1的由OPRD2所指示的描述符中的屬性字段是指描述符的 高4字節和00FXFF00H相與的結果,其中X表示第16位到第19位無定義。注意,如果指令使 用16位操作數,那么只有高4字節中的低字被裝入到OPRD1,即裝入到OPRD1的屬性字段不 包括G位和AVL位等。該指令只影響ZF標志。
5.裝載段界限指令
裝載界限指令的格式如下:
LSL OPRD1,OPRD2
其中,操作數OPRD1可以是16位或32位通用寄存器,操作數OPRD2是16位通用寄存器或存儲單 元,也可以是32位通用寄存器或存儲單元。操作數OPRD1和OPRD2的尺寸必須一致。該指令把 操作數OPRD2視為選擇子(當為32位時,僅使用低16位),如果OPRD2所指示的描述符滿足如下 條件,那么零標志ZF被置1,并把描述符內的界限字段裝入OPRD1;否則,ZF清0,OPRD1保持 不變。
(1)在描述符表的范圍內;
(2)是存儲段描述符或系統段描述符,而非門描述符;
(3)CPL和OPRD2的RPL都不大于DPL。
在滿足條件的情況下,裝入到OPRD1的由OPRD2所指示的描述符中的界限字段以字節位為單位。 如果描述符中的界限字段以4K字節為單位(G=1),那么裝入到OPRD1時被左移12位,空出的低位 全部填成1。注意,如果指令使用16位操作數,那么只有段界限的低16位被裝入到OPRD1。該指 令只影響ZF標志。
6.讀寫檢驗指令
利用讀檢驗指令和寫檢驗指令可分別檢查在當前特權級上指定的段能否讀或寫,從而避免引起 不必要的異常。
(1)讀檢驗指令
讀檢驗指令的一般格式如下:
VERR OPRD
其中,操作數OPRD可以是16位通用寄存器或存儲單元,也可以是32位通用寄存器或存儲單元。 該指令的功能是把OPRD的內容作為一個選擇子(當32位時僅使用低16位),判斷在當前特權級上 該選擇子所指示的段是否可讀。如果該選擇子指示合法的一個存儲段描述符,并且在當前特權 級上可讀所描述的段,那么零標志ZF被置為1,否則ZF被清0。該指令只影響ZF標志。
(2)寫檢驗指令
<DIV寫讀檢驗指令的一般格式如下:< DIV="">
VERW OPRD
其中,操作數OPRD可以是16位通用寄存器或存儲單元,也可以是32位通用寄存器或存儲單元。 該指令的功能是把OPRD的內容作為一個選擇子(當32位時僅使用低16位),判斷在當前特權級上 該選擇子所指示的段是否可寫。如果該選擇子指示合法的一個存儲段描述符,并且在當前特權 級上可寫所描述的段,那么零標志ZF被置為1,否則ZF被清0。該指令只影響ZF標志。
<四>顯示關鍵寄存器內容的實例(實例八)
為了更好地說明操作系統類指令的使用,下面給出一個顯示80386關鍵寄存器內容的實例。該實 例的邏輯功能是,顯示系統中GDTR、IDTR、LDTR和TR等關鍵寄存器的當前內容。實例八的源程 序清單如下:
;名稱: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而 執行它們,那么會引起通用保護異常。從上面介紹的操作系統類指令可歸納出如下表所示 的80386特權指令。這些特權指令在構成完善的保護機制方面起了重要的作用。
?
| 特 | 指 令 | 功 能 | 指 令 | 功 能 |
| CLTS | 清除CR0中的TS位 | LTR | 裝入TR寄存器 | |
| HLT | 停機 | MOV CRn,reg | 裝入控制寄存器 | |
| LGDT | 裝入GDTR寄存器 | MOV reg,CRn | 保存控制寄存器 | |
| LIDT | 裝入IDTR寄存器 | MOV DRn,reg | 裝入調試寄存器 | |
| LLDT | 裝入LDTR寄存器 | MOV reg,DRn | 保存調試寄存器 | |
| LMSW | 裝入MSW寄存器(CR0的低16位) | ? | ? |
?
從上表可見,裝入GDTR、IDTR、LDTR、TR和MSW的指令都是特權指令,而存儲上述寄存器的 指令不是特權指令。這表示,保護模式下任何程序可獲得這些寄存器的值,但只有特權 級0的程序才能夠改變這些寄存器的值。從上表還可以看出,設置和存儲控制寄存器及調試 寄存器的指令都是特權指令。
總結
- 上一篇: 保护模式下GDTR,LDTR,全局描述符
- 下一篇: 内存管理寄存器