|
把改进后的代码贴出来,供查看。
- .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 0x08 // sectors per cluster, should be changed by installer
- . = start + 0x0E
- .word 0x0020 // reserved sectors, should be changed by installer
- . = start + 0x10
- .byte 0x02 // number of FATs(nearly always 2)
- . = start + 0x11
- .word 0 // FAT12/16 root dir entries. Must be 0 for FAT32
- . = start + 0x13
- .word 0 // FAT12/16 total sectors. Must be 0 for FAT32
- . = start + 0x15
- .byte 0xF8 // media descriptor
- . = start + 0x16
- .word 0 // FAT12/16 sectors per FAT. Must be 0 for FAT32
- . = start + 0x18
- .word 0x3f // sectors per track
- . = start + 0x1A
- .word 0xff // number of heads
- . = start + 0x1C
- .long 0x3F // hidden sectors, installer will change it
- . = start + 0x20
- .long 0x00FC0000 // total sectors, installer will change it
- . = start + 0x24
- /* 4-byte FAT32 sectors per FAT, installer will change it */
- /* The byte at offset 0x026 in this entry should never become
- * 0x28 or 0x29 in order to avoid any misinterpretation with the
- * EBPB format under non-FAT32 aware operating systems.
- */
- .byte 0x00, 0x3F, 0x00, 0x00
- //.byte 0x80, 0x00, 0x29, 0x00
- //.long 0
- . = start + 0x28
- .word 0 // current active FAT, installer will change it
- . = start + 0x2A
- .word 0 // FAT32 revision number, installer will change it
- . = start + 0x2C
- .long 2 // root dir starting cluster, installer will change it
- . = start + 0x30
- .word 1 // file system information sector number
- // installer will change it
- . = start + 0x32
- .word 6 // boot record backup sector number
- // installer will change it
- . = start + 0x34
- .long 0 // reserved
- .long 0 // reserved
- .long 0 // reserved
- . = start + 0x40
- .byte 0x80 // drive number
- . = start + 0x41
- /* Windows NT use it for CHKDSK flags:
- * Bits 7-2 always cleared;
- * Bit 1: disk I/O errors encountered, possible bad sectors,
- run surface scan on next boot;
- * Bit 0: volume is "dirty" and was not properly unmounted before
- shutdown, run CHKDSK on next boot.
- */
- .byte 0 // reserved, should be set to 0 by formating tools.
- . = start + 0x42
- /* Signature (must be 28h or 29h to be recognised by NT). */
- .byte 0x29 // extended boot signature for FAT32
- . = start + 0x43
- /* Originally it was 4-byte volume serial number. */
- /* hi word at offset 0x45 is used for serial number of sector 190 */
- .word 0xAF63 // hour, minutes, seconds
- .word (0x21 + 126 + (255*63) - 190) // installer will change it
- . = 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 $0x7C00, %bp /* constant BP=0x7C00 */
- movw %di, %ss /* constant SS=0 */
- movw %bp, %sp
- /* save DL first */
- movb %dl, 0x40(%bp) /* assume BIOS pass correct drive number. */
- /* Got control! */
- movw $0x0003, %ax /* Must switch to 80x25 color text mode! */
- pushaw
- int $0x10
- popaw
- movw %di, %ds /* constant DS=0 */
- /* print DX */
- xchgw %ax, %dx /* store DX into AX */
- call print_hex # BX changed
- /* print serial number of this sector */
- movw 0x0E(%bp), %ax
- call print_hex # BX changed
- /* sleep 3 seconds */
- sti /* enable interrupt for int8 timer */
- movw $55, %cx /* 55 / 18.2 = 3 seconds */
- 2:
- movw 0x46c, %ax /* get new ticks */
- cmpw %ax, %bx /* changed? */
- je 2b /* no, continue to wait */
- /* ticks changed by int8 */
- xchgw %ax, %bx /* update ticks */
- loop 2b
- /* CX=0 */
- pushw $0x0201 //--- /* BP-2 point to int13/AX: read 1 sector */
- /* read C/H/S=0/0/1 to 0000:7E00 */
- /* Generally, it is safe enough. */
- xorw %ax, %ax
- movw %ax, %es
- movw $0x7E00, %bx
- pushw %es //---
- pushw %bx //--- /* BP-6 point to 0x00007E00 on stack */
- incw %cx /* read 1 sector */
- call readDisk /* CX=1, DX=0 */
- pushw %cx /* 1, no POP in LBA branch. See below. */
- incw %cx /* CX=2 */
- movw %cx, 0x18(%bp) /* interim sectors per track */
- movw %cx, 0x1a(%bp) /* interim number of heads */
- pushw %cx /* 2, no POP in LBA branch. See below. */
- movw 0x0E(%bx), %si # mbr0
- /* print serial number of mbr0 */
- movw %si, %ax
- call print_hex # BX changed
- /* check LBA support */
- /* This can also be considered safe. */
- movb $0x41, %ah
- movw $0x55AA, %bx
- call int13
- jc 1f /* no ebios */
- cmpw $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 */
- /* print "AA55" */
- xchgw %ax, %bx /* store BX into AX */
- call print_hex # BX changed
- /* Keep the pushed 1 and 2 on stack without POPs. There is no harm. */
- jmp geometry_OK /* ready to load GRLDR */
- 1:
- /* CHS mode. Must determine geometry. */
- /* read C/H/S=0/1/1 to 0000:7E00 */
- //movw $2, %ax /* AX=2, interim sectors per track */
- popw %ax /* AX=2, interim sectors per track */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- popw %cx /* CX=1, read 1 sector */
- call readDisk # AX=3, CX=1, DX=0
- movw %si, %ax # mbr0
- subw 0x0E(%bx), %ax /* real sectors per track */
- jbe boot_error /* installation problem? */
- cmpw $63, %ax
- ja boot_error /* installation problem? */
- movw %ax, 0x18(%bp) /* update sectors per track! */
- /* print real sectors per track */
- call print_hex # BX changed
- /* read C/H/S=1/0/1 to 0000:7E00 */
- shlw $1, %ax /* AX=interim sectors per cylinder */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- //movw $1, %cx /* read 1 sector */
- call readDisk # AX=5, CX=1, DX=0
- movw %si, %ax # mbr0
- subw 0x0E(%bx), %ax /* real sectors per cylinder */
- jbe boot_error /* installation problem? */
- /* DX=0 */
- divw 0x18(%bp) /* rem=DX, should be 0 */
- /* quo=AX, number of heads */
- /* if DX != 0, stop! */
- testw %dx, %dx
- jnz boot_error /* installation problem? */
- movw %ax, 0x1A(%bp) /* update number of heads! */
- /* print real number of heads */
- call print_hex # BX changed
- testb %ah, %ah
- jnz boot_error /* installation problem? */
- geometry_OK:
- /* read GRLDR to 0000:7E00 */
- /* calculate grldr starting sector number */
- /* grldr serial number = (0x21 + 126 + 255*63 - 190) */
- xchgw %ax, %si # AX=mbr0
- #if 0
- movw $(0x21 + 126 + (255*63) - 190), %si
- #else
- movw 0x45(%bp), %si
- #endif
- subw %si, %ax
- jbe boot_error /* installation problem? */
- lesw -6(%bp), %bx /* ES:BX=0000:7E00 */
- movw $1152, %cx /* read 576K grldr */
- call readDisk /* CX=1152, DX=0 */
- cmpw %si, 0x0E(%bx)
- jne boot_error /* installation problem? */
- #if 0
- /* We can do it later in the second stage. */
- movb 0x40(%bp), %dl
- movb $0xFF, %dh
- pushw %dx
- #endif
- #if 1
- movw $0xACED, %ax /* OK! passed. */
- jmp boot_error /* Test succeeded. Halt. */
- #else
- /* jump to stage 2 */
- //ljmp $0, $0x7E00
- pushw %ds /* DS=0 */
- pushw %bx /* BX=0x7E00 */
- lret
- #endif
- int13_retry:
- movw $3, %di /* try 3 times on failure */
- 2:
- pushaw
- call int13
- popaw
- jc 1f
- ret
- 1:
- pushaw
- cbw /* AH=0, reset disk */
- call int13
- popaw
- decw %di
- jnz 2b
- disk_error:
- //movw $0xDEAD, %ax
- movw $0xCEDE, %ax # disk read error, give up
- boot_error:
- call print_hex # BX changed
- 2:
- jmp 2b
- /* Read sectors from disk, using LBA or CHS
- * input: AX = 16-bit LBA sector number
- * CX = number of sectors to read
- * AX + CX <= 0x8000
- * ES:BX = destination buffer
- * SS = DS
- * BP-0x02 -> function call number for AX
- * 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 */
- #if 1
- shrw $2, %ax /* hi 2bit cylinder ... */
- orb %al, %cl /* ... should be in CL */
- testb %ah, %ah
- #else
- /* equivalently, this should also work. */
- rolw $6, %ax /* hi 2bit cylinder in AH */
- orb %ah, %cl /* put into CL */
- testb %al, %al
- #endif
- jnz boot_error /* Cylinder overflow! Stop misreading! */
- 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:
- 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
- movb 0x40(%bp), %dl /* drive number */
- int $0x13
- sti
- popw %bp
- popw %di
- popw %si
- // popw %dx
- // popw %bx
- popw %es
- popw %ds
- ret
- print_hex:
- # input AX = value to print
- # DI = video text offset
- #
- # output ES = 0xB800
- # DF = 0
- # DI = changed
- # BX = changed
- pushw $0xB800
- popw %es # text mode video memory
- cld
- pushw %ax
- pushw %cx
- pushw %bx
- movw $4, %cx
- xchgw %ax, %bx
- 2:
- rolw $4, %bx
- #if 0
- movw %bx, %ax
- andb $0x0F, %al
- cmpb $10, %al
- jb 1f
- addb $7, %al
- 1:
- addb $0x30, %al
- movb $0x9F, %ah # back/fore ground=bright blue/white
- #else
- /* this can save 2 bytes of code. */
- movzbw %bl, %ax # AH=0
- sahf # AF=0
- aaa # AAA operation:
- // { IF (((AL & 0x0F) > 9) || AF == 1)
- // { AL += 6; AH++ ; AF = CF = 1; }
- // ELSE
- // { AF = CF = 0; }
- // AL &= 0x0F; }
- add %ah, %al
- .byte 0xD5, 0x10 # AAD imm8 operation:
- // { AL += (AH * imm8); AH = 0; }
- addw $0x1F30, %ax # back/fore ground=blue/bright white
- #endif
- stosw
- loop 2b
- movb $0x20, %al # keep colors in AH untouched
- stosw
- popw %bx
- popw %cx
- popw %ax
- ret
- . = start + 0x1B8
- . = start + 0x1BE
- .byte 0x80, 1, 1, 0, 0x0C, 0xFE, 0xFF, 0xFF
- .byte 0x3F, 0, 0, 0, 0x00, 0x00, 0xFC, 0x00
- . = start + 0x1FE
- .word 0xAA55
复制代码
|
|