📄 setup.s
字号:
;这段代码载入内存0x10000, 把内核移到0x20000,
;切换到保护模式后可以跳入操作系统内核了
mov ax,cs ;0x10000 ;this code load at 0x10000
mov ds,ax
mov es,ax
mov cx,12
mov bx,0x0007 ; page 0, attribute 7 (normal)
mov bp,msg
mov ax,0x1301 ; write string, move cursor
int 0x10
;======================
;above is Test OK!!!!!!
;======================
;这段代码被Boot.s(长度0x800,即2048字节) 装入0x10000
;
;re move system at 0x20000
cli
mov ax,0x2000 ;dest seg 和编译选项-Ttext 一致
mov es,ax
mov si,0x800 ;source offset 和setup大小一致
mov di,0x0000 ;dest offset
mov cx,0x1500 ;count 临时值
rep movsw
end_move:
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
; that was painless, now we enable 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
; well, that went ok, I hope. Now we have to reprogram the interrupts :-(
; we put them right after the intel-reserved hardware interrupts, at
; int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
; messed this up with the original PC, and they haven't been able to
; rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
; which is used for the internal hardware interrupts as well. We just
; have to reprogram the 8259's, and it isn't fun.
mov al,0x11 ; initialization sequence
out 0x20,al ; send it to 8259A-1
dw 0x00eb,0x00eb ; jmp $+2, jmp $+2
out 0xA0,al ; and to 8259A-2
dw 0x00eb,0x00eb
mov al,0x20 ; start of hardware int's (0x20)
out 0x21,al
dw 0x00eb,0x00eb
mov al,0x28 ; start of hardware int's 2 (0x28)
out 0xA1,al
dw 0x00eb,0x00eb
mov al,0x04 ; 8259-1 is master
out 0x21,al
dw 0x00eb,0x00eb
mov al,0x02 ; 8259-2 is slave
out 0xA1,al
dw 0x00eb,0x00eb
mov al,0x01 ; 8086 mode for both
out 0x21,al
dw 0x00eb,0x00eb
out 0xA1,al
dw 0x00eb,0x00eb
mov al,0xFF ; mask off all interrupts for now
out 0x21,al
dw 0x00eb,0x00eb
out 0xA1,al
; 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:
mov eax,0x10
mov ds,ax
mov es,ax
mov ss,ax
mov esp,0x1000
mov ax,0
jmp dword 8:0x20000 ; jmp offset 0 of segment 8 (cs)
; 和 os 装入位置一致
; 这里是 32 位的代码
;-------------------临时的32位环境以便启动内核-------------------------------
align 4
gdt:
dw 0,0,0,0 ; dummy
dw 0x07FF ; 8Mb - limit=2047 (2048*4096=8Mb)
dw 0x0000 ; base address=0
dw 0x9A00 ; code read/exec
dw 0x00C0 ; granularity=4096, 386
dw 0x07FF ; 8Mb - limit=2047 (2048*4096=8Mb)
dw 0x0000 ; base address=0
dw 0x9200 ; data read/write
dw 0x00C0 ; granularity=4096, 386
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 13,10
db "Setup ......."
db 13,10,13,10
;**********************子程序**********************************************
; 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
;****************************************************************************
times (2048-($-$$)) db 0 ;为setup预留1 个扇区
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -