完善引导程序——未启动分页机制的保护模式3

第二遍写。。刚写完结果电脑重启了。。只好大概重写下要点。。
1.[BITS 32] 明确告诉编译器接下来的段是32位的段
2.用bocsh虚拟机调试操作系统
将run.bat中的..\bochs -q -f bochsrc.bxrc改为..\bochsdbg -q -f bochsrc.bxrc
bocsh常用命令:

3.保护模式下写hello shadow程序
(1)问:如何修改gdt使保护模式下的数据段描述符和代码段描述符的段基址分别与data_32和code_32对应?
答:观察描述符的结构可知,第2、3、4、7位表示段基址(从0开始计数)。修改这几位即可。
相关代码:

			xor eax,eax
			add eax,data_32
			mov word [gdt_data+2],ax
			shr eax,16
			mov byte [gdt_data+4],al
			mov byte [gdt_data+7],ah

(2)问:由实模式跳转到保护模式的代码段时为什么加上dword?(jmp dword gdt_code_addr:0)
答:因为该段是32位的段,偏移应是32位,dword告诉编译器编译时,0为32位。
下面是修改后的程序:

[BITS 16]
org 07c00h
jmp main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gdt表
gdt_table_start:
	gdt_null:
		dd 0h
		dd 0h
	gdt_data_addr equ $-gdt_table_start
	gdt_data:
		dw 07ffh
		dw 0h
		db 0h
		db 10010010b
		db 11000000b
		db 0
	gdt_video_addr equ $-gdt_table_start
	gdt_video:
		dw 0ffh
		dw 8000h
		db 0bh
		db 92h
		db 0c0h
		db 0
	gdt_code_addr	equ	$-gdt_table_start
	gdt_code:
		dw 07ffh
		dw 1h
		db 80h
		db 10011010b
		db 11000000b
		db 0
gdt_table_end:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	gdtr_addr:
		dw gdt_table_end-gdt_table_start-1;
		dd gdt_table_start
	
main:								;从main开始执行代码	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化数据段描述符的基地址
	xor eax,eax
	add eax,data_32
	mov word [gdt_data+2],ax
	shr eax,16
	mov byte [gdt_data+4],al
	mov byte [gdt_data+7],ah
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化代码段描述符的基地址
	xor eax,eax
	add eax,code_32
	mov word [gdt_code+2],ax
	shr eax,16
	mov byte [gdt_code+4],al
	mov byte [gdt_code+7],ah
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	lgdt	[gdtr_addr]				;将gdt的基地址和长度送入gdtr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	enable_a20:						;开启A20地址线
		in al,92h
		or al,00000010b
		out 92h,al
	cli								;废弃实模式中断向量表
	
	mov eax,cr0						;修改cr0寄存器的第0位
	or eax,1
	mov cr0,eax
	
	jmp dword gdt_code_addr:0				;真正由实模式跳转到保护模式的代码段,super jump,jump!!。。好耳熟,好像是道acm题的名字。。?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	[BITS 32]
	data_32:
			db 'hello shadow'
	code_32:
			mov ax,gdt_data_addr
			mov ds,ax
			mov ax,gdt_video_addr
			mov gs,ax
			mov cx,12
			mov edi,(80*10+12)*2
			mov bx,0
			mov ah,0ch
		s:	mov al,[ds:bx]
			mov [gs:edi],al
			mov [gs:edi+1],ah
			inc bx
			add edi,2
			loop s
			jmp $
	times 510-($-$$) db 0
	dw 55aah

这样一个简陋的bootloader基本完成了。。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>