📄 kinit.asm
字号:
;0x010:0x0003072 0010:00097953 0010:00097c98
[global kernel_entry]
[global _setvect]
[global _soft_int]
[extern _osmain]
[extern _common_interrupt]
%define LOAD_BASE 0x90000 ;phy_addr where we load our kernel to
[section .text]
kernel_entry:
start:
cli
lgdt [gdt_addr] ;
jmp gdt_code_addr:flush_gdt
flush_gdt:
mov ax,gdt_data_addr
mov ds,ax ;seg value is in the loader
fill_page_directory:
mov edi,_page_directory
mov ecx,0x1000
mov eax,0
push ds
pop es
fill_zero_page: ;fill all page directory entries as NULL
mov [edi],eax
add edi,4
dec ecx
cmp ecx,0
jnz fill_zero_page
fill_presented_page:
mov dword [_page_directory+(LOAD_BASE>>22)*4],_kernel_page_table+7 ;seccond param is compile time determined
mov eax,7
mov ebx,0
fill_page_table:
mov dword [_kernel_page_table+ebx*4], eax
add eax,0x1000
inc ebx
cmp ebx,0xfff
jnz fill_page_table
mov eax,_page_directory
mov cr3,eax
;Doing nothing here
; hlt
; nop
; nop
enable_paging:
mov eax,cr0
or eax,1<<31
mov cr0,eax
jmp gdt_code_addr:flush_page
;ret can also flush the pre-frech queue :)
flush_page:
reset_data_seg:
mov ax,gdt_data_addr ;data segment descriptor
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,0x90000
;install the irq handler
mov ecx,(idt_end - idt) >> 3 ; number of exception handlers
mov edi,idt
mov esi,isr0 ;first handler
do_idt:
mov eax,esi ; EAX=offset of entry point
mov [edi],ax ; set low 16 bits of gate offset
shr eax,16 ; get high 16 of the handler address
mov [edi + 6],ax ; set high 16 bits of gate offset
add edi,8 ; 8 bytes/interrupt gate
add esi,(isr1 - isr0) ; bytes/stub
loop do_idt
lidt [idt_addr] ;load null interrupt describe table
;Everything have done!Let's go!
;sti(we can do this in C,after everything initialized)
call _osmain
hang:
jmp hang
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;here is the gdt data for the kernel;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
gdt_null:
dd 0
dd 0
gdt_data_addr equ $-gdt
gdt_data:
dw 0xffff
dw 0
db 0
db 10010010b ;(7)seg exist,(6-5)privileg,(4)0:sys seg,1:data or code seg,(3-0)seg attr,2:data seg,read and write.
db 11001111b ;(7)limit len,0:1 byte,1:4K,(6)B bit,control stack,B=1,use esp,B=0,use sp,(5-4) reserved,(3-0)seg limit 19-16.
db 0
gdt_code_addr equ $-gdt
gdt_code:
dw 0xffff
dw 0
db 0
db 10011010b ;(7)seg exist,(6-5)privileg,(4)0:sys seg,1:data or code seg,(3-0)seg attr,10:code seg,execute and read.
db 11001111b
db 0
gdt_end:
gdt_addr:
dw gdt_end - gdt - 1 ;gdt total length,here it contains 3 item
dd gdt ;gdt start address
;set null interrupt
idt:
%rep 256
dw 0 ; offset 15:0
dw gdt_code_addr ; selector
db 0 ; (always 0 for interrupt gates)
db 8Eh ; present,ring 0,'386 interrupt gate
dw 0 ; offset 31:16
%endrep
idt_end:
idt_addr:
dw idt_end - idt - 1 ; IDT limit
dd idt ; linear adr of IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%macro PUSHB 1
db 6Ah
db %1
%endmacro
%macro INTR 1 ; (byte offset from start of stub)
isr%1:
push byte 0 ; ( 0) fake error code
PUSHB %1 ; ( 2) exception number
push gs ; ( 4) push segment registers
push fs ; ( 6)
push es ; ( 8)
push ds ; ( 9)
pusha ; (10) push GP registers
mov ax,gdt_data_addr ; (11) put known-good values...
mov ds,eax ; (15) ...in segment registers
mov es,eax ; (17)
mov fs,eax ; (19)
mov gs,eax ; (21)
mov eax,esp ; (23)
push eax ; (25) push pointer to regs_t
.1:
; setvect() changes the operand of the CALL instruction at run-time,
; so we need its location = 27 bytes from start of stub. We also want
; the CALL to use absolute addressing instead of EIP-relative, so:
; hlt
; nop
; nop
mov eax,_common_interrupt; (26)
call eax ; (31)
pop eax
popa ; pop GP registers
pop ds ; pop segment registers
pop es
pop fs
pop gs
nop
nop
add esp,8 ; drop exception number and error code
iret
%endmacro ; (38)
%macro INTR_EC 1
isr%1:
nop ; error code already pushed
nop ; nop+nop=same length as push byte
PUSHB %1 ; ( 2) exception number
push gs ; ( 4) push segment registers
push fs ; ( 6)
push es ; ( 8)
push ds ; ( 9)
pusha ; (10) push GP registers
mov ax,gdt_data_addr ; (11) put known-good values...
mov ds,eax ; (15) ...in segment registers
mov es,eax ; (17)
mov fs,eax ; (19)
mov gs,eax ; (21)
mov eax,esp ; (23)
push eax ; (25) push pointer to regs_t
.1:
; setvect() changes the operand of the CALL instruction at run-time,
; so we need its location = 27 bytes from start of stub. We also want
; the CALL to use absolute addressing instead of EIP-relative, so:
mov eax,_common_interrupt ; (26)
call eax ; (31)
pop eax
popa ; pop GP registers
pop ds ; pop segment registers
pop es
pop fs
pop gs
nop
nop
add esp,8 ; drop exception number and error code
iret
%endmacro ; (38)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt/exception stubs
; *** CAUTION: these must be consecutive, and must all be the same size.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INTR 0 ; zero divide (fault)
INTR 1 ; debug/single step
INTR 2 ; non-maskable interrupt (trap)
INTR 3 ; INT3 (trap)
INTR 4 ; INTO (trap)
INTR 5 ; BOUND (fault)
INTR 6 ; invalid opcode (fault)
INTR 7 ; coprocessor not available (fault)
INTR_EC 8 ; double fault (abort w/ error code)
INTR 9 ; coproc segment overrun (abort; 386/486SX only)
INTR_EC 0Ah ; bad TSS (fault w/ error code)
INTR_EC 0Bh ; segment not present (fault w/ error code)
INTR_EC 0Ch ; stack fault (fault w/ error code)
INTR_EC 0Dh ; GPF (fault w/ error code)
INTR_EC 0Eh ; page fault
INTR 0Fh ; reserved
INTR 10h ; FP exception/coprocessor error (trap)
INTR 11h ; alignment check (trap; 486+ only)
INTR 12h ; machine check (Pentium+ only)
INTR 13h
INTR 14h
INTR 15h
INTR 16h
INTR 17h
INTR 18h
INTR 19h
INTR 1Ah
INTR 1Bh
INTR 1Ch
INTR 1Dh
INTR 1Eh
INTR 1Fh
; isr20 through isr2F are hardware interrupts. The 8259 programmable
; interrupt controller (PIC) chips must be reprogrammed to make these work.
INTR 20h ; IRQ 0/timer interrupt
INTR 21h ; IRQ 1/keyboard interrupt
INTR 22h
INTR 23h
INTR 24h
INTR 25h
INTR 26h ; IRQ 6/floppy interrupt
INTR 27h
INTR 28h ; IRQ 8/real-time clock interrupt
INTR 29h
INTR 2Ah
INTR 2Bh
INTR 2Ch
INTR 2Dh ; IRQ 13/math coprocessor interrupt
INTR 2Eh ; IRQ 14/primary ATA ("IDE") drive interrupt
INTR 2Fh ; IRQ 15/secondary ATA drive interrupt
; syscall software interrupt
INTR 30h
; the other 207 vectors are undefined
%assign i 31h
%rep (0FFh - 30h)
INTR i
%assign i (i + 1)
%endrep
_soft_int:
push ebp
mov ebp,esp
push eax
mov eax,[ebp+8]
;int ax
int 0x20
pop eax
pop ebp
ret
_setvect:
push ebp
mov ebp,esp
push esi
push ebx
mov esi,[ebp + 8]
; store accessdbyte in IDT[i]
mov eax,[esi + 0]
xor ebx,ebx
mov bl,[ebp + 12]
shl ebx,3 ;ebx+5+idt=priv addr
mov [idt + ebx + 5],al ;in al,8Eh=Present Ring0 386mode
; store handler address in stub
mov eax,isr1
sub eax,isr0 ; assume stub size < 256 bytes
mul byte [ebp + 12] ;which intr? 0x20 like so
mov ebx,eax ;because the mul source is byte(al),the result is (AX)
add ebx,isr0 ;ebx=Delta_dis*No+Start
mov eax,[esi + 4] ;[esi+4]=eip
mov [ebx + (isr0.1 - isr0 + 1)],eax
pop ebx
pop esi
pop ebp
ret
align 0x1000
GLOBAL _page_directory
_page_directory:
times 0x1000 db 0
align 0x1000
GLOBAL _kernel_page_table
_kernel_page_table:
times 0x1000 db 0
[section .data]
[section .bss]
knrl_stack:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -