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 + -
显示快捷键?