参考:
https://blog.csdn.net/tyler_download/article/details/52021120
https://www.bilibili.com/video/BV1VJ41157wq?p=5&spm_id_from=pageDriver
先分析kernel.asm
https://github.com/wycl16514/OS-Kernel-from-real-to-protected-mode/blob/master/kernel.asm
这段代码有些复杂
先定义GDT
然后是16位跳转到32位
然后在32位模式下,往显存里面复制message,显示出来。
再分析pm.inc
https://github.com/wycl16514/OS-Kernel-from-real-to-protected-mode/blob/master/pm.inc
Descriptor 在这里定义。
编译为kernel.bat,用上一节的工具制作system.img,加载运行出错。检查发现boot.asm偏移地址不太对,需要修改一下
https://github.com/wycl16514/OS-Kernel-from-real-to-protected-mode/blob/master/boot.asm
LOAD_ADDR EQU 0X9000
修改后问题解决:
kernel.asm
%include "pm.inc"
org 0x9000
jmp LABEL_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, 0fffh, DA_DRW
GdtLen equ $ - LABEL_GDT
GdtPtr dw GdtLen - 1
dd 0
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
[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_GDT
mov dword [GdtPtr + 2], eax
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
[SECTION .s32]
[BITS 32]
LABEL_SEG_CODE32:
mov ax, SelectorVideo
mov gs, ax
mov si, msg
mov ebx, 10
mov ecx, 2
showChar:
mov edi, (80*11)
add edi, ebx
mov eax, edi
mul ecx
mov edi, eax
mov ah, 0ch
mov al, [si]
cmp al, 0
je end
add ebx, 1
add si, 1
mov [gs:edi], ax
jmp showChar
end:
jmp $
msg:
DB "Protect Mode", 0
SegCode32Len equ $ - LABEL_SEG_CODE32
pm.inc
%macro Descriptor 3
dw %2 & 0FFFFh
dw %1 & 0FFFFh
db (%1>>16) & 0FFh
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)
db (%1 >> 24) & 0FFh
%endmacro
DA_32 EQU 4000h
DA_C EQU 98h
DA_DRW EQU 92h
boot.asm
org 0x7c00;
LOAD_ADDR EQU 0X9000
entry:
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov si, ax
readFloppy:
mov CH, 1 ;CH 用来存储柱面号
mov DH, 0 ;DH 用来存储磁头号
mov CL, 2 ;CL 用来存储扇区号
mov BX, LOAD_ADDR ; ES:BX 数据存储缓冲区
mov AH, 0x02 ; AH = 02 表示要做的是读盘操作
mov AL, 1 ; AL 表示要练习读取几个扇区
mov DL, 0 ;驱动器编号,一般我们只有一个软盘驱动器,所以写死
;为0
INT 0x13 ;调用BIOS中断实现磁盘读取功能
JC fin
jmp LOAD_ADDR
fin:
HLT
jmp fin