實模式到保護模式再到實模式,完成時的分享!

; boot.asm

bits 16

start16:
	mov ax, 0x7c0 ;實模式下,數據段、堆棧段基地址都爲0x7c00
	mov ds, ax
	mov ss, ax
	mov sp, 0x0

	cli  ;應關閉中斷

	; 讀取硬盤第二個扇區到內存0x7e00處, 是緊挨着引導扇區內存處的一個扇區	
	mov dx, 0x1f2
	mov al, 2 ;一下加載了兩個扇區,因此,下面的向緩衝區中寫入數據也應該是,一個扇區的兩倍
	out dx, al

	mov dx, 0x1f3
	mov al, 1 ;第二個扇區,邏輯扇區從0開始計數。這也是容易出問題的地方
	out dx, al
	
	mov dx, 0x1f4
	mov al, 0
	out dx, al
	
	mov dx, 0x1f5
	mov al, 0
	out dx, al
	
	mov dx, 0x1f6
	mov al, 0xe0 ;第一塊硬盤,LBA模式
	out dx, al
	
	mov dx, 0x1f7
	mov al, 0x20 ;讀命令
	out dx, al
	
	mov dx, 0x1f7 
.1:
	in al, dx
	and al, 0x88
	cmp al, 0x08 ;測試是否完成操作
	jnz .1
	
	mov bx, 0x200 ; 0x7c00 + 0x200,512 bytes,即0x7e00
	mov dx, 0x1f0
	mov cx, 2 * 256
.2:
	in ax, dx
	mov [bx], ax
	inc bx
	inc bx
	loop .2
	
	lgdt [gdtr]
	
	;open A20 address line
	in al, 0x92
	or al, 0x2
	out 0x92, al
	
	;set CR0 protected mode bit
	mov eax, cr0
	or al, 0x1
	mov cr0, eax
	
	jmp dword 1 * 8 : 0 ;更新cs,eip

gdtr:
	dw gdt_end - gdt_start - 1; global descriptor table size -- xxx bytes
	dd gdt_start + 0x7c00; phy Address
	
gdt_start:
	dq 0x0000000000000000 ; 0 * 8
	dq 0x00c09a007e00ffff ; 1 * 8 segment base address 0x7c00 + 0x200
	dq 0x00c092007e00ffff ; 2 * 8
	dq 0x00c0920b8000ffff ; 3 * 8 video memory address
	dq 0x00c092100000ffff ; 4 * 8 other data segment
	dq 0x000092000000ffff ; 5 * 8 other data segment
	dq 0x000098000000ffff ; 6 * 8 other data segment	
gdt_end:
	
times 512 - 2 - ($ - $$) db 0
dw 0xaa55 ; == db 0x55, 0xaa
;loader.asm

bits 32

start:
	mov ax, 2 * 8
	mov ds, ax
	
	mov ax, 3 * 8
	mov es, ax
	
	mov ebx, 3 * 160
	mov byte [es: ebx], 'l'
	inc ebx
	mov byte [es: ebx], 0xc
	inc ebx
	
	jmp 6 * 8 : 0x7e00 + start16 ;這裏《orange's一個操作系統的實現》說是應該切換到16位代碼段
							;但古老的清華書似乎沒有這麼說,但是還是這樣做了
							;決定明天按照清華老書裏直接切換到實模式,驗證一下,到底誰的對。
	jmp $
	
align 32
bits 16

start16:
	mov ax, 5 * 8
	mov ds, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax

	
	;位0清零後,切換到實模式,緊接着就要刷新高速緩存,從而進入實模式
	mov eax, cr0
	and eax, 1111_1111_1111_1110b
	mov cr0, eax

	;這段顯示字符的程序一定要在保護模式位清零後,方可執行,否則宕機

	xor bx, bx
	mov ax, 0xb800
	mov es, ax
	mov byte [es: bx], 'a'
	inc bx
	mov byte [es: bx], 0xe
	inc bx
	
	;這裏使用db僞指令定義的跳轉到實模式的代碼段的指令,nasm應該怎麼表示,我不太知道
	;明天也要驗證一下這裏,看看nasm的jmp指令是否也生成同樣的機器碼。
	db 0xea
	dw 0x8000
	dw 0

 

; kernel.asm

bits 16

start16:
	mov ax, 0
	mov ds, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	mov sp, 0
	
	;應該關閉a20地址線
	in al, 0x92
	and al, 1111_1101b
	out 0x92, al

	mov bx, 160
	mov ax, 0xb800
	mov es, ax
	mov byte [es: bx], 'r'
	inc bx
	mov byte [es: bx], 0xa
	inc bx

	;一定要打開中斷,否則沒法用BIOS中斷讀軟盤引導扇區到0x7c00處。
	sti

	mov dx, 0
	mov cx, 1
	mov ax, 0x7c0
	mov es, ax
	mov bx, 0
	mov ax, 0x201
	int 0x13

	jmp 0x7c0 : 0 ;跳轉到軟盤的引導扇區,我們的系統是用硬盤引導扇區加載的。
;軟盤裏面預製的是menuetOS,一個純粹用彙編語言寫成的操作系統。這樣就完成王爽老師大作業中的一個小知識點。
	

 

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