|
@@ -3,30 +3,90 @@
|
|
|
; ----------------------------------------------------------------
|
|
; ----------------------------------------------------------------
|
|
|
%include "boot.inc"
|
|
%include "boot.inc"
|
|
|
SECTION LOADER vstart=LOADER_BASE_ADDR
|
|
SECTION LOADER vstart=LOADER_BASE_ADDR
|
|
|
|
|
+LOADER_STACK_TOP equ LOADER_BASE_ADDR
|
|
|
|
|
+jmp loader_start
|
|
|
|
|
|
|
|
-; 输出背景绿色,前景红色,并且跳动的字符串 "2 LOADER"
|
|
|
|
|
- mov byte [gs:0x00], '2'
|
|
|
|
|
- mov byte [gs:0x01], 0xA4
|
|
|
|
|
|
|
+; 构建 GDT 及其内部描述符(GDT 的第 0 个描述符不可用)
|
|
|
|
|
+GDT_BASE: dd 0x00000000
|
|
|
|
|
+ dd 0x00000000
|
|
|
|
|
|
|
|
- mov byte [gs:0x02], ' '
|
|
|
|
|
- mov byte [gs:0x03], 0xA4
|
|
|
|
|
|
|
+CODE_DESC: dd 0x0000FFFF
|
|
|
|
|
+ dd DESC_CODE_HIGH4
|
|
|
|
|
|
|
|
- mov byte [gs:0x04], 'L'
|
|
|
|
|
- mov byte [gs:0x05], 0xA4
|
|
|
|
|
|
|
+DATA_STACK_DESC: dd 0x0000FFFF
|
|
|
|
|
+ dd DESC_DATA_HIGH4
|
|
|
|
|
|
|
|
- mov byte [gs:0x06], 'O'
|
|
|
|
|
- mov byte [gs:0x07], 0xA4
|
|
|
|
|
|
|
+VIDEO_DESC: dd 0x80000007 ; limit=(0xbffff-0xb8000)/4k=0x7
|
|
|
|
|
+ dd DESC_VIDEO_HIGH4 ; 此时 dpl 为 0
|
|
|
|
|
|
|
|
- mov byte [gs:0x08], 'A'
|
|
|
|
|
- mov byte [gs:0x09], 0xA4
|
|
|
|
|
|
|
+GDT_SIZE equ $ - GDT_BASE
|
|
|
|
|
+GDT_LIMIT equ GDT_SIZE - 1
|
|
|
|
|
+times 60 dq 0 ; 此处预留 60 个描述符的空位
|
|
|
|
|
|
|
|
- mov byte [gs:0x0A], 'D'
|
|
|
|
|
- mov byte [gs:0x0B], 0xA4
|
|
|
|
|
|
|
+SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ; 相当于 (CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0
|
|
|
|
|
+SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0
|
|
|
|
|
+SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0
|
|
|
|
|
|
|
|
- mov byte [gs:0x0C], 'E'
|
|
|
|
|
- mov byte [gs:0x0D], 0xA4
|
|
|
|
|
|
|
+; 以下是 gdt 的指针,前 2 个字节是 gdt 界限,后 4 字节是 gdt 起始地址
|
|
|
|
|
+gdt_ptr dw GDT_LIMIT
|
|
|
|
|
+ dd GDT_BASE
|
|
|
|
|
+loadermsg db '2 loader in real.'
|
|
|
|
|
|
|
|
- mov byte [gs:0x0E], 'R'
|
|
|
|
|
- mov byte [gs:0x0F], 0xA4
|
|
|
|
|
|
|
+loader_start:
|
|
|
|
|
+;----------------------------------------------------------------
|
|
|
|
|
+; INT 0x10 功能号:0x13 功能描述: 打印字符串
|
|
|
|
|
+;----------------------------------------------------------------
|
|
|
|
|
+; 输入:
|
|
|
|
|
+; AH 子功能号 13H
|
|
|
|
|
+; BH = 页码
|
|
|
|
|
+; BL = 属性(若 AL=00H 或 01H)
|
|
|
|
|
+; CX = 字符串长度
|
|
|
|
|
+; (DH、DL) = 坐标(行,列)
|
|
|
|
|
+; ES:BP = 字符串地址
|
|
|
|
|
+; AL=显示输出方式
|
|
|
|
|
+; 0 ---- 字符串中只含显示字符,其显示属性在 BL 中,显示后,光标位置不变
|
|
|
|
|
+; 1 ---- 字符串中只含显示字符,其显示属性在 BL 中,显示后,光标位置不变
|
|
|
|
|
+; 2 ---- 字符串中含显示字符和显示属性。显示后,光标位置不变
|
|
|
|
|
+; 3 ---- 字符串中含显示字符和显示属性。显示后,光标位置改变
|
|
|
|
|
+; 无返回值
|
|
|
|
|
+ mov sp, LOADER_BASE_ADDR
|
|
|
|
|
+ mov bp, loadermsg ; ES:BP = 字符串地址
|
|
|
|
|
+ mov cx, 17 ; CX = 字符串长度
|
|
|
|
|
+ mov ax, 0x1301 ; AH = 13h, AL = 01h
|
|
|
|
|
+ mov bx ,0x001f ; 页号 0(BH=0)蓝底粉红色(BL=1fh)
|
|
|
|
|
+ mov dx, 0x1800 ; 坐标(行,列)
|
|
|
|
|
+ int 0x10 ; 10h 号中断
|
|
|
|
|
|
|
|
- jmp $ ; 通过死循环使程序悬停在此
|
|
|
|
|
|
|
+;---------------------- 准备进入保护模式 ------------------------------------------
|
|
|
|
|
+; 1 打开 A20
|
|
|
|
|
+; 2 加载 GDT
|
|
|
|
|
+; 3 将 cr0 的 pe 位置 1
|
|
|
|
|
+
|
|
|
|
|
+ ;-------------------------- 打开 A20 --------------------------------
|
|
|
|
|
+ in al, 0x92
|
|
|
|
|
+ or al, 0000_0010b
|
|
|
|
|
+ out 0x92, al
|
|
|
|
|
+
|
|
|
|
|
+ ;-------------------------- 加载 GDT --------------------------------
|
|
|
|
|
+ LGDT [gdt_ptr]
|
|
|
|
|
+
|
|
|
|
|
+ ;-------------------------- cr0 第 0 位置 1 --------------------------
|
|
|
|
|
+ mov eax, cr0
|
|
|
|
|
+ or eax, 0x00000001
|
|
|
|
|
+ mov cr0, eax
|
|
|
|
|
+
|
|
|
|
|
+ jmp dword SELECTOR_CODE:p_mode_start ; 刷新流水线
|
|
|
|
|
+
|
|
|
|
|
+[bits 32]
|
|
|
|
|
+p_mode_start:
|
|
|
|
|
+ mov ax, SELECTOR_DATA
|
|
|
|
|
+ mov ds, ax
|
|
|
|
|
+ mov es, ax
|
|
|
|
|
+ mov ss, ax
|
|
|
|
|
+ mov esp, LOADER_STACK_TOP
|
|
|
|
|
+ mov ax, SELECTOR_VIDEO
|
|
|
|
|
+ mov gs, ax
|
|
|
|
|
+
|
|
|
|
|
+ mov byte [gs:160], 'P'
|
|
|
|
|
+
|
|
|
|
|
+ jmp $
|