实模式到保护模式的转变


;======================================
;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]

猜你喜欢

转载自blog.csdn.net/u012323667/article/details/79268836