<body>

kenshou

天空没有飞过的痕迹,但我已经努力飞过……

« Home | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next »

bootsystem之hello(3)

哇哈哈,本人的第一个保护模式程序诞生了,从实模式转换到保护模式经历了很多曲折的东西,gdt的地址一直加载不对,经过对bochs的调试和参考大量文献的基础上终于发现在linux0.11的setup中加载gdt的时候是把gdt的地址加上512才对了,修改后我的也就成功运行了第一在保护模式下打印“hello keroro!”的程序了。不过现在保护模式下的测试打印程序还有点问题,呵呵,明天继续修改。
总结下明天需要对今天的一些东西进行学习:1.机器高字节和nasm编译出来的字节的关系;2:gdtr,gdt等东西的定义。

先把今天的代码成列出来,明天再记录今天解决问题所使用的一些方法了。

----
boot.asm程序就使用之前的,修改了setup.asm,增加了system.asm这个实模式下的程序文件.

setup.asm文件

;setup.asm文件
mov ax,cs ;将ds,es,ss都设置成移动后的代码所在段处(因为下面的打印程序需要es)
mov ds,ax
mov es,ax
;mov ss,ax
mov sp,0xffff

jmp Main

SETUPSEG equ 0x9000;setup程序的起始地址
SETUPLEN equ 2048
SETUPOFFSET equ 0x200;

SYSTEMSEG equ 0x0000
SYSTEMOFFSET equ 0x0000
SYSTEMSIZE equ 1024

;定义GDT表描述符
gdt_addr:
dw 0x800 ;gdt表的大小
dw gdt+512 ;gdt表的位置/*****最刚开始我没有加512导致一直gdt没有加载对
dw 0x0009
gdt:
gdt_null:
dw 0x0000
dw 0x0000
dw 0x0000
dw 0x0000
gdt_system_code:
dw 0x07ff
dw 0x0000
dw 0x9a00
dw 0x00c0
gdt_system_data:
dw 0x07ff
dw 0x0000
dw 0x9200
dw 0x00c0

;等待键盘控制器空闲的子程序
Empty_8042
in al,0x64
test al,0x2
jnz Empty_8042
ret

;清屏子程序
ClearSrc:
mov bh,00
mov cx,0
mov dx,0x184f
mov ax,0x0600
int 10h
ret

;简单打印信息子程序
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 14 ; CX = 串长度
mov dx,0x0 ;DH,DL=起始行,列
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, keroro!"
;----------------------------------
Main:

; call ClearSrc ;//清屏幕

;读取system的代码到setup程序后面
load_system:
mov ch,0 ;
mov cl,1+1+SETUPLEN/512 ;system所在的启始扇区
mov dx,0x0000;暂时直接就设置为读取软驱
mov bx,SETUPLEN
mov ax,0x0200+SYSTEMSIZE/512

int 0x13
jnc ok_load_system
;如果没有成功则磁盘系统复位然后再重新读取
mov dx,0x0000
mov ax,0x0000
int 0x13
jmp load_system

ok_load_system:
;jmp 0x90a0:0
;jmp SETUPSEG+SETUPOFFSET/0x10+SETUPLEN/0x10:0 ;用来测试system是否加载成功

cld
;移动system代码到0x0000


mov ax,SETUPSEG+SETUPOFFSET/0x10+SETUPLEN/0x10
mov ds,ax
mov ax,SYSTEMSEG
mov es,ax
mov cx,SYSTEMSIZE


sub si,si
sub di,di
rep movsw


;设置gdt
cli ;关中断
;由于要加载gdt重置一下段
mov ax,cs
mov ds,ax
lgdt [gdt_addr]

;打开A20地址线
call Empty_8042
mov al,0xd1
out 0x64,al
call Empty_8042
mov al,0xdf
out 0x60,al
call Empty_8042
;下面设置进入32位保护模式运行
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword 0x8:0x0
times SETUPLEN-($-$$) db 0

----------------------

bits 32
org 0x0
jmp Main
DATA_SEL equ 0x10 ;内核代码段选择子
BootMessage: db "Hello keroro!"
dw 0x0000
dw 0x0000


Main:
mov eax,DATA_SEL

mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,DATA_SEL ;# 所有数据段选择子设置为0x10,即GDT的第3项,特权级为0。

mov al,0x07
mov esi,BootMessage
mov edi,0xb8000
display:
cmp esi,0
je endPro
movsb
stosb
jmp display
endPro:
jmp endPro






参考文献(注:以前的参考文献同样会参考,这里就不列举了):
1:[Bochs]Bochs调试技术 http://huqingyu.cnblogs.com/archive/2005/02/19/105864.html
2:《自己动手写内核(中文版)》http://www.cppblog.com/jinglexy

标签:

leave a response