为啥不能追求自己的爱好一辈子呢
分类: 其他平台
2013-02-06 15:09:36
上一段时间碰到一个问题,摸索了好长时间,原来是ld链接器对地址的定位,与我把程序的加载地址冲突,所以访问不到正确的位置,引起的。等碰到这个问题再说啦。
到达这里我们基本上已经完成了操作系统内核之前的准备了。我们就准备跳转到32位模式下啦。ok,让我们先考虑下进入32位模式之前需要做些什么
1.应该禁用pic中断,以避免有问题(虽然不禁用,暂时没发现什么问题)
2.开启A20Gate
3.初始化GDT
4.置CR0寄存器保护模式位
4.跳转啦
解释:为什么要禁用中断呢,嘿嘿,我也不知道。不过据说是:根据AT兼容机的规格,如果要初始化PIC必须在CLI之前进行,否则有时候会被挂起,随后进行PIC的初始化
代码为
mov AL,0xff out 0x21,AL ;pic0的端口 NOP ;等会儿嘛,太快了,可能出问题 out 0xal,al ;pic1的端口 cli ;禁用可屏蔽中断 |
pic有两个芯片的,一个是master一个slave在这里就不做详细的讨论啦。给个网址大家去看 http://wiki.osdev.org/PIC
然后是开启A20啦,因为之前只能访问1M的内存嘛(2的20次方),请参照 http://wiki.osdev.org/A20
;开启A20管脚 IN AL,0x64 AND AL,0x02 JNZ waitkbdout ; RET |
初始化GDT和CR0,我们开始初始化两个段,一个代码段一个数据段。看之前请参照 http://wiki.osdev.org/GDT,我们以后还会讲的
LGDT [GDTR0] ; 加载gd
ALIGNB 16
DW 0 ALIGNB 16 |
大家度过linux内核源码的估计会记得置位CR0的保护位用的是lmsw,那是古老的方式啦。
然后我决定可以把我们的程序移位到另一个地址,在此之前先刷新一下段寄存器吧
MOV AX,1*8 ; 段偏移量 MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX mov ax,AX MOV SS,AX |
然后是移位啦
BOTPAK EQU 0x00280000 ; 我们主程序load地址 MOV EDI,BOTPAK ; MOV ECX,512*1024/4 CALL memcpy MOV ESI,0x7c00 ;把boot程序加载到DSKCAC MOV EDI,DSKCAC ; MOV ECX,512/4 CALL memcpy MOV ESI,DSKCAC0+512 ; 把其余的也加载进来 MOV EDI,DSKCAC+512 ; MOV ECX,0 MOV CL,BYTE [CYLS] IMUL ECX,512*18*2/4 ; SUB ECX,512/4 ; CALL memcpy
memcpy: |
最后先写一个32位的汇编会跳到这里kernelFunc.asm,我们会让屏幕变个颜色的
[bits 32] hah: MOV eAX,1*8 ; 段偏移量 ,还是在这再初始化一次吧 MOV DS,AX MOV ES,AX MOV FS,AX MOV SS,AX mov esp,0x280000;把栈地址放到这把 mov eax ,0xa0000 loops: mov byte [eax],14 inc eax cmp eax, 0xaffff jbe loops jmp loo loo: hlt jmp loo |
然后写一个脚本吧 build.bat如在linux请先安装nasm,然后自己写一个makefile
rem 我们的bootloader nasm -o .\bin\begin.bin begin.asm rem 我们的入口 nasm -o haribote.o haribote.asm rem 我们的32位入口 nasm -o kernelFunc.o kernelfunc.asm rem copy二进制内容到一个地方 copy /B haribote.o+kernelFunc.o kernel |
至此全部haribote.asm的内容如下:
; haribote-os boot asm
BOTPAK EQU 0x00280000 ; 我们主程序load地址
ORG 0xc200 ;程序开始的地址
MOV AL,0x13 ; ;
MOV AH,0x02
;禁用pic中断 CLI ; 禁用可屏蔽中断
LGDT [GDTR0] ;
memcpy:
DW 0
ALIGNB 16 |
然后用winImage把boot加载进去,然后选择Image下面的Inject把我们的 kernel注入进去,用虚拟机加载一把吧,会有奇迹发生的。嘿嘿。今天就到这里吧。有问题请提问哈。