86 lines
3.5 KiB
NASM
86 lines
3.5 KiB
NASM
SELECTOR_KERNEL_CS equ 8
|
||
|
||
; 导入函数
|
||
extern cstart
|
||
|
||
; 导入全局变量
|
||
extern gdt_ptr
|
||
|
||
[SECTION .bss]
|
||
StackSpace resb 4096
|
||
StackTop: ; 栈顶
|
||
|
||
[section .text] ; 代码在此
|
||
|
||
global _start ; 导出 _start
|
||
|
||
_start:
|
||
; 此时内存看上去是这样的(更详细的内存情况在 LOADER.ASM 中有说明):
|
||
; ┃ ┃
|
||
; ┃ ... ┃
|
||
; ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃■■■■■■Page Tables■■■■■■┃
|
||
; ┃■■■■■(大小由LOADER决定)■■■■┃ PageTblBase
|
||
; 00101000h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃■■■■Page Directory Table■■■■┃ PageDirBase = 1M
|
||
; 00100000h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃□□□□ Hardware Reserved □□□□┃ B8000h ← gs
|
||
; 9FC00h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃■■■■■■■LOADER.BIN■■■■■■┃ somewhere in LOADER ← esp
|
||
; 90000h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃■■■■■■■KERNEL.BIN■■■■■■┃
|
||
; 80000h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃■■■■■■■■KERNEL■■■■■■■┃ 30400h ← KERNEL 入口 (KernelEntryPointPhyAddr)
|
||
; 30000h ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┋ ... ┋
|
||
; ┋ ┋
|
||
; 0h ┗━━━━━━━━━━━━━━━━━━┛ ← cs, ds, es, fs, ss
|
||
;
|
||
;
|
||
; GDT 以及相应的描述符是这样的:
|
||
;
|
||
; Descriptors Selectors
|
||
; ┏━━━━━━━━━━━━━━━━━━┓
|
||
; ┃ Dummy Descriptor ┃
|
||
; ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃ DESC_FLAT_C (0~4G) ┃ 8h = cs
|
||
; ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃ DESC_FLAT_RW (0~4G) ┃ 10h = ds, es, fs, ss
|
||
; ┣━━━━━━━━━━━━━━━━━━┫
|
||
; ┃ DESC_VIDEO ┃ 1Bh = gs
|
||
; ┗━━━━━━━━━━━━━━━━━━┛
|
||
;
|
||
; 注意! 在使用 C 代码的时候一定要保证 ds, es, ss 这几个段寄存器的值是一样的
|
||
; 因为编译器有可能编译出使用它们的代码, 而编译器默认它们是一样的. 比如串拷贝操作会用到 ds 和 es.
|
||
;
|
||
;
|
||
|
||
; 把 esp 从 LOADER 挪到 KERNEL
|
||
mov esp, StackTop ; 堆栈在 bss 段中
|
||
; task1, make sure we arrive here
|
||
pusha ; just feel free to use gpr
|
||
mov esi, 0
|
||
mov ebx, STR_kernel
|
||
.loop:
|
||
mov al, [ebx, esi * 1]
|
||
or ax, 0f00h
|
||
mov word [gs:esi * 2 + 80 * 1 * 2], ax ; gs <-> DESC_VIDEO, copy from write_terminal
|
||
add esi, 1
|
||
cmp esi, 6
|
||
jne .loop
|
||
popa
|
||
|
||
sgdt [gdt_ptr] ; cstart() 中将会用到 gdt_ptr
|
||
call cstart ; 在此函数中改变了gdt_ptr,让它指向新的GDT
|
||
lgdt [gdt_ptr] ; 使用新的GDT
|
||
|
||
|
||
jmp SELECTOR_KERNEL_CS:csinit
|
||
csinit: ; “这个跳转指令强制使用刚刚初始化的结构”——<<OS:D&I 2nd>> P90.
|
||
|
||
push 0
|
||
popfd ; Pop top of stack into EFLAGS
|
||
|
||
hlt
|
||
|
||
STR_kernel: db 'kernel' |