【学习笔记】自己动手写操作系统--pmtest4

ContractedBlock.gif ExpandedBlockStart.gif Code
; ==========================================
;
 pmtest4.asm
;
 编译方法:nasm pmtest4.asm -o pmtest4.com
;
 ==========================================

%include    
"pm.inc"    ; 常量, 宏, 以及一些说明

org    0100h
    
jmp    LABEL_BEGIN

[SECTION .gdt]
; GDT
;
                                         段基址,       段界限     , 属性
LABEL_GDT:        Descriptor           0,         00             ; 空描述符
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
; 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

    
call    SelectorCallGateTest:0    ; 测试调用门(无特权级变换),将打印字母 'C'。
    ;call    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]

转载于:https://www.cnblogs.com/dfzx/archive/2009/05/27/1490817.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值