+ .set SECT_PER_TRACK, 18
+
+ .set ARG_NSECT, 6
+ .set ARG_SIDX, 4
+
+# read_sect(first, num)
+read_sect:
+ push %bp
+ mov %sp, %bp
+
+ mov ARG_SIDX(%bp), %ax
+ mov ARG_NSECT(%bp), %cx
+
+ jmp 1f
+0: push %ax
+ call read_sector
+ add $2, %sp
+1: cmp ARG_NSECT(%bp), %cx
+ jnz 0b
+
+ pop %bp
+ ret
+
+# read_sector(sidx)
+read_sector:
+ push %bp
+ mov %sp, %bp
+ push %cx
+ push %dx
+
+ # calculate the track (sidx / sectors_per_track)
+ mov 4(%bp), %ax
+ xor %dx, %dx
+ mov $SECT_PER_TRACK, %cx
+ div %cx
+ mov %ax, %cx
+ # save the remainder in ax
+ mov %dx, %ax
+ # head in dh
+ mov %cl, %dh
+ and $1, %dh
+ # cylinder (track/2) in ch [0-7] and cl[6,7]<-[8,9]
+ rol $7, %cx
+ ror $2, %cl
+ and $0xc0, %cl
+ # sector num cl[0-5] is sidx % sectors_per_track (saved in ax)
+ inc %al
+ or %al, %cl
+ # ah = 2 (read), al = 1 sectors
+ mov $0x0201, %ax
+ movb drive_number, %dl
+ int $0x13
+
+ # increment es:bx accordingly (advance es if bx overflows)
+ add $512, %bx
+ jno 0f
+ mov %es, %ax
+ add $4096, %ax
+ mov %ax, %es
+
+ pop %dx
+ pop %cx
+ pop %bp
+ ret
+
+clearscr:
+ push %es
+ pushw $0xb800
+ pop %es
+ xor %eax, %eax
+ xor %di, %di
+ movl $500, %ecx
+ rep stosl
+ pop %es
+ ret
+
+# expects number in eax
+print_num:
+ # save es
+ push %es
+
+ xor %cx, %cx
+ movw $numbuf, %si
+ mov $10, %ebx
+
+0: xor %edx, %edx
+ div %ebx
+ add $48, %dl
+ mov %dl, (%si)
+ inc %si
+ inc %cx
+ cmp $0, %eax
+ jnz 0b
+
+ # print the backwards string
+ pushw $0xb800
+ pop %es
+ xor %di, %di
+
+0: dec %si
+ mov (%si), %al
+ movb %al, %es:(%di)
+ inc %di
+ mov $7, %al
+ movb %al, %es:(%di)
+ inc %di
+ dec %cx
+ jnz 0b
+
+ # restore es
+ pop %es
+ ret
+
+drive_number: .byte 0
+numbuf: .space 10