📄 kinit.old
字号:
;0x010:0x0003072
[global kernel_entry]
[global _setvect]
[global _soft_int]
;[global _enable_paging]
[extern _osmain]
[extern _common_interrupt]
;[extern pg0]
;[extern pg1]
%define _PAGE_OFFSET 0xC0000000 ;3G
%define LOAD_BASE 0x90000 ;phy_addr where we load our kernel to
[section .text]
kernel_entry:
jmp start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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 0x00
db 0x00
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 0xC0 ;(=1100 0000)
gdt_code_addr equ $-gdt
gdt_code:
dw 0xffff
dw 0x00
db 0x00
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 0xC0
gdt_end:
gdt_addr:
dw gdt_end - gdt - 1 ;gdt total length,here it contains 3 item
dd gdt+LOAD_BASE ;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
align 0x1000
GLOBAL _page_directory
_page_directory:
times 0x1000 db 0
align 0x1000
GLOBAL _kernel_page_table
_kernel_page_table:
times 0x1000 db 0
start:
cli
;setup IDT
; lgdt [gdt_addr] ;load GDT again,though we have load it in loader,let's do it again.
;*******************************************************************************
;we just stopped here as I am going to sleep now
;I still need to change the GDT in this file.Make the base address at 0xC0000000
;*******************************************************************************
enable_paging:
;Attention ! We are still using the bootloader's GDT!
;|22-31(Directory)|21-12(Table)|11-0(Offset)
;mov eax,_PAGE_OFFSET>>22
mov dword [_page_directory+(_PAGE_OFFSET>>22)*4],_kernel_page_table+LOAD_BASE+7 ;seccond param is compile time determined
;Fill the map
;Error Correction:
;forget to add -_PAGE_OFFSET for the following code first :(
;as we use Ttext=0 ,so _kernel_page_table + 4*X + LOAD_BASE is the real address
;little explaination:
; mov dword [_kernel_page_table+0+LOAD_BASE], 0x90000+7
; file the first entry in PT with the value of 0x90000,which we want to map to _PAGE_OFFSET
; For example ,linear address 0xC0002345
; We get the PT index by the value of 0xC0000000>>20(=3072) ,
; 0xC0000000>>12&&0x3FF indecates the index in PT ,
; we can find the PAGE with the information in PT
; DATA in PT is a common pointer.
; However ,the pointer is still a little "special"
; Pointer structure : |31-12(base addr)|11-0(melicious bits)|
; Then what is a PAGE? I don't think PAGE is a data structure,
; but a useful virtural concept
;the follow coade is filling the PT
mov dword [_kernel_page_table+0+0], 0x90000+7
mov dword [_kernel_page_table+4+0], 0x91000+7
;mov dword [_kernel_page_table+8+0], 0x92000+7
mov dword [_kernel_page_table+12+0],0x93000+7
mov dword [_kernel_page_table+16+0],0x94000+7
mov dword [_kernel_page_table+20+0],0x95000+7
mov dword [_kernel_page_table+24+0],0x96000+7
mov dword [_kernel_page_table+28+0],0x97000+7
mov dword [_kernel_page_table+32+0],0x98000+7
mov eax,_page_directory + LOAD_BASE
mov cr3,eax
;until here,we got:
;cr0:0x00000011, cr1:0x00000000, cr2:0x00000000
;cr3:0x0000e080, cr4:0x00000000
;Doing nothing here
reset_gdt:
lgdt [gdt_addr] ;load GDT.Now will use kernel gdt.
;GDT has set correctly ,now let's enable PAGING :-)
jmp gdt_code_addr:reset_data_seg
reset_data_seg:
mov eax,cr0
or eax,1<<31
mov cr0,eax
jmp flush_page
;ret can also flush the pre-frech queue :)
flush_page:
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,0x1000
;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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%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:
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
[section .data]
[section .bss]
knrl_stack:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -