操作系统实现----中断调用

在上一篇的基础之上,实现加载中断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




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