“实模式--保护模式--实模式”转换过程
下面以pmtest2.asm為例,來講述“實模式--保護模式--實模式”的轉換過程。
1、“實模式--保護模式--實模式”的轉換過程。
2、介紹段描述符屬性
3、pm.inc 中的宏定義
4、pmtest2.asm源代碼
一、“實模式--保護模式--實模式”的轉換過程
1、“實模式--保護模式”的跳轉
(1)關中斷
(2)打開地址線A20
(3)置cr0寄存器的末位為1
(4)實現跳轉,進入到保護模式
2、“保護模式--實模式”的跳轉
(1)從保護模式下的32位代碼段跳轉到16位代碼段
(2)在16位代碼段下初始化所有段寄存器
(3)置cr0的末位為0
(4)實現跳轉,返回到實模式
3、pmtest2.asm中“實模式--保護模式--實模式”的跳轉過程
(1)下面是“實模式--保護模式--實模式”的跳轉過程圖
其中?LABEL_BEGIN、LABEL_REAL_ENTRY運行于實模式下;LEBEL_SEG_CODE32、LABEL_SEG_CODE16運行于保護模式下。所以該程序實現了“實模式--保護模式--實模式”的跳轉。
(2)“實模式--保護模式”的跳轉
這個跳轉過程主要存在于LABEL_BEGIN代碼段中:
70- 71行:保存實模式下的SP內的值
73-111行:初始化段描述符
113-121行:加載GDTR
123-124行:關中斷
126-129行:打開地址線A20
141-144行:準備切換到保護模式,置cr0的末位為1
146-147行:跳轉到保護模式
(3)“保護模式--實模式”的跳轉
208-209行:從保護模式下的32位代碼段跳轉到16位代碼段
316-322行:為跳回實模式做準備,將段寄存器初始化為符合實模式下的代碼段規范。即用SelectorNormal來初始化段寄存器。
324-326行:置cr0的末位為0
328-329行:實現跳轉,進入到實模式下的 LABEL_REAL_ENTRY段
158-158行:恢復實模式下的SP
160-162行:關閉A20地址線
164-164行:開中斷
166-168行:返回DOS
二、段描述符的屬性
段描述符屬性占5、6字節,其具體特性如下:
在這里主要介紹第5字節的內容。
1、 P:存在(Present)位。
1 表示段在內存中存在
0 表示段在內存中不存在
2、 DPL:表示描述符特權級(Descriptor Privilege level),共2位。
它規定了所描述段的特權級,用于特權檢查,以決定對該段能否訪問。
3、 S:說明描述符的類型。
1 數據段和代碼段描述符
0系統段描述符和門描述符
4、 TYPE:說明存儲段描述符所描述的存儲段的具體屬性
數據段類型:
類型值 ? ? ? ? ? ? ?說明
---------------------------------
0 ? ? ? ? ? ? ? ?只讀
1 ? ? ? ? ? ? ? ?只讀、已訪問
2 ? ? ? ? ? ? ? ?讀/寫
3 ? ? ? ? ? ? ? ?讀/寫、已訪問
4 ? ? ? ? ? ? ? ?只讀、向下擴展
5 ? ? ? ? ? ? ? ?只讀、向下擴展、已訪問
6 ? ? ? ? ? ? ? ?讀/寫、向下擴展
7 ? ? ? ? ? ? ? ?讀/寫、向下擴展、已訪問
代碼段類型:
類型值 ? ? ? ? ? ? ?說明
---------------------------------
8 ? ? ? ? ? ? ? ?只執行
9 ? ? ? ? ? ? ? ?只執行、已訪問
A ? ? ? ? ? ? ? ?執行/讀
B ? ? ? ? ? ? ? ?執行/讀、已訪問
C ? ? ? ? ? ? ? ?只執行、一致碼段
D ? ? ? ? ? ? ? ?只執行、一致碼段、已訪問
E ? ? ? ? ? ? ? ?執行/讀、一致碼段
F ? ? ? ? ? ? ? ?執行/讀、一致碼段、已訪問
系統段類型:
類型編碼 ? ? ? ? 說明
----------------------------------
0 ? ? ? ? ? ? ? ?<未定義>
1 ? ? ? ? ? ? ? ?可用286TSS
2 ? ? ? ? ? ? ? ?LDT
3 ? ? ? ? ? ? ? ?忙的286TSS
4 ? ? ? ? ? ? ? ?286調用門
5 ? ? ? ? ? ? ? ?任務門
6 ? ? ? ? ? ? ? ?286中斷門
7 ? ? ? ? ? ? ? ?286陷阱門
8 ? ? ? ? ? ? ? ?未定義
9 ? ? ? ? ? ? ? ?可用386TSS
A ? ? ? ? ? ? ? ?<未定義>
B ? ? ? ? ? ? ? ?忙的386TSS
C ? ? ? ? ? ? ? ?386調用門
D ? ? ? ? ? ? ? ?<未定義>
E ? ? ? ? ? ? ? ?386中斷門
F ? ? ? ? ? ? ? ? 386陷阱門
三、pm.inc中的宏定義
在程序中,我們定義屬性時,使用了pm.inc中的宏定義DA_DRW、DA_C、DA_32、DA_DRW、DA_DRWA。下面讓我來向大家解釋這些宏定義。
DA ? : Descriptor Attribute
D ? ?: 數據段
C ? ?: 代碼段
S ? ?: 系統段
R ? ?: 只讀
RW ? : 讀寫
A ? ?: 已訪問
-----------------------------------------------------------
DA_32 ? ? ? ? ? ? ? EQU 4000h ? ? ? ; 32 位段
DA_DPL0 ? ? ? ? ?EQU ? 00h ? ? ? ?; DPL = 0
DA_DPL1 ? ? ? ? ?EQU ? 20h ? ? ? ?; DPL = 1
DA_DPL2 ? ? ? ? ?EQU ? 40h ? ? ? ?; DPL = 2
DA_DPL3 ? ? ? ? ?EQU ? 60h ? ? ? ?; DPL = 3
-----------------------------------------------------------
存儲段描述符類型值說明
-----------------------------------------------------------
DA_DR ? ? ? ? ? ? ? ? ?EQU 90h ?; 存在的只讀數據段類型值
DA_DRW ? ? ? ? ? ? ?EQU 92h ?; 存在的可讀寫數據段屬性值
DA_DRWA ? ? ? ? ? ?EQU 93h ?; 存在的已訪問可讀寫數據段類型值
DA_C ? ? ? ? ? ? ? ? ? ? EQU 98h ?; 存在的只執行代碼段屬性值
DA_CR ? ? ? ? ? ? ? ? ?EQU 9Ah ?; 存在的可執行可讀代碼段屬性值
DA_CCO ? ? ? ? ? ? ? EQU 9Ch ?; 存在的只執行一致代碼段屬性值
DA_CCOR ? ? ? ? ? ?EQU 9Eh ?; 存在的可執行可讀一致代碼段屬性值
-----------------------------------------------------------
?系統段描述符類型值說明
-----------------------------------------------------------
DA_LDT ? ? ? ? ? ? EQU ? 82h ? ? ? ; 局部描述符表段類型值
DA_TaskGate ? ?EQU ? 85h ? ? ? ; 任務門類型值
DA_386TSS ? ? ?EQU ? 89h ? ? ? ; 可用 386 任務狀態段類型值
DA_386CGate ? EQU ? 8Ch ? ? ? ; 386 調用門類型值
DA_386IGate ? ? EQU ? 8Eh ? ? ? ; 386 中斷門類型值
DA_386TGate ? ?EQU ? 8Fh ? ? ? ; 386 陷阱門類型值
四、pmtest2.asm源代碼:
;===================================================== ;pmtest2.asm ;編譯方法:nasm pmtest2.asm -o pmtest2.com%include "pm.inc" ;常量,宏,以及一些說明org 0100hjmp LABEL_BEGIN[SECTION .gdt] ;GDT ; 段基址 段界限 段屬性 LABEL_GDT: Descriptor 0, 0, 0 ;空描述符 LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ;Normal描述符 LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C + DA_32 ;非一致代碼段,32 LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ;非一致代碼段,16 LABEL_DESC_DATA: Descriptor 0, DataLen-1, DA_DRW + DA_DPL1 ;Data LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32 ;Stack,32位 LABEL_DESC_TEST: Descriptor 0500000h, 0ffffh, DA_DRW ;測試代碼段 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ;顯存首地址 ;GDT 結束GdtLen equ $ - LABEL_GDT ;GDT長度 GdtPtr dw GdtLen - 1 ;GDT界限dd 0 ;GDT基地址;GDT選擇子 SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT SelectorData equ LABEL_DESC_DATA - LABEL_GDT + SA_RPL3 SelectorStack equ LABEL_DESC_STACK - LABEL_GDT SelectorTest equ LABEL_DESC_TEST - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ;END of [SECTION .gdt][SECTION .data1] ;數據段 ALIGN 32 [BITS 32] LABEL_DATA: SPValueInRealMode dw 0 ;字符串 PMMessage: db "In Protect Mode now.", 0 ;進入保護模式后顯示該字符串 OffsetPMMessage equ PMMessage - $StrTest: db "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0 OffsetStrTest equ StrTest - $DataLen equ $ - LABEL_DATA ;END of [SECTION .data1];全局堆棧段 [SECTION .gs] ALIGN 32 [BITS 32] LABEL_STACK:times 512 db 0 TopOfStack equ $ - LABEL_STACK - 1 ;END of [SECTION .gs][SECTION .s16] [BITS 16] LABEL_BEGIN:mov ax, csmov ds, axmov es, axmov ss, axmov sp, 0100hmov [LABEL_GO_BACK_TO_REAL + 3], axmov [SPValueInRealMode], sp;初始化16位代碼段描述符mov ax, csmovzx eax, axshl eax, 4add eax, LABEL_SEG_CODE16mov word[LABEL_DESC_CODE16+2], axshr eax, 16mov byte[LABEL_DESC_CODE16+4], almov byte[LABEL_DESC_CODE16+7], ah;初始化32位代碼段描述符xor eax, eaxmov ax, csshl eax, 4add eax, LABEL_SEG_CODE32mov word[LABEL_DESC_CODE32+2], axshr eax, 16mov byte[LABEL_DESC_CODE32+4], almov byte[LABEL_DESC_CODE32+7], ah;初始化數據段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_DATAmov word[LABEL_DESC_DATA+2], axshr eax, 16mov byte[LABEL_DESC_DATA+4], almov byte[LABEL_DESC_DATA+7], ah;初始化堆棧段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_STACKmov word[LABEL_DESC_STACK+2], axshr eax, 16mov byte[LABEL_DESC_STACK+4], almov byte[LABEL_DESC_STACK+7], ah;為加載GDTR作準備xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_GDT ; eax <- gdtmov dword[GdtPtr+2], eax ; [GdtPtr+2] <- gdt 基地址;加載GDTRlgdt [GdtPtr];關中斷cli;打開地址線A20in al, 92hor al, 00000010bout 92h, al;清屏操作(用以指定色彩)mov ah, 06H ;功能06H和07H mov ch, 00 ;功能描述:初始化屏幕或滾屏mov cl, 00 ;入口參數:AH=06H——向上滾屏,07H——向下滾屏mov dh, 24 ;AL=滾動行數(0——清窗口)mov dl, 79 ;BH=空白區域的缺省屬性mov bh, 7 ;(CH、CL)=窗口的左上角位置(Y坐標,X坐標)mov al, 00 ;(DH、DL)=窗口的右下角位置(Y坐標,X坐標)int 10H ;出口參數:無;準備切換到保護模式mov eax, cr0or eax, 1mov cr0, eax;真正進入保護模式jmp dword SelectorCode32:0 ;執行這一句會把SelectorCode32裝入cs,并跳轉到SelectorCode32:0處;...................................................................... ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,LABEL_REAL_ENTRY: ;從保護模式跳回到實模式就到了這里mov ax, csmov ds, axmov es, axmov ss, axmov sp, [SPValueInRealMode]in al, 92h ;關閉A20地址線and al, 11111101b out 92h, alsti ;開中斷;回到DOSmov ax, 4C00hint 21h; ;END of [SECTION .s16][SECTION .s32] ;32位代碼段,由實模式跳入 [BITS 32]LABEL_SEG_CODE32:mov ax, SelectorDatamov ds, ax ;數據段選擇子mov ax, SelectorTestmov es, ax ;測試段選擇子mov ax, SelectorVideo mov gs, ax ;視頻段選擇子mov ax, SelectorStackmov ss, ax ;堆棧段選擇子mov esp, TopOfStack;下面顯示一個字符串mov ah, 0Ch ;0000:黑底 1100:紅字xor esi, esixor edi, edimov esi, OffsetPMMessage ;源數據偏移mov edi, (80*10+0)*2 ;目的數據偏移。屏幕第10行,第0列cld .1:lodsbtest al, aljz .2mov [gs:edi], ax ;將ax中的數據送入到顯存add edi, 2jmp .1 .2: ;顯示完畢call DispReturncall TestReadcall TestWriteCall TestRead;到此停止jmp SelectorCode16:0 ;---------------------------------------------------------------------------TestRead:xor esi, esimov ecx, 8 .loop:mov al, [es:esi]call DispALinc esiloop .loopcall DispReturnret ;TestRead結束--------------------------------------------------------------;-------------------------------------------------------------------------- TestWrite:push esipush edixor esi, esixor edi, edimov esi, OffsetStrTest ;源數據偏移.1:lodsbtest al, aljz .2mov [es:edi], alinc edijmp .1 .2:pop edipop esiret;TestWrite結束--------------------------------------------------------------;--------------------------------------------------------------------------- ;顯示AL中的數字 ;默認地: ; 數字已經存在AL中 ; edi始終指向要顯示的下一個字符的位置 ;被改變的寄存器 ; ax, edi ;---------------------------------------------------------------------------DispAL:push ecxpush edxmov ah, 0Chmov dl, alshr al, 4mov ecx, 2 .begin:and al, 01111bcmp al, 9ja .1add al, '0'jmp .2 .1:sub al, 0Ahadd al, 'A' .2:mov [gs:edi], axadd edi, 2mov al, dlloop .beginadd edi, 2pop edxpop ecxret ;DispAL結束-----------------------------------------------------------------;--------------------------------------------------------------------------- DispReturn:push eaxpush ebxmov eax, edimov bl, 160div bland eax, 0FFhinc eaxmov bl, 160mul blmov edi, eaxpop ebxpop eaxret ;DispReturn結束--------------------------------------------------------------SegCode32Len equ $ - LABEL_SEG_CODE32 ; END of [SECTION .s32];16位代碼段,由32位代碼段跳入,跳出后到實模式 [SECTION .s16code] ALIGN 32 [BITS 16] LABEL_SEG_CODE16:;跳回實模式:mov ax, SelectorNormalmov ds, axmov es, axmov fs, axmov gs, axmov ss, axmov eax, cr0and al, 11111110bmov cr0, eaxLABEL_GO_BACK_TO_REAL:jmp 0:LABEL_REAL_ENTRY ;段地址會在程序開始處被設置成正確的值Code16Len equ $-LABEL_SEG_CODE16 ;END of [SECTION .s16code]總結
以上是生活随笔為你收集整理的“实模式--保护模式--实模式”转换过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一章--最小的“操作系统”
- 下一篇: 第三章--堆栈段的工作方式