|
我把楼上所说的阶段性的代码贴出来,一方面是作为一个备份来防止代码丢失,另一方面也许有人对此感兴趣,那就可以帮助开发完善了。目前这个代码还没有取消楼上在结尾处所谈到的 “拥有 1152 空白扇区” 的功能。
这个代码编译完成后,已经抵达偏移 0x1B7 了,也就是说,连一个字节的剩余空间都没有了。从偏移 0x1B8 开始,那是大家熟悉的微软磁盘签名以及分区表。
- .text
- .code16
- start:
- jmp 1f
- . = start + 0x02
- .byte 0x90
- . = start + 0x03
- .ascii "MSWIN4.1"
- . = start + 0x0B
- .word 0x200
- . = start + 0x0D
- /* Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64 and 128.
- * But a cluster size larger than 32K should not occur.
- */
- .byte 0x01 // sectors per cluster, should be changed by installer
- . = start + 0x0E
- .word 0x0001 // reserved sectors, should be changed by installer
- . = start + 0x10
- .byte 0x02 // number of FATs
- . = start + 0x11
- .word 0 // FAT12/16 root dir entries. Must be 0
- . = start + 0x13
- .word 0 // FAT12/16 total sectors. Must be 0
- . = start + 0x15
- .byte 0xF8 // media descriptor
- . = start + 0x16
- .word 0 // FAT12/16 sectors per FAT. Must be 0
- . = start + 0x18
- .word 0x3f // sectors per track
- . = start + 0x1A
- .word 0xff // number of heads
- . = start + 0x1C
- .long 0 // hidden sectors, should be changed by installer
- . = start + 0x20
- .long 0 // total sectors, should be changed by installer
- . = start + 0x24
- .long 0 // sectors per FAT, should be changed by installer
- . = start + 0x28
- .word 0 // current active FAT
- . = start + 0x2A
- .word 0 // FAT32 revision number
- . = start + 0x2C
- .long 0 // root dir starting cluster
- . = start + 0x30
- .word 0 // file system information sector number
- . = start + 0x32
- .word 6 // boot record backup sector number
- . = start + 0x34
- .long 0 // reserved
- .long 0 // reserved
- .long 0 // reserved
- . = start + 0x40
- .byte 0x80 // drive number
- . = start + 0x41
- .byte 0
- . = start + 0x42
- /* Signature (must be 28h or 29h to be recognised by NT). */
- .byte 0x29 // extended boot signature for FAT12/FAT16
- . = start + 0x43
- .long 0x0AC4AF63 // volume serial number
- . = start + 0x47
- .ascii "NO NAME " // volume label, 11 bytes
- . = start + 0x52
- .ascii "FAT32 " // filesystem ID, 8 bytes
- . = start + 0x5A
- .word 0 // reserved
- .word 0 // reserved
- .word 0 // reserved
- . = start + 0x60
- 1:
- xorw %di, %di
- movw %di, %ds /* constant DS=0 */
- movw $0x7C00, %bp /* constant BP=0x7C00 */
- movw %di, %ss /* constant SS=0 */
- movw %bp, %sp
- movb %dl, 0x40(%bp) /* assume BIOS pass correct drive number. */
- /* Got control! Print DL on the screen. */
- movw $0xB800, %bx
- movw %bx, %es
- xchgw %ax, %dx /* DX -> AX */
- /* Undocumented AAM instruction Opcode: D4 imm8 */
- .byte 0xD4, 0x10 // AH= AL / 16, AL= AL % 16
- addw $0x3030, %ax
- xchgw %ax, %dx
- movb %dh, %al
- movb $0x9F, %ah # back/fore ground=bright blue/white
- cld
- stosw /* DI=2 */
- xchgw %ax, %dx
- movb $0x9F, %ah # back/fore ground=bright blue/white
- stosw /* DI=4 */
- /* sleep 3 seconds */
- movw $55, %cx /* 55 / 18.2 = 3 seconds */
- 1:
- movl 0x46c, %eax /* get old timer counter */
- sti /* enable interrupt for int8 timer */
- cmpl 0x46c, %eax /* timer counter changed by int8 ? */
- je 1b /* user will report it if it hangs here */
- loop 1b /* no change, wait a timer interrupt */
- /* DI=4 */
- //movw $4, %di /* try 4 times on read failure */
- movw %di, 0x18(%bp) /* set a known value 4: sectors per track */
- movw %di, 0x1a(%bp) /* set a known value 4: number of heads */
- pushw $0x0201 //--- /* BP-2 point to int13/AX: read 1 sector */
- /* read C/H/S=0/0/1 to 0000:7E00 */
- xorw %ax, %ax
- movw %ax, %es
- movw $0x7E00, %bx
- pushw %es //---
- pushw %bx //--- /* BP-6 point to 0x00007E00 on stack */
- movw $1, %cx /* read 1 sector */
- call readDisk /* CX=1, DX=0 */
- pushw 0x0E(%bx) //--- /* save sector serial number at BP-8 */
- movb $0x41, %ah
- movw $0x55AA, %bx
- call int13
- jc 1f /* no ebios */
- subw $0xAA55, %bx
- jnz 1f /* no ebios */
- //testb $1, %cl
- //jz 1f
- .byte 0xD0, 0xD9 // RCR CL,1; D0 C9 ROR CL,1 also OK
- jnc 1f /* no ebios */
- movb $0x42, -1(%bp) /* LBA supported */
- geometry_OK:
- /* read GRLDR to 0000:7E00 */
- /* calculate grldr starting sector number */
- /* grldr serial number = (0x28 + 126 + 255*63 - 190) */
- movw -8(%bp), %ax
- subw $(0x28 + 126 + (255*63) - 190), %ax
- //cdq /* EDX=0 */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- //xorl %ecx, %ecx
- movw $1152, %cx /* read 576K grldr */
- call readDisk /* CX=1152, DX=0 */
- movb 0x40(%bp), %dl
- movb $0xFF, %dh
- pushw %dx
- //ljmp $0, $0x7E00
- pushw %ds /* DS=0 */
- pushw %bx /* BX=0x7E00 */
- lret
- 1:
- /* no LBA */
- /* XXX: should confirm 0x18(%bp)=63, 0x1A(%bp)=255 */
- /* read C/H/S=0/1/1 to 0000:7E00 */
- //xorl %eax, %eax
- movw %di, %ax /* AX=4, start sector number */
- //cdq /* EDX=0 */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- movw $1, %cx /* read 1 sector */
- call readDisk /* CX=1, DX=0 */
- movw -8(%bp), %ax
- subw 0x0E(%bx), %ax /* the real sectors per track */
- pushw %ax //--- /* save it at BP-10 */
- pushw %dx //--- /* initial 0 at BP-12 */
- //movb %al, 0x18(%bp) /* update it! */
- /* read C/H/S=1/0/1 to 0000:7E00 */
- movw $21, %cx
- xorw %ax, %ax
- 1:
- addw $(4*4), %ax /* 16=sectors per cylinder */
- movw -10(%bp), %dx
- addw %dx, -12(%bp)
- pushw %cx
- pushw %ax
- //cdq /* EDX=0 */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- //xorl %ecx, %ecx
- movw %di, %cx /* read 4 sectors */
- call readDisk /* CX=4, DX=0 */
- movw 0x0E(%bx), %ax
- movw %ax, %cx
- decw %ax
- cmpw 0x20E(%bx), %ax
- jne 2f
- decw %ax
- cmpw 0x40E(%bx), %ax
- jne 2f
- decw %ax
- cmpw 0x60E(%bx), %ax
- jne 2f
- movw -8(%bp), %ax
- subw %cx, %ax /* sectors in cylinders */
- divw -12(%bp) /* rem=DX, should be 0 */
- /* quo=AX, number of heads */
- /* XXX: if DX != 0, here should halt! */
- movw %ax, 0x1A(%bp) /* update number of heads! */
- movb -12(%bp), %al
- movb %al, 0x18(%bp) /* update sectors per track! */
- jmp geometry_OK /* ready to load GRLDR */
- 2:
- popw %ax
- popw %cx
- loop 1b
- 1:
- hlt
- jmp 1b
- /* Read sectors from disk, using LBA or CHS
- * input: AX = 16-bit LBA sector number, and AX <= 0x7FFF
- * CX = number of sectors to read
- * ES:BX = destination buffer
- * SS = DS
- * BP+0x18 -> sectors per track
- * BP+0x1A -> number of heads
- * BP+0x40 -> drive number
- *
- * output: No return on error
- * BX not changed
- * CX not changed
- * ES = ES + 0x20 * CX
- * AX = AX + CX
- * DX = 0
- * ZF = 0
- * CF = 0
- */
-
- readDisk:
- cwd /* DX=0 */
- 2:
- pushaw
- pushw %dx /* 0 */
- pushw %dx /* 0 */
- pushw %dx /* 0 */
- pushw %ax /* lo 16bit of sector number */
- pushw %es /* buffer segment */
- pushw %bx /* buffer offset */
- pushw $1 /* 1 sector to read */
- pushw $16 /* size of this parameter block */
- cmpb $0x42, -1(%bp) /* LBA supported */
- je 1f /* LBA mode */
- /* CHS mode */
- divw 0x18(%bp) /* rem=DX */
- /* quo=AX */
- /* DH=0 */
- incw %dx /* DL=sector number */
- xchgw %dx, %cx /* CH=0, CL=sector number */
- cwd /* DX=0 */
- divw 0x1A(%bp) /* rem=DX */
- /* quo=AX, cylinder number */
- /* DH=0, DL=head number */
- xchgb %dl, %dh /* DL=0, DH=head number */
- xchgb %al, %ch /* AL=0, CH=lo 8bit cylinder */
- //shlb $6, %ah /* hi 2bit cylinder ... */
- //orb %ah, %cl /* ... should be in CL */
- shrw $2, %ax /* hi 2bit cylinder ... */
- orb %al, %cl /* ... should be in CL */
- testb %ah, %ah
- jnz disk_error /* cylinder overflow */
- 1:
- movw -2(%bp), %ax /* (E)BIOS read 1 sector */
- movw %sp, %si /* DS:SI points to disk address packet */
- movb 0x40(%bp), %dl /* drive number */
- pushw %es
- call int13_retry
- popw %bx
- //jc disk_error
- leaw 0x20(%bx), %bx
- movw %bx, %es
- popaw /* remove parameter block from stack */
- popaw
- incw %ax /* next sector, here ZF=0 */
- loop 2b
- ret
- // . = . - (. - readDisk)/68
- int13_retry:
- //movw $4, %di /* try 4 times on failure */
- 1:
- pushaw
- call int13
- popaw
- jc 2f
- ret
- 2:
- pushaw
- cbw /* AH=0, reset disk */
- //xorw %ax, %ax /* reset disk */
- call int13
- popaw
- decw %di
- jnz 1b
- disk_error:
- movw $(msg_DiskReadError - start + 0x7c00), %si
- //boot_error:
- /* prints string DS:SI (modifies AX BX SI) */
- 1:
- lodsb (%si), %al /* get token */
- //xorw %bx, %bx /* video page 0 */
- movb $0x0e, %ah /* print it */
- int $0x10 /* via TTY mode */
- cmpb $0, %al /* end of string? */
- jne 1b /* until done */
- 1: jmp 1b
- int13:
- pushw %ds
- pushw %es
- // pushw %bx /* int13/ah=41h use BX, so do not save. */
- // pushw %dx /* drive number already saved in memory. */
- pushw %si
- pushw %di
- pushw %bp
- stc
- int $0x13
- sti
- popw %bp
- popw %di
- popw %si
- // popw %dx
- // popw %bx
- popw %es
- popw %ds
- ret
- msg_DiskReadError:
- .ascii "disk fail\0"
复制代码
|
|