⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boot.asm

📁 用C和汇编写的Dos操作系统的源码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
next_clust:     stosw                           ; store cluster number
		mov     si, ax                  ; SI = cluster number
		cmp     byte ptr extBoot, 29h
		jne     fat_12
		cmp     byte ptr filesys[4], '6'  ; check for FAT-16 system
		je      fat_16

		; 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, cl          ; shift the cluster number 
		
fat_even:       and     ah, 0fh         ; mask off the highest 4 bits
		cmp     ax, 0fffh       ; check for EOF
		jmp     short next_test

		; 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, tempbuf
		add     si, si          ; multiply cluster number by two
		jnc     first_half      ; if overflow...
		add     dh, 10h         ; ...add 64 kb to segment value

first_half:     mov     ds, dx          ; DS:SI = pointer to next cluster
		lodsw                   ; AX = next cluster

		cmp     ax, 0fff8h      ; >= FFF8 = 16-bit EOF
next_test:      jb      next_clust      ; continue if not EOF

finished:       ; 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
fatError:
		ENDM

;	loadFile: Loads the file into memory, one cluster at a time.

loadFile        MACRO
		mov     es, tempbuf     ; set ES:BX to load address
		xor     bx, bx

		mov     si, FATBUF      ; set DS:SI to the FAT chain
		push    cs      
		pop     ds              

next_cluster:   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 ptr sectPerCluster
		and     di, 0ffh                ; DI = sectors per cluster
		mul     di                       
		add     ax, data_start
		adc     dx, data_start+2        ; DX:AX = first sector to read
		call    readDisk
		jnc     next_cluster            

		ENDM

		org     BASE+3eh

tempbuf         equ     [bp+3eh]
load_seg        dw      LOADSEG

real_start:     cli
		cld
		mov     ax, cs
		mov     ss, ax          ; initialize stack      
		mov     bp, 7c00h
		lea     sp, [bp-20h]
		sti

		mov     es, ax
		mov     ds, ax
		mov     drive, dl       ; BIOS passes drive number in DL

		GETDRIVEPARMS

		FINDFILE                ; locate file in root directory
		jc      boot_error      ; fail if not found

		GETFATCHAIN             ; read FAT chain
		LOADFILE                ; load file (jumps to boot_sucess if successful)

boot_error:     mov     cx, ERRMSGLEN
		mov     si, offset errmsg+7c00h

next_char:      lodsb                   ; print error message
		mov     ah, 0eh
		xor     bh, bh
		int     10h
		loop    next_char

		xor     ah, ah
		int     16h             ; wait for keystroke
		int     19h             ; invoke bootstrap loader

boot_success:   mov     dl, drive

		db      0eah            ; far jump to LOADSEG:0000
		dw      0
		dw      LOADSEG


;	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        proc
		push    si
read_next:      push    dx
		push    ax

		;
		; translate sector number to BIOS parameters
		;

		;
		; abs = sector                          offset in track
		;     + head * sectPerTrack             offset in cylinder
		;     + track * sectPerTrack * nHeads   offset in platter
		; 
		; t1     = abs  /  sectPerTrack         (ax has t1)
		; sector = abs mod sectPerTrack         (cx has sector)
		;
		div     word ptr sectPerTrack
		mov     cx, dx

		;
		; t1   = head + track * nHeads
		;
		; track = t1  /  nHeads                 (ax has track)
		; head  = t1 mod nHeads                 (dl has head)
		;
		xor     dx, dx
		div     word ptr nHeads

		; 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, dl                  ; save head o dh for bios
		ror     ah, 1                   ; move track high bits into
		ror     ah, 1                   ; bits 7-6 (assumes top = 0)
		xchg    al, ah                  ; swap for later
		mov     dl, byte ptr sectPerTrack
		sub     dl, cl
		inc     cl                      ; sector offset from 1
		or      cx, ax                  ; merge cylinder into sector
		mov     al, dl                  ; al has # of sectors left

		; Calculate how many sectors can be transfered in this read
		; due to dma boundary conditions.
		push    dx

		mov     si, di                  ; temp register save
		; this computes remaining bytes because of modulo 65536
		; nature of dma boundary condition
		mov     ax, bx                  ; get offset pointer
		neg     ax                      ; and convert to bytes
		jz      ax_min_1                ; started at seg:0, skip ahead

		xor     dx, dx                  ; convert to sectors
		div     word ptr bytesPerSector
		
		cmp     ax, di                  ; check remainder vs. asked
		jb      ax_min_1                ; less, skip ahead
		mov     si, ax                  ; transfer only what we can

ax_min_1:       pop     dx

		; Check that request sectors do not exceed track boundary
		mov     si, sectPerTrack
		inc     si
		mov     ax, cx                  ; get the sector/cyl byte
		and     ax, 03fh                ; and mask out sector
		sub     si, ax                  ; si has how many we can read
		mov     ax, di
		cmp     si, di                  ; see if asked <= available
		jge     ax_min_2
		mov     ax, si                  ; get what can be xfered

ax_min_2:       mov     si, RETRYCOUNT
		mov     ah, 2
		mov     dl, drive

retry:          push    ax
		int     13h
		pop     ax
		jnc     read_ok
		push    ax
		xor     ax, ax          ; reset the drive
		int     13h
		pop     ax
		dec     si
		jnz     retry
		stc
		pop     ax
		pop     dx
		pop     si
		ret

read_next_jmp:  jmp     short read_next
read_ok:        xor     ah, ah                          
		mov     si, ax                  ; AX = SI = number of sectors read      
		mul     word ptr bytesPerSector ; AX = number of bytes read
		add     bx, ax                  ; add number of bytes read to BX
		jnc     no_incr_es              ; if overflow...

		mov     ax, es       
		add     ah, 10h                 ; ...add 1000h to ES
		mov     es, ax
		
no_incr_es:     pop     ax
		pop     dx                      ; DX:AX = last sector number

		add     ax, si
		adc     dx, 0                   ; DX:AX = next sector to read
		sub     di, si                  ; if there is anything left to read,
		jg      read_next_jmp           ; continue

		clc
		pop     si
		ret
readDisk        endp

errmsg          db      "Boot error"
ERRMSGLEN       equ     $ - errmsg


filename        db      "IPL     SYS"   

		org     BASE+01feh
sign            dw      0aa55h

TEXT            ENDS
		end




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -