;======================================
;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]
實模式到保護模式的轉變
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.