boot.asm
来自「GNU FreeDOS兼容MS DOS很好的东东.」· 汇编 代码 · 共 528 行 · 第 1/2 页
ASM
528 行
; GETFATCHAIN:;; Reads the FAT chain and stores it in a temporary buffer in the first; 64 kb. The FAT chain is stored an array of 16-bit cluster numbers,; ending with 0.;; The file must fit in conventional memory, so it can't be larger than; 640 kb. The sector size must be at least 512 bytes, so the FAT chain; can't be larger than around 3 kb.;; Call with: AX = first cluster in chain ; Load the complete FAT into memory. The FAT can't be larger ; than 128 kb, so it should fit in the temporary buffer. les bx, [loadsegoff_60] ; es:bx=60:0 mov di, [sectPerFat] mov ax, word [fat_start] mov dx, word [fat_start+2] call readDisk pop ax ; restore first cluster numberjmp_boot_error: jc boot_error ; Set ES:DI to the temporary storage for the FAT chain. push ds pop es mov ds, [loadseg_60] mov di, FATBUFnext_clust: stosw ; store cluster number mov si, ax ; SI = cluster number%ifdef ISFAT12 ; This is a FAT-12 disk.fat_12: add si, si ; multiply cluster number by 3... add si, ax shr si, 1 ; ...and divide by 2 lodsw ; If the cluster number was even, the cluster value is now in ; bits 0-11 of AX. If the cluster number was odd, the cluster ; value is in bits 4-15, and must be shifted right 4 bits. If ; the number was odd, CF was set in the last shift instruction. jnc fat_even mov cl, 4 shr ax, clfat_even: and ah, 0x0f ; mask off the highest 4 bits cmp ax, 0x0ff8 ; check for EOF jb next_clust ; continue if not EOF%endif%ifdef ISFAT16 ; This is a FAT-16 disk. The maximal size of a 16-bit FAT ; is 128 kb, so it may not fit within a single 64 kb segment.fat_16: mov dx, [loadseg_60] add si, si ; multiply cluster number by two jnc first_half ; if overflow... add dh, 0x10 ; ...add 64 kb to segment valuefirst_half: mov ds, dx ; DS:SI = pointer to next cluster lodsw ; AX = next cluster cmp ax, 0xfff8 ; >= FFF8 = 16-bit EOF jb next_clust ; continue if not EOF%endiffinished: ; Mark end of FAT chain with 0, so we have a single ; EOF marker for both FAT-12 and FAT-16 systems. xor ax, ax stosw push cs pop ds ;call print ;db " Kernel",0 ; "KERNEL" ; loadFile: Loads the file into memory, one cluster at a time. les bx, [loadsegoff_60] ; set ES:BX to load address 60:0 mov si, FATBUF ; set DS:SI to the FAT chaincluster_next: lodsw ; AX = next cluster to read or ax, ax ; if EOF... je boot_success ; ...boot was successful dec ax ; cluster numbers start with 2 dec ax mov di, word [bsSecPerClust] and di, 0xff ; DI = sectors per cluster mul di add ax, [data_start] adc dx, [data_start+2] ; DX:AX = first sector to read call readDisk jnc cluster_nextboot_error: call print db " err",0 xor ah,ah int 0x16 ; wait for a key int 0x19 ; reboot the machineboot_success: ;call print ;db " GO! ",0 mov bl, [drive] jmp far [loadsegoff_60]; prints text after call to this function.print_1char: xor bx, bx ; video page 0 mov ah, 0x0E ; else print it int 0x10 ; via TTY modeprint: pop si ; this is the first characterprint1: lodsb ; get token push si ; stack up potential return address cmp al, 0 ; end of string? jne print_1char ; until done ret ; and jump to it; readDisk: Reads a number of sectors into memory.;; Call with: DX:AX = 32-bit DOS sector number; DI = number of sectors to read; ES:BX = destination buffer; ES must be 64k aligned (1000h, 2000h etc).;; Returns: CF set on error; ES:BX points one byte after the last byte read.readDisk: push si mov LBA_SECTOR_0,ax mov LBA_SECTOR_16,dx mov word [LBA_SEG],es mov word [LBA_OFF],bxread_next:;******************** LBA_READ ******************************* ; check for LBA support mov ah,041h ; mov bx,055aah ; mov dl, [drive] test dl,dl ; don't use LBA addressing on A: jz read_normal_BIOS ; might be a (buggy) ; CDROM-BOOT floppy emulation int 0x13 jc read_normal_BIOS shr cx,1 ; CX must have 1 bit set sbb bx,0aa55h - 1 ; tests for carry (from shr) too! jne read_normal_BIOS ; OK, drive seems to support LBA addressing lea si,[LBA_PACKET] ; setup LBA disk block mov LBA_SECTOR_32,bx mov LBA_SECTOR_48,bx mov ah,042h jmp short do_int13_read read_normal_BIOS: ;******************** END OF LBA_READ ************************ mov cx,LBA_SECTOR_0 mov dx,LBA_SECTOR_16 ; ; translate sector number to BIOS parameters ; ; ; abs = sector offset in track ; + head * sectPerTrack offset in cylinder ; + track * sectPerTrack * nHeads offset in platter ; mov al, [sectPerTrack] mul byte [nHeads] xchg ax, cx ; cx = nHeads * sectPerTrack <= 255*63 ; dx:ax = abs div cx ; ax = track, dx = sector + head * sectPertrack xchg ax, dx ; dx = track, ax = sector + head * sectPertrack div byte [sectPerTrack] ; dx = track, al = head, ah = sector mov cx, dx ; cx = track, al = head, ah = sector ; the following manipulations are necessary in order to ; properly place parameters into registers. ; ch = cylinder number low 8 bits ; cl = 7-6: cylinder high two bits ; 5-0: sector mov dh, al ; save head into dh for bios xchg ch, cl ; set cyl no low 8 bits ror cl, 1 ; move track high bits into ror cl, 1 ; bits 7-6 (assumes top = 0) mov al, byte [sectPerTrack] sub al, ah ; al has # of sectors left inc ah ; sector offset from 1 or cl, ah ; merge sector into cylinder les bx,[LBA_OFF] mov ax, 0x0201do_int13_read: mov dl, [drive] int 0x13read_finished: jnc read_ok ; jump if no error xor ah, ah ; else, reset floppy int 0x13read_next_chained: jmp short read_next ; read the same sector againread_ok: mov ax, word [bsBytesPerSec] div byte[LBA_PACKET] ; luckily 16 !! add word [LBA_SEG], ax add LBA_SECTOR_0, byte 1 adc LBA_SECTOR_16, byte 0 ; DX:AX = next sector to read dec di ; if there is anything left to read, jnz read_next_chained ; continue mov es,word [LBA_SEG] ; clear carry: unnecessary since adc clears it pop si ret times 0x01f1-$+$$ db 0filename db "KERNEL SYS",0,0sign dw 0xAA55
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?