⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kinit.old

📁 raywill写的操作系统内核
💻 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 + -