📄 setup.s
字号:
%include "boot.inc"
extern detect_mem, dis_irq
global setup_entry
;这段代码载入内存0x10000, 把内核移到0x100000,
;切换到保护模式后可以跳入操作系统内核了
[bits 16]
setup_entry:
mov ax,cs ;0x10000 ;this code load at 0x10000
mov ds,ax
mov es,ax
mov di,msg
call stuprint
;call vesa_mode
call detect_mem
;======================
;above is Testing OK!!!!!!
;======================
;这段代码被Boot.s(长度0x800,即2048字节) 装入0x10000
cli
; load idt gdt
mov ax,cs ; right, forgot this at first. didn't work :-)
mov ds,ax
lidt [idt_48] ; load idt with 0,0
lgdt [gdt_48] ; load gdt with whatever appropriate
; 开启A20
call empty_8042
mov al,0xD1 ; command write
out 0x64,al
call empty_8042
mov al,0xDF ; A20 on
out 0x60,al
call empty_8042
; 禁止8259 响应任何中断
call dis_irq
; well, that certainly wasn't fun :-(. Hopefully it works, and we don't
; need no steenking BIOS anyway (except for the initial loading :-).
; The BIOS-routine wants lots of unnecessary data, and it's less
; "interesting" anyway. This is how REAL programmers do it.
;
; Well, now's the time to actually move into protected mode. To make
; things as simple as possible, we do no register set-up or anything,
; we let the gnu-compiled 32-bit programs do that. We just jump to
; absolute address 0x00000, in 32-bit protected mode.
mov ax,0x0001 ; protected mode (PE) bit
lmsw ax ; This is it!
jmp clean
clean:
BIT32
mov ax,0x10
mov ds,ax ;原来竟然没有初始化
mov es,ax
mov ss,ax
mov esp,0x800000 ;栈顶 0x200000 (8M)
mov eax,0
;move os.bin to 0x100000
mov esi,0x010800 ;source offset
mov edi,0x100000 ;dest offset
mov ecx,0x60000 ;count, byte 384k
move:
mov ax, word [dword ds:esi]
mov word [dword ds:edi],ax
dec ecx
cmp ecx,0
je endmove
inc esi
inc edi
jmp move ;晕倒,没写这一句,怎么他妈的移动!
endmove:
;跳到内核
jmp dword 8:0x100000 ; jmp offset 100000 of segment 8 (cs)
;**********************子程序**********************************************
; This routine checks that the keyboard command queue is empty
; No timeout is used - if this hangs there is something wrong with
; the machine, and we probably couldn't proceed anyway.
empty_8042:
dw 0x00eb,0x00eb
in al,0x64 ; 8042 status port
test al,2 ; is input buffer full?
jnz empty_8042 ; yes - loop
ret
;-------------------临时的32位环境以便启动内核-------------------------------
align 4
gdt:
dw 0,0,0,0 ; dummy
;kernel code
dw 0xFFFF ; 4G - limit=2047 (2048*4096=8Mb)
dw 0x0000 ; base address=0
db 0x00 ; base address=0
db 0x9A ; code read//exec || 1 00(dpl)//1(code/data) 1010
db 0xCF ; 1100,粒度4k,32bit默认操作数,1111(4G),
db 0x00 ; base
;kernel data
dw 0xFFFF ; 4G - limit=2047 (2048*4096=8Mb)
dw 0x0000 ; base address=0
db 0x00 ; base address=0
db 0x92 ; data read/write || 1 00(dpl)/1(code/data) 1010
db 0xCF ; 1100,粒度4k,32bit默认操作数,1111(4G),
db 0x00 ; base
idt_48:
dw 0 ; idt limit=0
dw 0,0 ; idt base=0L
gdt_48:
dw 0x800 ; gdt limit=2048, 256 GDT entries
dw gdt,0x1 ; 注意 gdt base = 0X1xxxx
; 因为 setup 装入0X10000
msg :
db "Setup.s : Switch to PE,Move os at 1M, And Jmp to os ..."
db 13,10,0
;****************************************************************************
;times (2048-($-$$)) db 0 ;为setup预留4 个扇区
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -