- 论坛徽章:
- 0
|
6、可运行的最小规模的 OS
在这个版本里,修正了一些bug,加入了 TSS,和较完整的 idt
看看 kernel.asm 的源码:
--------------------------------------------------------------------------------------------
%include "x64os.inc"
org 0x6000
jmp code16_entry
gdt32:
null dq 0
; cs: limit = fffff*10000+ffff (4g)
; base = 0x00000000
; DPL=0,G=1,D=1,C=0,P=1,r=1
cs0 dw 0xffff ; limit
dw 0 ; base 15 ~ 0
db 0 ; base 23 ~ 16
db 0x9a ; 1 00 11010 : p=1,c=0,r=1
db 0xcf ; G=1,D=1,base=00
db 0
cs0_sel equ 0x08
; cs1: limit = 7ffff*10000+ffff (2g)
; base = 0x80000000
; DPL = 1
; G = 1, D = 1,C = 0
cs1 dw 0xffff
dw 0
db 0
db 0xba
db 0xc7
db 0x80
cs1_sel equ cs0_sel + 8
; cs2: limit = 3ffff*10000+ffff (1g)
; base = 0xd0000000
; DPL = 2
; G=1,D=1,C=0,P=1,R=1
cs2 dw 0xffff
dw 0
db 0
db 0xda
db 0xc3
db 0xd0
cs2_sel equ cs1_sel + 8
; cs3: limit = 7ffff*10000+ffff (2g)
; base = 0x00000000
; DPL = 3
; G=1,D=1,C=0,P=1,R=1
cs3 dw 0xffff
dw 0
db 0
db 0xfa
db 0xc7
db 0
cs3_sel equ cs2_sel + 8
; ds0: limit = fffff*1000+ffff (4g)
; base = 0x00000000
; DPL = 0
; G=1,D/B=1,P=1,E=0,W=1,A=1
ds0 dw 0xffff
dw 0
db 0
db 0x92
db 0xcf
db 0
ds0_sel equ cs3_sel + 8
; ds1: limit = 7ffff*10000+ffff (2g)
; base = 0x80000000
; DPL = 1
; G=1,D/B=1,P=1,E=0,W=1,A=1
ds1 dw 0xffff
dw 0
db 0
db 0xb2
db 0xc7
db 0x80
ds1_sel equ ds0_sel + 8
; ds2: limit = 3ffff*10000+ffff (1g)
; base = 0xd0000000
; DPL=2
; G=1,D/B=1,P=1,E=0,W=1,A=1
ds2 dw 0xffff
dw 0
db 0
db 0xd2
db 0xc3
db 0xd0
ds2_sel equ ds1_sel + 8
; ds3: limit = 7ffff*10000+ffff(2g)
; base = 0x00000000
; DPL=3
; G=1,D/B=1,P=1,E=0,W=1,A=1
ds3 dw 0xffff
dw 0
db 0
db 0xf2
db 0xc7
db 0
ds3_sel equ ds2_sel + 8
; kernel_cs: limit = fffff*1000+ffff (4g)
; base = 0x00000000
; DPL = 0
; G=1,D=1,C=0,R=1,P=1,A=1
kernel_cs dw 0xffff
dw 0
db 0
db 0x9a
db 0xcf
db 0
kernel_cs_sel equ ds3_sel + 8
; user_cs: limit = fffff*1000+ffff (4g)
; base = 0x00000000
; DPL = 3
; G=1,D=1,C=0,R=1,P=1
user_cs dw 0xffff
dw 0
db 0
db 0xfa
db 0xcf
db 0
user_cs_sel equ kernel_cs_sel + 8
ss0 dw 0xffff
dw 0
db 0
db 0x92
db 0xcf
db 0
ss0_sel equ user_cs_sel + 8
; kernel_ds: limit = fffff*1000+ffff (4g)
; base = 0x00000000
; DPL = 0
; G=1,D/B=1,P=1,E=0,W=1,A=1
kernel_ds dw 0xffff
dw 0
db 0
db 0x92
db 0xcf
db 0
kernel_ds_sel equ ss0_sel + 8
; user_ds: limit = fffff*10000+ffff(4g)
; base = 0x00000000
; DPL=3
; G=1,D/B=1,P=1,E=0,W=1,A=1
user_ds dw 0xffff
dw 0
db 0
db 0xf2
db 0xcf
db 0
user_ds_sel equ kernel_ds_sel + 8
tss_selector:
tss1 dw 0x67 ; limit
dw tss32 ; base15-0
db 0 ; base23-16
db 0xe9 ; DPL=3,type=32-bit available tss
db 0 ; G=0
db 0 ; base31-24
tss1_sel equ user_ds_sel + 8
ldt_selector:
ldt1 dw 0 ; limit
dw 0 ; base15-0
db 0 ; base23-16
db 0x82 ; DPL=0,type=ldt
db 0x80 ; G=1
db 0 ; base31-24
gdt32_end:
ldt1_sel equ tss1_sel + 8
;-----------------------------------------------------------
idt32:
_DE dw exception_DE ; offset15-0
dw kernel_cs_sel ; selector
db 0 ; resever
db 0x8e ; DPL=0,type=interrup-gate
dw 0 ; offset31-16
_DB dq 0
_NMI dq 0
_BP dq 0
_OF dq 0
_BR dq 0
_UD dq 0
_NM dq 0
_DF dw exception_DF
dw kernel_cs_sel
db 0
db 0x8e
dw 0
dq 0 ; reserved
_TS dq 0
_NP dq 0
_SS dq 0
_GP dw exception_GP
dw kernel_cs_sel
db 0
db 0x8e
dw 0
dq 0 ; reserved
_MF dq 0
_AC dq 0
_MC dq 0
_XF dq 0
times 10 dq 0 ; reserved
_SX dq 0
idt32_end:
;-----------------------------------------------------------
tss32:
dd 0 ; link=0
dd 0x3fff0000 ; esp0
dd ds0_sel ; ss0 = 0x0028, ds0-selector
dd 0x2fff0000 ; esp1
dd ds1_sel ; ss1
dd 0x1fff000 ; esp2
dd ds2_sel ; ss2
dd 0 ; cr3
dd 0 ; eip
dd 0 ; eflags
dd 0 ; eax
dd 0 ; ecx
dd 0 ; edx
dd 0 ; ebx
dd 0 ; esp
dd 0 ; ebp
dd 0 ; esi
dd 0 ; edi
dd 0x00000058 ; es: kernel_ds
dd 0x00000048 ; cs: kernel_cs
dd 0x00000058 ; ss: kernel_ds
dd 0x00000058 ; ds: kernel_ds
dd 0 ; fs
dd 0 ; gs
dd 0 ; ldt-selector
db 0 ; T=0
db tss32_end-tss32
tss32_end:
gdt:
gdt_limit dw gdt32_end-gdt32
gdt_base dd gdt32
idt:
idt_limit dw idt32_end-idt32
idt_base dd idt32
cursor dd 0xb8000
code16_entry:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x6000
cli
lidt [idt]
lgdt [gdt] ; load from ds:[gdt] into gdtr
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword kernel_cs_sel:code32_entry
bits 32
code32_entry:
mov ax,ds0_sel
mov ds,ax
mov es,ax
mov ax,ss0_sel
mov ss,ax
mov esp, 0x10000
sti
lea esi,[message]
push esi
push dword 0
push dword 0
call display_message
cld
mov edi,0x10000
lea esi,[next]
mov ecx, kernel_end-next
rep movsb
push dword 0x10000
ret
; 0x10000:
next:
; call init_tss
mov ax, tss1_sel
ltr ax
mov eax,0
div al
mov ax, ds3_sel|0x03
mov ds, ax
mov es, ax
push (ds3_sel) | 0x03 ; stack 3
push 0x1fff0000 ; stack 3
push (user_cs_sel)|0x03
push os_main
retf
done:
jmp $
message db "... protected mode... ...",0
exception0 db " exception: divide by zero...",0
os_main:
jmp os_next
os_msg db 'Shell > ',0
os_next:
call clear
push os_msg
push 0
push 0
call display_message
jmp $
init_gdt:
ret
init_idt:
lea edx, [exception_DE]
mov word [_DE+0], dx ; offset15-0
mov word [_DE+2], kernel_cs_sel ; selector: kernel_cs
shr edx,16
mov word [_DE+6], dx ; offset31-16
lea edx, [exception_GP]
mov word [_GP+0], dx ; offset15-0
mov word [_GP+2], kernel_cs_sel ; selector: kernel_cs
shr edx,16
mov word [_GP+6], dx ; offset31-16
ret
init_tss:
lea edx, [tss32]
mov word [tss1+0], 0x68 ; limit
mov word [tss1+2], dx
shr edx, 16
mov byte [tss1+4], dl
mov byte [tss1+7], dh
mov ax, tss1_sel ; tss1 selector
ltr ax
ret
;------------------ exception handler --------------------------
exception_DE:
push ebp
mov ebp,esp
mov edi, [ebp+4] ; eip
mov esi, [ebp+8] ; cs
jmp DE_next
DE_msg1 db 'exception instruction at 0x',0
DE_msg2 db 'continue at 0x',0
DE_next:
push DE_msg1
push 1
push 40
call display_message
push edi
push eax
push 40
call print_hex
mov ax,1
mov esp, ebp
pop ebp
iret
;---------- #GP exception handler ----------------
exception_GP:
iret
;----------- #TS exception handler ---------------
exception_TS:
iret
;------------ #DF exception handler ---------------
exception_DF:
iret
;---------------------- kernel routune --------------------
clear:
mov edi, 0xb8000
mov ecx, 40*80
xor eax,eax
rep stosw
ret
; print_hex(row, column, value)
print_hex:
push ebp
mov ebp,esp
push edi
push esi
push ebx
mov edi, [ebp+8] ; row
mov esi, [ebp+0xc] ; column
mov ebx, [ebp+0x10] ; value
mov edx, ebx
imul edi, 80 ; row * 80
add edi, 0xb8000
mov ecx, 32
jmp pl
hex_table db '0123456789ABCDEF',0
pl:
mov ebx, edx
sub ecx,4
shr ebx, cl
and ebx,0x0f
mov al, [ebx+hex_table]
mov ah,0x0f
mov word [edi+esi*2], ax
inc esi
cmp ecx, 0
jz pd
jmp pl
pd:
mov eax, esi
pop ebx
pop esi
pop edi
mov esp,ebp
pop ebp
ret 12
; printf()
printf:
ret
; display_message(row, column, message)
display_message:
push ebp
mov ebp,esp
push edi
push ecx
push esi
mov edi,[ebp+0x8] ; row
mov ecx, [ebp+0x0c] ; column
mov esi, [ebp+0x10] ; message
imul edi,80
add edi,0xb8000
xor eax,eax
mov ah,0x0f
l1:
lodsb
test al,al
jz l2
mov word [edi + ecx*2], ax
inc ecx
jmp l1
l2:
mov eax, ecx
pop esi
pop ecx
pop edi
mov esp, ebp
pop ebp
ret 0x0c
kernel_end: |
|