操作系統實現----中斷調用

在上一篇的基礎之上,實現加載中斷idt,並調用中斷:

boot.s用來加載kernel

%define LOAD_KERNEL_TO 0x1000 ;加載到0x1000:0000處執行
%define KERNEL_LEN 20
;內核佔據多少個扇區 20*512

org 0x7c00


mov ax,cs
mov ds,ax
mov es,ax

;display"Loading kernel..."

mov ax,msg
mov bp,ax
mov cx,msgLen
mov ax,0x1301
mov bx,0x000c
mov dl,0
int 10h


load:
mov dh,0  ;磁頭號
mov dl,0x00  ;驅動器號
mov ch,0  ;磁道號 
mov cl,2  ;起始扇區號
mov ax,LOAD_KERNEL_TO
mov es,ax  ;es:bx -> read data to 
xor bx,bx  ;
mov ah,02h  ;param
mov al,KERNEL_LEN
;how many blocks to read
int 13h

system: 
jmp LOAD_KERNEL_TO:0x00

msg:
db "Loading kernel...."
msgLen equ ($ - msg)


times 510-($-$$) db 0

dw 0xaa55


kernel.s如下:


	mov ax,cs
	mov ds,ax
	mov es,ax
	mov ss,ax

	mov ax,msg
	mov bp,ax
	mov ax,0x1301
	mov	bx,0x000c
	mov cx,msgLen
	mov dx,0x0b00
	int 10h
	jmp start

msg:
	db "kernel is started!"
msgLen equ $ - msg
	
	;gdt
;as編譯器的寫法
;			.quad 0x0000000000000000
;gdt_cs:	.quad 0x00cf9a000000ffff	;cs
;gdt_ds:	.quad 0x00c092000000ffff	;ds
;gdt_gs:	.quad 0x00c0920b8000ffff	;gs

gdt:	db 0,0,0,0,0,0,0,0
gdt_cs:	db 0xff,0xff,0,0,0,0x9a,0xcf,0
gdt_ds:	db 0xff,0xff,0,0,0,0x92,0xcf,0
gdt_gs:	db 0xff,0xff,0,0x80,0x0b,0x92,0xc0,0

gdtLen 	equ $-gdt
gdtPtr:	dw gdtLen - 1
		dd 0

selector_cs equ gdt_cs - gdt
selector_ds equ gdt_ds - gdt
selector_gs equ gdt_gs - gdt
	
	;idt
idt:
;256 selector
%rep 256
	dw	intHandler - label_cs	;offset
	dw	selector_cs			;selector
	dw	0x8e00				;property
	dw 	0					;offset
	
%endrep

idtLen equ $ - idt
idtPtr		dw idtLen - 1
			dd 0

start:
	mov ax,cs
	mov ds,ax
	mov es,ax
	mov ss,ax

	;initial cs descriptor	
	;offset
	xor eax,eax
	mov ax,cs
	shl eax,4
	add eax,label_cs
	mov word [gdt_cs + 2],ax
	shr eax,16
	mov byte [gdt_cs + 4],al
	mov byte [gdt_cs + 7],ah

	;起初的時候並沒有這段代碼
	;即,cs段限長爲0xfffff
	;在bochs中調試的時候,運行到後面訪問數據段[0]號內存的時候
	;出現“00013868788e[CPU0 ] write_virtual_checks(): no write access to seg Next at t=13868789”
	;的錯誤,但是使用qemu運行好像沒有什麼問題,加上如下初始化段限長的代碼之後,bochs調試沒有這樣的錯誤了
	;《linux內核完全剖析》一文中,cs段和ds段直接設置相同的起始地址0,段限長爲0x07ff
	;length
	mov eax,label_cs_end - label_cs + 0xff
	mov word [gdt_cs],ax
	shr eax,16
	or al,11110000b
	and byte [gdt_cs + 6],al
	
	

	;initial ds descriptor
	xor eax,eax
	mov ax,cs
	shl eax,4
	add eax,label_ds
	mov word [gdt_ds + 2],ax
	shr eax,16
	mov byte [gdt_ds + 4],al
	mov byte [gdt_ds + 7],ah
	
	;initial gdtPtr
	xor eax,eax
	mov ax,cs
	shl eax,4
	add eax,gdt
	mov dword [gdtPtr + 2],eax

	;initial idtPtr
	xor eax,eax
	mov ax,cs
	shl eax,4
	add eax,idt
	mov dword [idtPtr + 2],eax

	;set the 0x80 interrupt
	mov eax,intHandler - label_cs
	mov word [idt+0x80*8],ax
	mov word [idt+0x80*8+2],selector_cs
	mov word [idt+0x80*8+4],0x8e00
	shr eax,16
	mov word [idt+0x80*8+6],ax
	

	;load gdtPtr
	lgdt [gdtPtr]

	;this is very important!!
	cli

	;load idtPtr
	lidt [idtPtr]
	
	;enable A20	
	in al,92h
	or al,00000010b
	out 92h,al
	
	;protect mode
	mov eax,cr0
	or eax,1
	mov cr0,eax
	
	jmp dword selector_cs:0


[bits 32]
[section .32]
label_cs:
	;initial ds
	mov ax,selector_ds
	mov ds,ax

	;inital ss,sp
	mov ax,selector_ds
	mov ss,ax
	mov esp,stackOff

	mov ah,0ch
	mov al,'P'
	call display_char
	mov ah,0ch
	mov al,'r'
	call display_char
	
	int 0x80
	jmp $

display_char:
	push gs
	push ebx
	mov ebx,selector_gs
	mov gs,ebx
			;	mov [gs:((80*cusor_i+cusor_j)*2)],ax
	xor ebx,ebx
	mov bx,[0]		;cursor_i is 0
	shl bx,1
	mov [gs:bx],ax
	shr bx,1
	inc bx
	cmp bx,2000
	je	.2
	jmp .1
.2	mov bx,0
.1	mov word [0],bx	;cursor_i is 0
	pop ebx
	pop gs

	ret


intHandler:
	mov ah,0ch
	mov al,'I'
	call display_char
	mov ah,0ch
	mov al,'n'
	call display_char
	mov ah,0ch
	mov al,'t'
	call display_char

	iretd	;very important

label_cs_end:

label_ds:
	cusor_i dw 0		;cusor_i [0,2000)

	;stack room
	times 1024 db 0
stack:
stackOff equ stack - label_ds	;stack offset

	times 512*20 - ($-$$) db 0




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章