作者在介绍了一个简单的引导区程序后,就开始引入了DOS操作系统,我感觉在介绍一个从零开始的操作系统时,引入一个成型的操作系统不是一件很好的事情,因此非到万不得已,我还是坚持在pmtest1.asm程序上改动这个操作系统的雏形,直到编译之后的文件体积超过了510字节。
作者为了展示保护模式下强大的数据读取能力,将一块数据区放在了5M的位置,然后先写后读,我在pmtest1.asm的基础上,完成了和作者几乎一样的功能,也能够很好地理解保护模式下数据读取的强大能力。其中红色代码部分为本程序增加内容
%include "pm.inc" ; 常量, 宏, 以及一些说明
org 07c00h
HAHA_begin:
jmp LABEL_BEGIN
Qianlen equ $-HAHA_begin
[SECTION .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 ; 显存首地址
LABEL_DESC_HONDATA: Descriptor 0500000h, 0ffffh, DA_DRW ; HONDATA
LABEL_DESC_HONMSG: Descriptor 0, 0ffffh, DA_DRW ; HONMSG
GdtLen equ $ - LABEL_GDT ; GDT长度
GdtPtr dw GdtLen - 1 ; GDT界限
dd 0 ; GDT基地址
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
SelectorHONDATA equ LABEL_DESC_HONDATA - LABEL_GDT
SelectorHONMSG equ LABEL_DESC_HONMSG - LABEL_GDT
GDTLen1 equ $-LABEL_GDT
[SECTION .HONMSG]
LABEL_HONMSG:
Message db "Hello world!",0
OffsetMessage equ $-LABEL_HONMSG
;End of [SECTION .HONDATA]
HONMSGLen equ $-LABEL_HONMSG
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h
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_HONMSG
mov word [LABEL_DESC_HONMSG+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_GDT ; eax <- gdt 基地址
mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址
lgdt [GdtPtr]
cli
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 处
mov eax, cr0
SegCode16Len equ $-LABEL_BEGIN
[SECTION .s32]
[BITS 32]
LABEL_SEG_CODE32:
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子(目的)
mov ax, SelectorHONDATA
mov es, ax ; 5M数据段的选择子
mov ax, SelectorHONMSG
mov ds, ax ; message 段
;将MSG中的数据移动到DATA区域
mov edi, (80 * 10 + 0) * 2 ; 屏幕第 11 行, 第 79 列。
xor esi,esi
mov ah, 0Ch
mov al, 'A';
mov [gs:edi], ax
call Write
mov edi, (80 * 11 + 0) * 2
xor esi,esi
mov ah, 0Ch
mov ecx,20h
.begin:
mov al,[es:esi]
test al,al
jz .jieshu
mov [gs:edi], ax
inc esi
inc edi
inc edi
jmp .begin
.jieshu:
jmp $
Write:
push esi
push edi
push ecx
xor esi,esi
xor edi,edi
mov ecx,100
cld
.a:
lodsb
test al,al
jz over
stosb
loop .a
over:
pop ecx
pop edi
pop esi
ret
SegCode32Len equ $ - LABEL_SEG_CODE32
; END of [SECTION .s32]
times 510-(4+(GDTLen1+3)/4*4+(SegCode16Len+3)/4*4+(HONMSGLen+3)/4*4+(SegCode32Len)) db 0
dw 0xAA55