前面提到过我们装载system的时候有问题,当system还很小的时候可以应付,后面如果变大我们没办法把它全部读入内存,下面我们就来修改启动扇区中的load_system将全部的system读入内存。
load_system:
movb $0x00,%dl
mov $0x0800,%ax
int $0x13
movb $0x00,%ch
mov %cx,(sectors)
mov $SYSSEG,%ax
mov %ax,%es
call read_it
call kill_motor
ok_load_system:
jmpl $SETUPSEG,$0
sread:.word 1+SETUPLEN
head: .word 0
track:.word 0
sectors:
.word 0
read_it:
mov %es,%ax
test $0x0fff,%ax//es值必须位于64KB地址边界(ax&0xfff)
die:jne die
xor %bx,%bx //bx为段内偏移,清零
rp_read:
mov %es,%ax
cmp $ENDSEG,%ax //ax - ENDSEG //如果ax小于ENDSEG,则跳到ok1_read去执行
jb ok1_read //JB是无符号数比较测试指令,条件是小于则转移,而CPU是通过测试CF是否等于1,如果等于1表示有借位,则说明前面这个数小于后面这个数
ret
ok1_read:
//seg %cs
mov (sectors),%ax //将磁道扇区数sectors的值放到ax中
sub (sread),%ax //剩余扇区数 = 磁道扇区数(sectors) - 已读扇区数(sread)
mov %ax,%cx //剩余扇区数放到cx寄存器
shl $9,%cx //剩余扇区数*512字节+当前段内偏移值(bx)
add %bx,%cx
//可用于两个数的判断!jnc是进位位为0则转移!而两个数的比较就是想减,例如X-Y,X小于Y,X就要借位,这样进位位就为1,如果X大于Y,X就不需要借位,这样进位位为0
jnc ok2_read//jnc是一条跳转指令,当进位标记C为0时跳转,为1时执行后面的指令,如果小于0x10000(64KB),跳转到ok2_read执行
je ok2_read //刚好等于64KB时,0标志为1,跳转
//计算最多能读取的扇区数
xor %ax,%ax //ax清零
sub %bx,%ax //ax - bx即0 - bx即取bx对64KB的补值,
shr $9,%ax //除以512得到扇区数,计算出需要读取的扇区数
ok2_read:
call read_track
mov %ax,%cx //cx = 该次操作读取的扇区数
add (sread),%ax //加上当前磁道已读扇区数
//seg %cs
cmp (sectors),%ax //如果当前磁道还有未读扇区,跳到ok3_read执行
jne ok3_read
mov $1,%ax
sub (head),%ax //判断当前磁头号,ax=ax-head
jne ok4_read //如果是0磁头,再去读1磁头上扇区的数据
//inc (track) //否则去读下一磁道
add $1,(track)
ok4_read:
mov %ax,(head) //保存当前磁头号
xor %ax,%ax //清当前磁道已读扇区数
ok3_read:
//如果当前磁道上还有未读扇区,则先保存当前磁道已读扇区数,然后调整存放数据处的开始位置
//若小于64KB边界,则跳转到rp_read处,继续读数据。
mov %ax,(sread) //保存当前磁道已读扇区数
shl $9,%cx //已读扇区数*512字节
add %cx,%bx //调整当前段内数据开始位置
jnc rp_read
//否则说明已经读取64KB数据。调整当前段,为读下一段数据做准备。
mov %es,%ax
add $0x1000,%ax
mov %ax,%es
xor %bx,%bx
jmp rp_read
//读取当前磁道上指定开始扇区 需要读的扇区数的数据到es:bx处
read_track:
push %ax
push %bx
push %cx
push %dx
mov (track),%dx//取当前磁道号
mov (sread),%cx//取此磁道上已读扇区数
inc %cx //cl = 开始读的扇区号
mov %dl,%ch //ch = 当前磁头号
mov (head),%dx //取当前磁头号
mov %dl,%dh //dh = 磁头号
mov $0,%dl //dl = 驱动器号(0表示A驱动器)
and $0x0100,%dx//磁头号不大于1
mov $2,%ah //ah = 2,读取磁盘扇区功能号
int $0x13 //0x13中断
jc bad_rt //若出错,则跳转至bad_rt
pop %dx
pop %cx
pop %bx
pop %ax
ret
//若出错,则复位驱动器,重新读取
bad_rt:
mov $0,%ax
mov $0,%dx
int $0x13
pop %dx
pop %cx
pop %bx
pop %ax
jmp read_track
kill_motor:
push %dx
mov $0x3f2,%dx
mov $0,%al
outb %al,$0x3f2
pop %dx
ret