From 1e12320c28e9547eae43d135c30d0cd14048f3c1 Mon Sep 17 00:00:00 2001 From: icecoobe Date: Mon, 11 Mar 2019 17:51:38 +0800 Subject: [PATCH] example on GDT --- mbr/gdt.asm | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ mbr/gdt.h | 23 +++++++++++ mbr/inc/gdt.inc | 21 ++++++++++ 3 files changed, 151 insertions(+) create mode 100644 mbr/gdt.asm create mode 100644 mbr/gdt.h create mode 100644 mbr/inc/gdt.inc diff --git a/mbr/gdt.asm b/mbr/gdt.asm new file mode 100644 index 0000000..abb1ec6 --- /dev/null +++ b/mbr/gdt.asm @@ -0,0 +1,107 @@ + +%include "inc/gdt.inc" + + org 0x7c00 + + mov ax, cs + mov ds, ax + mov ss, ax + +clear_screen: + mov ax, 0x0003 + int 0x10 + +setup_gdt: + mov si, gdt + xor ax, ax + mov es, ax + mov di, [gdt_base] + mov cx, gdt_size;32 + rep movsb + +main: + lgdt [gdtr] + + Enable_A20 + cli ;保护模式下中断机制尚未建立,应禁止中断 + Enable_ProtectMode + + ;; 仍然是运行当前的 MBR 程序,但是模式变成了保护模式 + ;; 因此,offset 需要重新计算,减去编译指定的 org 0x7c00 + ;jmp dword 0x8:flush_regs-0x7c00 + jmp dword 0x8:0x0 + + [bits 32] +flush_regs: + mov ax, 0x10 + mov gs, ax + + mov al, 'A' + xor bx, bx + mov cx, 5 +write_vram: + mov [gs:bx], al + inc al + add bx, 2 + dec cx + jnz write_vram + +halt: + hlt + +gdt: + .null_desc: + dq 0x0 + + ; .text_seg_desc: + ; dd 0x7c0001ff + ; dd 0x00409800 + + ;; 仍然是运行当前的 MBR 程序,但是模式变成了保护模式 + ;; 段的起始地址还是之前的 0x7c00,当然也可以在编译器计算好 + ;; 可以以flush_regs为新程序的起点,重新设置段地址 + ;; size: 0x7b00 + .text_seg_desc: + dw 0x7aff ;; limit 15-0 + ;dw 0x7c00 ;; Base 15-0 + dw flush_regs ;; Base 15-0 + + db 0x00 ;; Base 23-16 + db 1001_1110B ;; P DPL S Type + db 0100_0000B ;; G DB L AVL limit19-16 + db 0x00 ;; Base 31-24 + + ;;0xB8000-0xBFFFF (64 KB) + ;;Base:0x00000000000B8000 (32bit) + ;;limit:0x008000 (20bit) + .vram_seg_desc: + dw 0x7 ;;0x8000 + dw 0x8000 + + db 0xB ;; Base 23-16 + db 1001_0010B ;; P DPL S Type + db 110100_00B ;; G DB L AVL limit19-16 + db 0x0 ;; Base 31-24 + + ;; + ;; + ;; limit:0x1000000 (1MB) + .stack_seg_desc: + dw 0x0400 ;; limit 15-0 + dw 0x0000 ;; Base 15-0 + + db 0x00 ;; Base 23-16 + db 1001_0110B ;; P DPL S Type + db 010000_00B ;; G DB L AVL limit19-16 + db 0x0 ;; Base 31-24 +gdt_size equ ($ - gdt) + + +;; 这部分可以不占用data段,可以使用字面常量 +;; 处理器没有规定 +gdtr: + gdt_limit dw (gdt_size - 1) ;; MAX=2^16=64KB + gdt_base dd 0x7e00 + +times 510-($-$$) db 0 + db 0x55,0xaa \ No newline at end of file diff --git a/mbr/gdt.h b/mbr/gdt.h new file mode 100644 index 0000000..b758f60 --- /dev/null +++ b/mbr/gdt.h @@ -0,0 +1,23 @@ + +typedef unsigned char byte; +typedef unsigned short ushort; + +struct seg_desc +{ + // Nibble LO (32 bit) + ushort limit_15_0; + ushort base_15_0; + + // Nibble HL + byte base_23_16:8; + byte type:4; + byte S:1; + byte DPL:2; + byte P:1; + byte limit_19_16:4; + byte AVL:1; + byte L:1; + byte D_B:1; + byte G:1; + byte base_31_24:8; +}; \ No newline at end of file diff --git a/mbr/inc/gdt.inc b/mbr/inc/gdt.inc new file mode 100644 index 0000000..aefb95b --- /dev/null +++ b/mbr/inc/gdt.inc @@ -0,0 +1,21 @@ + +;; 开启 A20 地址线 +;; 入口参数: 无 +;; 返回: 无 +;; 备注: +;; 这是利用 ICH 端口快速开启 A20 的方式; +;; 旧版采用键盘控制器中一个端口 +%macro Enable_A20 0 + in al, 0x92 ;; ICH I/O port + or al, 0000_0010B + out 0x92, al ;; 打开A20 +%endmacro + +;; 开启保护模式 cr0.PE=1 +;; 入口参数: 无 +;; 返回: 无 +%macro Enable_ProtectMode 0 + mov eax, cr0 + or eax, 1 + mov cr0, eax +%endmacro \ No newline at end of file