005-完成ipl

来源:互联网 发布:des算法破解 编辑:程序博客网 时间:2024/04/30 20:33

       上次完成了启动盘,我们已经成功把启动区加载到了内存中,当然了,这512字节的空间肯定是不可能够我们写一个完整的操作系统的,所以,我们操作系统的其他部分肯定得在别的地方写,那么,ipl的任务就应该是把软盘这1440KB的内容全部加载到内存中,不过这里有一个相当严重的问题,就是我们在实模式下,只有20位寻址空间,换句话说,我们只能访问1MB的内存,所以暂时还没办法把所有的数据都放到内存中,暂时我们先只放10个柱面的内容到内存中。交给操作系统的内存部分是0x8000到0x9fbff,不过,虽然ipl的部分事先被加载到了0x7c00的位置,但是,它仍然作为软盘数据的一部分,这部分的数据在以后是有可能会用到的,因此,我们还是把0x8000到0x81ff的内存空间留给它,把剩下的内容从0x8200开始储存。

       我们按照扇区-磁头-柱面的顺序变更来读取软盘(也就是C0-H0-S1, C0-H0-S2, ……C0-H0-S18, C0-H1-S1, …… C0-H1-S18, C1-H0-S1, ……这样的顺序)一直读到C9-H1-S18。下面是改过后的ipl。


org 0x7c00jmp entrydb 0x90db "HELLOIPL"dw 512db 1dw 1db 2dw 224dw 2880db 0xf0dw 9dw 18dw 2dd 0dd 2880db 0, 0, 0x29db 0xffffffffdb "HELLO-OS   "db "FAT12   "resb 18entry:mov ax, 0mov ss, axmov sp, 0x7c00mov ds, axmov ax, 0x0820mov es, ax;缓冲地址段地址mov ch, 0; 柱面号mov dh, 0; 磁头号mov cl, 2; 扇区号readloop:mov si, 0retry:mov ah, 0x02mov al, 1; 处理1个扇区mov bx, 0; 缓冲地址基址mov dl, 0; 驱动器号int 0x13; 0x13号中断,ah=0x2时读盘,内容读取到es:bx中jnc succeed; 如果进位符是1表示读取错误,jnc表示进位符为0add si, 1cmp si, 5jae errormov ah, 0mov dl, 0int 0x13    ; 0x13号中断 ah=0, dl=0时系统复位jmp retrynext:mov ax, esadd ax, 0x20mov es, axadd cl, 1cmp cl, 18jbe readloopmov cl, 1add dh, 1cmp dh, 2jb  readloopmov dh, 0add ch, 1cmp ch, 10jb  readloopmov [0xff0], chjmp 0xc200succeed:mov si, msg_succeedjmp putlooperror:mov si,msg_errorputloop:mov al, [si]add si, 1cmp al, 0je  nextmov ah, 0x0emov bx, 15int 0x10jmp putloopmsg_error:db 0x0d, 0x0adb "load error"db 0x0a, 0msg_succeed:db 0x0d, 0x0adb "load success "db 0x0a, 0resb 0x7dfe-$db 0x55, 0xaa

       24-27行是寄存器的初始化,ss和sp这两个寄存器在本程序里还用不到,只不过写上合适的值方便以后添加程序。29-30行初始化了缓冲地址寄存器es,这是因为我们要设置数据的起点,由于我们要把数据加载到0x8200位置,所以数据的起点就是这里,段寄存器就指向这里。13号BIOS中断时有关软盘操作的,当al为1时进行读盘操作,将会把dl表示的驱动器中的内容存放到[es:bx]中;当al为0时进行重新读盘操作。36-49行尝试读盘,si寄存器存放的是尝试读盘的次数,所以在35行初始化为0,当尝试5次都失败时将放弃读取,输出错误信息,而读取成功后,就会跳转到next标签下。50-64行通过不断循环36-49行的指令,把10个扇区的数据全部载入内存中。65行向内存0xff0处保存了一个数据,这个数据是目前读取的扇区数,这也是为了以后拓展这个程序用的,可以方便地知道之前加载了多少数据。执行到66行时,程序应当将10个扇区都加载完毕了,跳转到0xc200处,没错,0xc200已经超出ipl的范围了,这就是给操作系统的一个引子,我们就应当把操作系统加载到这个位置,由于ipl之前已经把这些内容都加载到内存中了,所以,接下来就可以直接执行操作系统的内容了,接下来我们来写操作系统,很简单的,输出一行文字就好。

org 0xc200osEntry:mov ax, 0mov ds, axmov si, msgputloop:mov al, [si]add si, 1cmp al, 0je  finmov ah, 0xemov bx, 15int 0x10jmp putloopfin:hltjmp finmsg:db 0x0d, 0x0adb "Hello World!"db 0x0d, 0x0a, 0

       在输出了一系列的加载成功以后,又输出了Hello World!,这就表示,我们的操作系统已经加载出来了。

       所以,ipl的使命基本就是这样,但是现在还不是很完善,这个以后再去修改,在较长的一段时间就会保持这样,接下来的任务就要转向我们的操作系统内核了。下次将介绍在操作系统加载后如何进入保护模式,以便利用32位寻址空间,访问4GB的内存。

0 0