實模式到保護模式的轉變


;======================================
;pmtest1.asm
;編譯方法:nasm pmtest1.asm -o pmtest1.bin
;======================================
%include "pm.inc";  常量,宏 以及一些說明
;org 07c00h
org 0100h
    jmp LABEL_BEGIN

[SECTION .gdt]
;GDT    段基址  段界限 屬性

LABEL_GDT:  Descriptor 0, 0, 0 ;空描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32;  非一致代碼
LABEL_DESC_VIDEO : Descriptor 0B8000h, 0ffffh, DA_DRW;  顯存首地址
;GDT 就是一個數組結構

GdtLen  equ  $-LABEL_GDT  ;GDT長度
GdtPtr  dw   GdtLen - 1  ;GDT 界限
dd 0  ; GDT基地址   先寫0 待會補上
;GdtPtr也是一個數據結構  前2字節是GDT界限  後4字節是GDT基地址

;GDT 選擇子  相當於段內與LABEL_GDT的偏移
SelectorCode32  equ     LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo   equ LABEL_DESC_VIDEO - LABEL_GDT
; END of [SECTION .gdt]



;這是一個16位代碼段 這個程序主要有如下操作
;1.準備GDT,基址和長度寫入gdtr
;2.用lgdt加載gdtr
;3.打開A20  是地址能訪問32bits
;4.置cr0的PE位  設置cpu爲保護模式
;5.進行跳轉 跳到保護模式代碼中運行
;然後執行跳轉到第三個section
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0100h

    ;初始化32位代碼段描述符
    xor eax, eax ;eax清零
    mov ax, cs   ;將cs寫入eax的低16位
    shl eax, 4   ;左移四位
    add eax, LABEL_SEG_CODE32  ;加上偏移地址 獲得LABEL_SEG_CODE32的物理地址(20位) 保存在eax中
    mov word [LABEL_DESC_CODE32 + 2], ax;0-15 
    shr eax, 16
    mov byte [LABEL_DESC_CODE32 + 4], al;16-23
    mov byte [LABEL_DESC_CODE32 + 7], ah;24-31理論上應該是零  因爲是從實模式轉的 實模式地址最大爲20位  24-31只能爲0

    ;爲加載GDTR作準備
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_GDT; eax <- gdt基地址
    mov     dword [GdtPtr + 2], eax; [GdtPtr + 2] <- gdt 基地址寫入GdtPtr  (補上了)

    ;加載GDTR  將GdtPtr指示的六字節加載到寄存器gdtr中
    lgdt    [GdtPtr]

    ;關中斷
    cli

    ;打開地址線A20
    in  al, 92h
    or  al, 00000010b
    out 92h, al

    ;準備切換到保護模式 cr0置1
    mov eax, cr0
    or  eax, 1
    mov cr0, eax

    ;真正進入保護模式
    jmp dword   SelectorCode32:0 ;  執行這句會把SelectorCode32裝入CS

    ;並跳轉到SelectorCode32:0 處
    ;END of [SECTION .s16]



[SECTION .s32]
[BITS 32]

LABEL_SEG_CODE32:
    mov ax, SelectorVideo
    mov gs, ax
    ;視頻選擇子(目的)  

    mov     edi, (80 * 11 + 79) * 2;  屏幕第11行 第79列
    mov ah, 0Ch
    mov al, 'P'
    mov [gs:edi], ax;

    ;到此停止
    jmp $

SegCode32Len    equ $-LABEL_SEG_CODE32
;END of [SECTION .s32]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章