《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)...
在上次的代碼基礎上,添加一個代碼段作為通過調用門轉移的目標段。了解一下調用的工作方法,代碼分析如下:
<<紅色標識部分為新增代碼>>
; ==========================================
; pmtest4.asm
; 編譯方法:nasm pmtest4.asm -o pmtest4.com
; ==========================================
%include??? "pm.inc"??? ; 常量, 宏, 以及一些說明
org??? 0100h
??? jmp??? 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_CODE_DEST: Descriptor 0,SegCodeDestLen-1, DA_C+DA_32; 非一致代碼段,32;目標代碼描述符
LABEL_DESC_DATA:????? Descriptor 0,?????? DataLen-1, DA_DRW??? ; Data
LABEL_DESC_STACK:???? Descriptor 0,????? TopOfStack, DA_DRWA+DA_32;Stack, 32 位
LABEL_DESC_LDT:?????? Descriptor 0,??????? LDTLen-1, DA_LDT??? ; LDT
LABEL_DESC_VIDEO:???? Descriptor 0B8000h,??? 0ffffh, DA_DRW??? ; 顯存首地址
; 門?????????????????????????????? 目標選擇子,偏移,DCount, 屬性
LABEL_CALL_GATE_TEST: Gate SelectorCodeDest,?? 0,???? 0, DA_386CGate+DA_DPL0;調用門描述符DPL=0
; 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
SelectorCodeDest??? equ??? LABEL_DESC_CODE_DEST??? - LABEL_GDT;目標代碼選擇子
SelectorData??????? equ??? LABEL_DESC_DATA??????? - LABEL_GDT
SelectorStack??????? equ??? LABEL_DESC_STACK??? - LABEL_GDT
SelectorLDT??????? equ??? LABEL_DESC_LDT??????? - LABEL_GDT
SelectorVideo??????? equ??? LABEL_DESC_VIDEO??? - LABEL_GDT
SelectorCallGateTest??? equ??? LABEL_CALL_GATE_TEST??? - 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, cs
??? mov??? ds, ax
??? mov??? es, ax
??? mov??? ss, ax
??? mov??? sp, 0100h
??? mov??? [LABEL_GO_BACK_TO_REAL+3], ax
??? mov??? [SPValueInRealMode], sp
??? ; 初始化 16 位代碼段描述符
??? mov??? ax, cs
??? movzx??? eax, ax
??? shl??? eax, 4
??? add??? eax, LABEL_SEG_CODE16
??? mov??? word [LABEL_DESC_CODE16 + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_CODE16 + 4], al
??? mov??? byte [LABEL_DESC_CODE16 + 7], ah
??? ; 初始化 32 位代碼段描述符
??? xor??? eax, eax
??? mov??? ax, cs
??? shl??? eax, 4
??? add??? eax, LABEL_SEG_CODE32
??? mov??? word [LABEL_DESC_CODE32 + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_CODE32 + 4], al
??? mov??? byte [LABEL_DESC_CODE32 + 7], ah
??? ; 初始化測試調用門的代碼段描述符
??? xor??? eax, eax
??? mov??? ax, cs
??? shl??? eax, 4
??? add??? eax, LABEL_SEG_CODE_DEST
??? mov??? word [LABEL_DESC_CODE_DEST + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_CODE_DEST + 4], al
??? mov??? byte [LABEL_DESC_CODE_DEST + 7], ah
??? ; 初始化數據段描述符
??? xor??? eax, eax
??? mov??? ax, ds
??? shl??? eax, 4
??? add??? eax, LABEL_DATA
??? mov??? word [LABEL_DESC_DATA + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_DATA + 4], al
??? mov??? byte [LABEL_DESC_DATA + 7], ah
??? ; 初始化堆棧段描述符
??? xor??? eax, eax
??? mov??? ax, ds
??? shl??? eax, 4
??? add??? eax, LABEL_STACK
??? mov??? word [LABEL_DESC_STACK + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_STACK + 4], al
??? mov??? byte [LABEL_DESC_STACK + 7], ah
??? ; 初始化 LDT 在 GDT 中的描述符
??? xor??? eax, eax
??? mov??? ax, ds
??? shl??? eax, 4
??? add??? eax, LABEL_LDT
??? mov??? word [LABEL_DESC_LDT + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_DESC_LDT + 4], al
??? mov??? byte [LABEL_DESC_LDT + 7], ah
??? ; 初始化 LDT 中的描述符
??? xor??? eax, eax
??? mov??? ax, ds
??? shl??? eax, 4
??? add??? eax, LABEL_CODE_A
??? mov??? word [LABEL_LDT_DESC_CODEA + 2], ax
??? shr??? eax, 16
??? mov??? byte [LABEL_LDT_DESC_CODEA + 4], al
??? mov??? byte [LABEL_LDT_DESC_CODEA + 7], ah
??? ; 為加載 GDTR 作準備
??? xor??? eax, eax
??? mov??? ax, ds
??? shl??? eax, 4
??? add??? eax, LABEL_GDT??????? ; eax <- gdt 基地址
??? mov??? dword [GdtPtr + 2], eax??? ; [GdtPtr + 2] <- gdt 基地址
??? ; 加載 GDTR
??? lgdt??? [GdtPtr]
??? ; 關中斷
??? cli
??? ; 打開地址線A20
??? in??? al, 92h
??? or??? al, 00000010b
??? out??? 92h, al
??? ; 準備切換到保護模式
??? mov??? eax, cr0
??? or??? eax, 1
??? mov??? cr0, eax
??? ; 真正進入保護模式
??? jmp??? dword SelectorCode32:0??? ; 執行這一句會把 SelectorCode32 裝入 cs, 并跳轉到 Code32Selector:0? 處
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LABEL_REAL_ENTRY:??????? ; 從保護模式跳回到實模式就到了這里
??? mov??? ax, cs
??? mov??? ds, ax
??? mov??? es, ax
??? mov??? ss, ax
??? mov??? sp, [SPValueInRealMode]
??? in??? al, 92h??????? ; ┓
??? and??? al, 11111101b??? ; ┣ 關閉 A20 地址線
??? out??? 92h, al??????? ; ┛
??? sti??????????? ; 開中斷
??? mov??? ax, 4c00h??? ; ┓
??? int??? 21h??????? ; ┛回到 DOS
; END of [SECTION .s16]
[SECTION .s32]; 32 位代碼段. 由實模式跳入.
[BITS??? 32]
LABEL_SEG_CODE32:
??? mov??? ax, SelectorData
??? mov??? ds, ax??????????? ; 數據段選擇子
??? mov??? ax, SelectorVideo
??? mov??? gs, ax??????????? ; 視頻段選擇子
??? mov??? ax, SelectorStack
??? mov??? ss, ax??????????? ; 堆棧段選擇子
??? mov??? esp, TopOfStack
??? ; 下面顯示一個字符串
??? mov??? ah, 0Ch??????????? ; 0000: 黑底??? 1100: 紅字
??? xor??? esi, esi
??? xor??? edi, edi
??? mov??? esi, OffsetPMMessage??? ; 源數據偏移
??? mov??? edi, (80 * 10 + 0) * 2??? ; 目的數據偏移。屏幕第 10 行, 第 0 列。
??? cld
.1:
??? lodsb
??? test??? al, al
??? jz??? .2
??? mov??? [gs:edi], ax
??? add??? edi, 2
??? jmp??? .1
.2:??? ; 顯示完畢
??? call??? DispReturn
??? ; 測試調用門(無特權級變換),將打印字母 'C'
??? call??? SelectorCallGateTest:0
??? ;call??? SelectorCodeDest:0 ---SelectorCallGateTest的選擇子為SelectorCodeDest,偏移為0
??? ; Load LDT
??? mov??? ax, SelectorLDT
??? lldt??? ax
??? jmp??? SelectorLDTCodeA:0??? ; 跳入局部任務,將打印字母 'L'。
; ------------------------------------------------------------------------
DispReturn:
??? push??? eax
??? push??? ebx
??? mov??? eax, edi
??? mov??? bl, 160
??? div??? bl
??? and??? eax, 0FFh
??? inc??? eax
??? mov??? bl, 160
??? mul??? bl
??? mov??? edi, eax
??? pop??? ebx
??? pop??? eax
??? ret
; DispReturn 結束---------------------------------------------------------
SegCode32Len??? equ??? $ - LABEL_SEG_CODE32
; END of [SECTION .s32]
[SECTION .sdest]; 調用門目標段
[BITS??? 32]
LABEL_SEG_CODE_DEST:
??? ;jmp??? $
??? mov??? ax, SelectorVideo
??? mov??? gs, ax??????????? ; 視頻段選擇子(目的)
??? mov??? edi, (80 * 12 + 0) * 2??? ; 屏幕第 12 行, 第 0 列。
??? mov??? ah, 0Ch??????????? ; 0000: 黑底??? 1100: 紅字
??? mov??? al, 'C'
??? mov??? [gs:edi], ax
??? retf
SegCodeDestLen??? equ??? $ - LABEL_SEG_CODE_DEST
; END of [SECTION .sdest]
; 16 位代碼段. 由 32 位代碼段跳入, 跳出后到實模式
[SECTION .s16code]
ALIGN??? 32
[BITS??? 16]
LABEL_SEG_CODE16:
??? ; 跳回實模式:
??? mov??? ax, SelectorNormal
??? mov??? ds, ax
??? mov??? es, ax
??? mov??? fs, ax
??? mov??? gs, ax
??? mov??? ss, ax
??? mov??? eax, cr0
??? and??? al, 11111110b
??? mov??? cr0, eax
LABEL_GO_BACK_TO_REAL:
??? jmp??? 0:LABEL_REAL_ENTRY??? ; 段地址會在程序開始處被設置成正確的值
Code16Len??? equ??? $ - LABEL_SEG_CODE16
; END of [SECTION .s16code]
; LDT
[SECTION .ldt]
ALIGN??? 32
LABEL_LDT:
;???????????????????????????????????????? 段基址?????? 段界限???? ,?? 屬性
LABEL_LDT_DESC_CODEA:??? Descriptor?????????? 0,???? CodeALen - 1,?? DA_C + DA_32??? ; Code, 32 位
LDTLen??????? equ??? $ - LABEL_LDT
; LDT 選擇子
SelectorLDTCodeA??? equ??? LABEL_LDT_DESC_CODEA??? - LABEL_LDT + SA_TIL
; END of [SECTION .ldt]
; CodeA (LDT, 32 位代碼段)
[SECTION .la]
ALIGN??? 32
[BITS??? 32]
LABEL_CODE_A:
??? mov??? ax, SelectorVideo
??? mov??? gs, ax??????????? ; 視頻段選擇子(目的)
??? mov??? edi, (80 * 13 + 0) * 2??? ; 屏幕第 13 行, 第 0 列。
??? mov??? ah, 0Ch??????????? ; 0000: 黑底??? 1100: 紅字
??? mov??? al, 'L'
??? mov??? [gs:edi], ax
??? ; 準備經由16位代碼段跳回實模式
??? jmp??? SelectorCode16:0
CodeALen??? equ??? $ - LABEL_CODE_A
; END of [SECTION .la]
Gate宏的分析請見《Orange’s 一個操作系統的實現》3.保護模式1----pm.inc分析:
?
本代碼只是展示了調用的使用方式,即提供了目標代碼段的入口地址及相關附加屬性(無特權級的轉移),如果需要特權級的轉移,則需
參照以下規則:
假設我們有代碼A轉移到代碼B,使用一個調用G,即調用門G中的目標選擇子指向代碼B的段。我們涉及到這么幾個要素CPL、RPL、
代碼B的DPL(記做DPL_B)、調用門的DPL(記做DPL_G)。根據《Orange’s 一個操作系統的實現》3.保護模式5----特權級概述(轉)
介紹可知A訪問調用門G時,相當于訪問一個數據段,要求CPL和RPL都小于或者等于DPL_G.換句話說,CPL和RPL須在更高的特權級上.
除此之外,還需比較CPL和DPL_B,如果是一致代碼段,則要求DPL_B<=CPL;如果是非一致代碼段,call和jmp指令又有所不同,使用
CALL時,要求DPL_B<=CPL;使用Jmp時,只能是DPL-B=CPL
規則如下
| 目標代碼段 | call | jmp |
| 目標是一致代碼段 | CPL<=DPL_G | 同CALL |
| ? | RPL<=DPL_G | 同CALL |
| ? | DPL_B<=CPL | 同CALL |
| 目標是非一致代碼 | CPL<=DPL_G | CPL<=DPL_G |
| ? | RPL<=DPL_G | RPL<=DPL_G |
| ? | DPL_B<=CPL | DPL_B=CPL |
綜上:通過調用門和call指令,可以實現從低特權級到高特權級的轉移,無論目標代碼是一致的還是非一致的
轉載于:https://www.cnblogs.com/Aoysme/archive/2011/01/17/1937759.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-无特权级转换)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mac下IPhone开发环境配置
- 下一篇: Windows下删除.svn文件夹的简易