【学习笔记】自己动手写操作系统——pmtest2

ContractedBlock.gif ExpandedBlockStart.gif Code
; ==========================================
;
 pmtest2.asm
;
 编译方法:nasm pmtest2.asm -o pmtest2.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_DATA:    Descriptor           0,    DataLen - 1, DA_DRW        ; Data
LABEL_DESC_STACK:    Descriptor           0,        TopOfStack, DA_DRWA + DA_32    ; Stack, 32 位
LABEL_DESC_TEST:    Descriptor    0500000h,            0ffffh, DA_DRW
LABEL_DESC_VIDEO:    Descriptor     0B8000h,            0ffffh, DA_DRW        ; 显存首地址
;
 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
SelectorData        EQU    LABEL_DESC_DATA        - LABEL_GDT
SelectorStack        EQU    LABEL_DESC_STACK    - LABEL_GDT
SelectorTest        EQU    LABEL_DESC_TEST        - LABEL_GDT
SelectorVideo        EQU    LABEL_DESC_VIDEO    - 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 ;因为LABEL_GO_BACK_TO_REAL后的代码是个mov语句,对应的字节有三个,第三个自己恰是跳转地址

    
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, 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

    
; 为加载 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, SelectorTest
    
MOV    ES, 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    TestRead
    
CALL    TestWrite
    
CALL    TestRead

    
; 到此停止
    JMP    SelectorCode16:0

; ------------------------------------------------------------------------
TestRead:
    
XOR    ESI, ESI
    
MOV    ECX, 8
.loop
    
MOV    AL, [ES:ESI]
    
CALL    DispAL
    
INC    ESI
    LOOP    .loop

    
CALL    DispReturn

    
RET
; TestRead 结束-----------------------------------------------------------


; ------------------------------------------------------------------------
TestWrite:
    
PUSH    ESI
    
PUSH    EDI
    
XOR    ESI, ESI
    
XOR    EDI, EDI
    
MOV    ESI, OffsetStrTest    ; 源数据偏移
    CLD
.
1:
    
lodsb
    
TEST    AL, AL
    
JZ    .2
    
MOV    [ES:EDI], AL
    
INC    EDI
    
JMP    .1
.
2:

    
POP    EDI
    
POP    ESI

    
RET
; TestWrite 结束----------------------------------------------------------


; ------------------------------------------------------------------------
;
 显示 AL 中的数字
;
 默认地:
;
    数字已经存在 AL 中
;
    edi 始终指向要显示的下一个字符的位置
;
 被改变的寄存器:
;
    ax, edi
;
 ------------------------------------------------------------------------
DispAL:
    
PUSH    ECX
    
PUSH    EDX

    
MOV    AH, 0Ch            ; 0000: 黑底    1100: 红字
    MOV    DL, AL
    
SHR    AL, 4
    
MOV    ECX, 2
.
begin:
    
AND    AL, 01111b
    
CMP    AL, 9
    
JA    .1
    
ADD    AL, '0'
    
JMP    .2
.
1:
    
SUB    AL, 0Ah
    
ADD    AL, 'A'
.
2:
    
MOV    [gs:EDI], AX
    
ADD    EDI, 2

    
MOV    AL, DL
    LOOP    .begin
    
ADD    EDI, 2

    
POP    EDX
    
POP    ECX

    
RET
; DispAL 结束-------------------------------------------------------------


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


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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值