chimaera.vhd: all
if [ -f $@ ]; then rm -rf $@; fi
+# utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,06,17,65535 $@
+# utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat16.bin --offset 17 --sectors 65535 -F 16 -n "CHIMAERA OS" $@
+
utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,11,17,66623 $@
utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat32_chs.bin --offset 17 --sectors 66623 -F 32 -n "CHIMAERA OS" $@
-
+
utils/dosfstools/mmd --arca --offset 17 -i $@ boot boot/freeldr
utils/dosfstools/mcopy --arca --offset 17 -i $@ $(SRCDIR)/boot/freeldr/freeldr.cfg ::/boot/freeldr/
chimaera.vhd: all
if exist $@ ( del /q $@ )
- utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,11,17,65535 $@
+ utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,06,17,65535 $@
utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat16.bin --offset 17 --sectors 65535 -F 16 -n "CHIMAERA OS" $@
utils/dosfstools/mmd --arca --offset 17 -i $@ boot boot/freeldr
call _writestr
call _crlf
- mov ah, HEX (08)
+; mov ah, HEX (08)
+; int HEX (21)
+;
+; call _writehex
+; call _crlf
+;
+; mov ah, HEX (07)
+; int HEX (21)
+;
+; call _writehex
+; call _crlf
+;
+; xor ax, ax
+; int HEX (16)
+
+ mov ah, HEX (39)
+ mov dx, offset _dir_non_exist
int HEX (21)
call _writehex
call _crlf
- mov ah, HEX (07)
+ mov ah, HEX (39)
+ mov dx, offset _dir_exist
int HEX (21)
call _writehex
call _crlf
- xor ax, ax
- int HEX (16)
+ mov ah, HEX (39)
+ mov dx, offset _dir_file
+ int HEX (21)
+
+ call _writehex
+ call _crlf
xor ax, ax
ret
;; Data area.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
msg_hello: db "Hello, world!", HEX (0D), HEX (0A), HEX (00)
+
+_dir_non_exist: db "abc\\123", HEX (00)
+_dir_exist: db "temp", HEX (00)
+_dir_file: db "hello.com", HEX (00)
gcc -o $@ $^
endif
-pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o dir.o erase.o exit.o history.o pcomm.o time.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
+pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o dir.o erase.o exit.o history.o mkdir.o pcomm.o time.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
../../utils/binutils/slink --oformat msdos -o $@ $^
%.o: %.asm
genver.exe: genver.c
gcc -o $@ $^
-pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o dir.o erase.o exit.o history.o pcomm.o time.o type.o vector.o writedec.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
+pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o dir.o erase.o exit.o history.o mkdir.o pcomm.o time.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
../../utils/binutils/slink --oformat msdos -o $@ $^
%.o: %.asm
mov bx, offset _cmdline
-_handler_dir.store_file:
+_handler_dir.store_arg:
cmp byte ptr [bx], 0
je _handler_dir.check2
je _handler_dir.check2
cmp byte ptr [bx], ' '
- ja _handler_dir.store_file
+ ja _handler_dir.store_arg
inc bx
jmp _handler_dir.skip
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file mkdir.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_mkdir
+;******************************************************************************
+global _handler_mkdir
+_handler_mkdir:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 4
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 2], 0
+
+ cmp byte ptr [bx], 0
+ jne _handler_mkdir.ok
+
+ mov bx, offset _err_invalid
+ call _writestr
+
+ jmp _handler_mkdir.done
+
+_handler_mkdir.ok:
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ mov di, offset _cmdline
+ mov si, bx
+
+ mov cx, ax
+ rep movsb
+
+ xor al, al
+ stosb
+
+ mov bx, offset _cmdline
+
+_handler_mkdir.store_arg:
+
+ cmp byte ptr [bx], 0
+ je _handler_mkdir.next
+
+ mov si, bx
+ push si
+
+ mov ax, offset _vec_files
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+_handler_mkdir.check:
+
+ mov ax, ' '
+ push ax
+
+ mov si, bx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _handler_mkdir.next
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ inc bx
+
+_handler_mkdir.skip:
+
+ cmp byte ptr [bx], 0
+ je _handler_mkdir.next
+
+ cmp byte ptr [bx], ' '
+ ja _handler_mkdir.store_arg
+
+ inc bx
+ jmp _handler_mkdir.skip
+
+_handler_mkdir.next:
+
+ mov ax, word ptr [bp - 4]
+ inc ax
+
+ cmp ax, cs:[_vec_files + 4]
+ ja _handler_mkdir.cleanup
+
+ mov word ptr [bp - 4], ax
+ dec ax
+
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+ push es
+
+ mov ax, cs:[_vec_files + 0]
+ mov es, ax
+
+ mov ax, es:[bx]
+ mov bx, ax
+
+ pop es
+
+_handler_mkdir.open:
+
+ mov ah, HEX (39)
+ mov dx, bx
+ int HEX (21)
+ jnc _handler_mkdir.next
+
+_handler_mkdir.error:
+
+ push bx
+
+ mov bx, offset _err_failed
+ call _writestr
+
+ pop bx
+
+ call _writestr
+ call _crlf
+
+ jmp _handler_mkdir.next
+
+_handler_mkdir.cleanup:
+
+ mov ax, cs:[_vec_files + 0]
+ push ax
+
+ call _free
+ add sp, 2
+
+ mov ax, cs
+ mov es, ax
+
+ mov di, offset _vec_files
+ xor al, al
+
+ mov cx, 6
+ rep stosb
+
+_handler_mkdir.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 4
+ pop bp
+
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_vec_files: db 6 dup (0)
+_cmdline: db 256 dup (0)
+
+_err_invalid: db "Invalid number of parameters", HEX (0D), HEX (0A), HEX (00)
+_err_failed: db "Unable to create directory - ", HEX (00)
call _strlen
add sp, 2
+ add bx, ax
+
+.L54:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was no string then we skip the following code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, ax
+ jz .L55
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the last character is not an asterisk then we have the
+ ;; right length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp byte ptr [bx - 1], '*'
+ jne .L55
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Otherwise, decrement ax by one as our command line doesn't
+ ;; have the asterisk character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec ax
+
+.L55:
+
mov bx, ax
jmp .L41
db "DIR Displays a list of files and subdirectories in a directory.", HEX (0D), HEX (0A)
db "ECHO Specifies the text to display to the screen.", HEX (0D), HEX (0A)
db "EXIT Exit the current shell if it's not the last instance.", HEX (0D), HEX (0A)
+ db "MKDIR Create a new directory.", HEX (0D), HEX (0A)
db "REBOOT Reboots the machine.", HEX (0D), HEX (0A)
db "TIME Displays the system time.", HEX (0D), HEX (0A)
db "TYPE Displays the contents of a text file.", HEX (0D), HEX (0A)
dw 0
dw _handler_help
+ dw hash_mkdir
+ dw 0
+ dw _handler_mkdir
+
dw hash_reboot
dw 0
dw _handler_reboot
mov bx, offset _cmdline
-_handler_type.store_file:
+_handler_type.store_arg:
cmp byte ptr [bx], 0
je _handler_type.next
je _handler_type.next
cmp byte ptr [bx], ' '
- ja _handler_type.store_file
+ ja _handler_type.store_arg
inc bx
jmp _handler_type.skip
_handler_type.clear_and_read:
- mov di, offset _buffer
- xor al, al
-
- mov cx, 256
- rep stosb
-
mov ah, HEX (3F)
mov cx, 255
mov dx, offset _buffer
and ax, ax
jz _handler_type.close
- mov si, offset _buffer
+ mov si, dx
+ mov cx, ax
_handler_type.print_loop:
lodsb
- and al, al
- jz _handler_type.clear_and_read
-
cmp al, HEX (0A)
jne _handler_type.char_ok
mov dl, al
int HEX (21)
- jmp _handler_type.print_loop
+ dec cx
+ jnz _handler_type.print_loop
+
+_handler_type.read_done:
+
+ jmp _handler_type.clear_and_read
_handler_type.close:
for f in *.lst; do if [ -f $$f ]; then rm -rf $$f; fi; done
if [ -f kernel.sys ]; then rm -rf kernel.sys; fi
-kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
+kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
../utils/binutils/slink --oformat binary -o $@ $^
%.o: %.asm
for %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
if exist kernel.sys ( del /q kernel.sys )
-kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
+kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
../utils/binutils/slink --oformat binary -o $@ $^
%.o: %.asm
;; Set the base pointer to the stack pointer and reserve some space.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov bp, sp
- sub sp, 24
+ sub sp, 26
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Preserve registers.
mov word ptr [bp - 20], 0
mov word ptr [bp - 22], 0
mov word ptr [bp - 24], 0
+ mov word ptr [bp - 26], 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MBR partitions start at offset 0x01BE and are 16 bytes in length.
cmp byte ptr es:[bx + 1], HEX (58)
jne .L12
+ mov ax, es:[bx + 48]
+ mov word ptr [bp - 26], ax
+
mov ax, es:[bx + 44]
mov dx, es:[bx + 46]
mov ax, word ptr [bp - 20]
stosw
+ mov ax, word ptr [bp - 26]
+ stosw
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Get drive parameters.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Clear the carry flag.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- add sp, 24
+ add sp, 26
clc
jmp .L20
.L22:
- add sp, 24
+ add sp, 26
stc
.L20:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ret
+;******************************************************************************
+; @function _write_sectors
+;******************************************************************************
+global _write_sectors
+_write_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+_write_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_write_sectors.retry:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push cx
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If disk extensions aren't avaiable then we need to use CHS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_edd_available], 1
+ jb _write_sectors.chs
+
+_write_sectors.lba:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll create the LBA write on the stack. 8086 doesn't allow pushing
+ ;; values directly so we'll use si.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+ push si
+ push si
+
+ push dx
+ push ax
+ push es
+ push bx
+
+ mov si, 1
+ push si
+
+ mov si, 16
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The dl register needs to be set to the drive number before we alter
+ ;; the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dl, cs:[_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need to set si to sp as the LBA write requires ds:si.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment to the stack segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ss
+ pop ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; write the sector into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (43)
+ stc
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cleanup the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 16
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was no carry the we successfully write the sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _write_sectors.success
+
+_write_sectors.chs:
+
+ div word ptr cs:[_sectors_per_track]
+ ; ax = LBA / SPT
+ ; dx = LBA # SPT = sector - 1
+
+ mov cx, dx
+ inc cx
+ ; cx = sector no.
+
+ xor dx, dx
+ div word ptr cs:[_heads_per_cylinder]
+ ; ax = (LBA / SPT) / HPC = cylinder
+ ; dx = (LBA / SPT) # HPC = head
+
+ mov ch, al
+ ; ch = LSB 0...7 of cylinder no.
+ ror ah
+ ror ah
+ or cl, ah
+ ; cl = MSB 8...9 of cylinder no. + sector no.
+ mov dh, dl
+ ; dh = head no.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; write the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0301)
+ mov dl, cs:[_drive_no]
+ stc
+ int HEX (13)
+ jnc _write_sectors.success
+
+_write_sectors.failure:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ah, ah
+ mov dl, cs:[_drive_no]
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement the loop counter and retry if greater than zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec di
+ jnz _write_sectors.retry
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_write_sectors.success:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the bytes per sector to bx to get the next offset to write in to.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add bx, cs:[_bytes_per_sector]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 1
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop until cx is zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ loop _write_sectors.next
+
+_write_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data area.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%include "fat.inc"
+;******************************************************************************
+; @function _calculate_total
+;******************************************************************************
+_calculate_total:
+
+ push cx
+ push si
+
+ mov ax, cs:[_total_sectors16]
+ xor dx, dx
+
+ and ax, ax
+ jnz _calculate_total.have_secs
+
+ mov ax, cs:[_total_sectors32]
+ mov dx, cs:[_total_sectors32 + 2]
+
+_calculate_total.have_secs:
+
+ sub ax, cs:[_data_start]
+ sbb dx, cs:[_data_start + 2]
+
+ xor ch, ch
+ mov cl, cs:[_sectors_per_cluster]
+
+ xor si, si
+ push si
+
+ push si
+ push cx
+ push dx
+ push ax
+
+ call _udivmodsi4
+ add sp, 10
+
+_calculate_total.done:
+
+ pop si
+ pop cx
+ ret
+
+
;******************************************************************************
; @function _convert_cluster12
;******************************************************************************
add dx, cx
- add ax, cs:[_data_start]
- adc dx, cs:[_data_start + 2]
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _find_free12
+;******************************************************************************
+global _find_free12
+_find_free12:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+ mov ax, cs:[_fat_seg]
+ mov es, ax
+
+ call _calculate_total
+
+ mov si, ax
+ mov di, dx
+
+ mov ax, 2
+ xor dx, dx
+
+_find_free12.loop:
+
+ mov bx, si
+ or bx, cx
+
+ and bx, bx
+ jz _find_free12.error
+
+ push ax
+ push dx
+ push si
+ push cx
+
+ mov si, ax
+
+ mov ax, 3
+ mul si
+
+ shr ax
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+ mov ax, cs:[_fat_start]
+ mov dx, cs:[_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ xor bx, bx
+
+ cmp ax, cs:[_fat_sector]
+ jne _find_free12.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _find_free12.check
+
+_find_free12.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_find_free12.check:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, es
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _find_free12.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_find_free12.even_cluster:
+
+ and ax, HEX (0FFF)
+
+ xor dx, dx
+ pop si
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _find_free12.next
+
+ pop dx
+ pop ax
+
+ jmp _find_free12.done
+
+_find_free12.next:
+
+ pop dx
+ pop ax
+
+ add ax, 1
+ adc dx, 0
+
+ sub si, 1
+ sbb di, 0
+
+ jmp _find_free12.loop
+
+_find_free12.error:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ stc
+ ret
+
+_find_free12.done:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _find_free16
+;******************************************************************************
+global _find_free16
+_find_free16:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+ mov ax, cs:[_fat_seg]
+ mov es, ax
+
+ call _calculate_total
+
+ mov si, ax
+ mov di, dx
+
+ mov ax, 2
+ xor dx, dx
+
+_find_free16.loop:
+
+ mov bx, si
+ or bx, cx
+
+ and bx, bx
+ jz _find_free16.error
+
+ push ax
+ push dx
+ push si
+ push cx
+
+ shl ax
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+ mov ax, cs:[_fat_start]
+ mov dx, cs:[_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ xor bx, bx
+
+ cmp ax, cs:[_fat_sector]
+ jne _find_free16.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _find_free16.check
+
+_find_free16.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_find_free16.check:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, cs:[_fat_seg]
+ jnc _find_free16.first64
+
+ add ax, HEX (1000)
+
+_find_free16.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+ xor dx, dx
+ pop si
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _find_free16.next
+
+ pop dx
+ pop ax
+
+ jmp _find_free16.done
+
+_find_free16.next:
+
+ pop dx
+ pop ax
+
+ add ax, 1
+ adc dx, 0
+
+ sub si, 1
+ sbb di, 0
+
+ jmp _find_free16.loop
+
+_find_free16.error:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ stc
+ ret
+
+_find_free16.done:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _find_free32
+;******************************************************************************
+global _find_free32
+_find_free32:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+ mov ax, cs:[_fat_seg]
+ mov es, ax
+
+ call _calculate_total
+
+ mov si, ax
+ mov di, dx
+
+ mov ax, 2
+ xor dx, dx
+
+_find_free32.loop:
+
+ mov bx, si
+ or bx, cx
+
+ and bx, bx
+ jz _find_free32.error
+
+ push ax
+ push dx
+ push di
+ push cx
+
+ mov di, ax
+
+ and di, cs:[_fat_secmask]
+ mov cx, cs:[_fat_secshift]
+
+_find_free32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _find_free32.cn_loop
+
+ shl di
+ shl di
+ mov word ptr [bp - 2], di
+
+ pop cx
+
+ add ax, cs:[_fat_start]
+ adc dx, cs:[_fat_start + 2]
+
+ xor bx, bx
+
+ cmp ax, cs:[_fat_sector]
+ jne _find_free32.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _find_free32.check
+
+_find_free32.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_find_free32.check:
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ pop di
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _find_free32.next
+
+ pop dx
+ pop ax
+
+ jmp _find_free32.done
+
+_find_free32.next:
+
+ pop dx
+ pop ax
+
+ add ax, 1
+ adc dx, 0
+
+ sub si, 1
+ sbb di, 0
+
+ jmp _find_free32.loop
+
+_find_free32.error:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ stc
+ ret
+
+_find_free32.done:
+
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+ clc
ret
;******************************************************************************
mov ax, offset _convert_cluster12
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free12
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat12
mov cs:[_next_cluster], ax
+ mov ax, offset _update_cluster12
+ mov cs:[_update_cluster], ax
+
jmp short _getfattype.done
_getfattype.fat16:
mov ax, offset _convert_cluster16
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free16
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat16
mov cs:[_next_cluster], ax
+
+ mov ax, offset _update_cluster16
+ mov cs:[_update_cluster], ax
_getfattype.done:
clc
ret
+;******************************************************************************
+; @function _update_cluster12
+;******************************************************************************
+global _update_cluster12
+_update_cluster12:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov si, ax
+ mov di, cx
+
+ mov ax, 3
+ mul si
+ shr ax
+
+ push cx
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_update_cluster12.read:
+
+ mov bx, cs:[_fat_seg]
+ mov es, bx
+ xor bx, bx
+
+ mov ax, cs:[_fat_start]
+ mov dx, cs:[_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ push ax
+ push dx
+
+ mov cx, 2
+ call _read_sectors
+
+ pop dx
+ pop ax
+
+ and di, HEX (0FFF)
+
+ pop si
+ popf
+ pop cx
+
+ push ax
+ push dx
+
+ mov cx, es:[si]
+ jnc _update_cluster12.even
+
+ shl di
+ shl di
+ shl di
+ shl di
+ mov ax, di
+
+ and cl, HEX (0F)
+ or al, cl
+
+ jmp _update_cluster12.update
+
+_update_cluster12.even:
+
+ mov ax, di
+
+ and ch, HEX (F0)
+ or ah, ch
+
+_update_cluster12.update:
+
+ mov es:[si], ax
+ pop dx
+ pop ax
+
+ mov cx, cs:[_sectors_per_fat]
+ call _write_sectors
+
+ mov cx, cs:[_sectors_per_fat]
+ call _write_sectors
+
+_update_cluster12.done:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _update_cluster16
+;******************************************************************************
+global _update_cluster16
+_update_cluster16:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov di, cx
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_update_cluster16.read:
+
+ mov bx, cs:[_fat_seg]
+ mov es, bx
+ xor bx, bx
+
+ mov ax, cs:[_fat_start]
+ mov dx, cs:[_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ push ax
+ push dx
+
+ mov cx, 2
+ call _read_sectors
+
+ pop dx
+ pop ax
+ pop si
+ popf
+ pop cx
+
+ push ax
+ push dx
+
+ mov ax, es
+ jnc _update_cluster16.first64
+
+ add ax, HEX (1000)
+
+_update_cluster16.first64:
+
+ push ds
+ mov ds, ax
+ mov [si], di
+ pop ds
+
+ mov cx, 2
+
+ cmp cs:[_sectors_per_fat], cx
+ jae _update_cluster16.update
+
+ mov cx, 1
+
+_update_cluster16.update:
+
+ pop dx
+ pop ax
+
+ push ax
+ push dx
+ call _write_sectors
+
+ pop dx
+ pop ax
+
+ add ax, cs:[_sectors_per_fat]
+ adc dx, 0
+
+ call _write_sectors
+
+_update_cluster16.done:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _update_cluster32
+;******************************************************************************
+global _update_cluster32
+_update_cluster32:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ push bx
+ push cx
+
+ mov di, ax
+
+ and di, cs:[_fat_secmask]
+ mov cx, cs:[_fat_secshift]
+
+_update_cluster32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _update_cluster32.cn_loop
+
+ pop cx
+ pop si
+
+ shl di
+ shl di
+
+ add ax, cs:[_fat_start]
+ adc dx, cs:[_fat_start + 2]
+
+ push ax
+ push dx
+ push cx
+
+ mov bx, cs:[_fat_seg]
+ mov es, bx
+ xor bx, bx
+
+ mov cx, 1
+ call _read_sectors
+
+ and si, HEX (0FFF)
+ pop cx
+
+ mov es:[di], cx
+ mov es:[di + 2], si
+
+_update_cluster32.update:
+
+ pop dx
+ pop ax
+
+ mov si, ax
+ mov di, dx
+
+ mov cx, 1
+ call _write_sectors
+
+ mov ax, cs:[_data_start]
+ mov dx, cs:[_data_start + 2]
+
+ sub ax, cs:[_fat_start]
+ sbb dx, cs:[_fat_start + 2]
+
+ xor ch, ch
+ mov cl, cs:[_number_of_fats]
+
+ div cx
+
+ add ax, si
+ adc dx, di
+
+ mov cx, 1
+ call _write_sectors
+
+_update_cluster32.done:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data area.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
global _convert_cluster
_convert_cluster: dw HEX (0000)
+global _find_free
+_find_free: dw HEX (0000)
+
global _next_cluster
_next_cluster: dw HEX (0000)
+global _update_cluster
+_update_cluster: dw HEX (0000)
+
global _fat_seg
_fat_seg: dw HEX (0000)
global _fat_secshift
_fat_secshift: dw HEX (0000)
+global _info_sector
+_info_sector: dw HEX (0000)
+
global _curr_cluster
_curr_cluster:
xor ch, ch
mov cl, es:[si + 6]
- mov bx, es:[si + 68]
+ mov bx, es:[si + 70]
mov es, bx
xor bx, bx
_getc.is_eof:
- mov ax, es:[si + 64]
- mov dx, es:[si + 66]
+ mov ax, es:[si + 66]
+ mov dx, es:[si + 68]
mov cx, ax
_getc.check:
- cmp dx, es:[si + 62]
+ cmp dx, es:[si + 64]
ja _getc.check2
- cmp dx, es:[si + 62]
+ cmp dx, es:[si + 64]
jne _getc.done
- cmp ax, es:[si + 60]
+ cmp ax, es:[si + 62]
jbe _getc.done
_getc.check2:
- mov ax, es:[si + 60]
- mov dx, es:[si + 62]
+ mov ax, es:[si + 62]
+ mov dx, es:[si + 64]
mov cx, es:[si + 50]
div cx
- cmp word ptr es:[si + 52], 0
+ cmp word ptr es:[si + 54], 0
je _getc.check_offset
- mov word ptr es:[si + 52], 0
+ mov word ptr es:[si + 54], 0
jmp short _getc.read
_getc.check_offset:
_getc.read:
- mov bx, es:[si + 56]
- mov cx, es:[si + 58]
+ mov bx, es:[si + 58]
+ mov cx, es:[si + 60]
call _read_cluster
_getc.loaded:
push es
- mov bx, es:[si + 68]
+ mov bx, es:[si + 70]
mov es, bx
mov bx, dx
mov al, es:[bx]
mov bx, ds
mov es, bx
- stosb
-
- mov bx, es
- mov ds, bx
+ stosb
pop es
+
inc word ptr [bp - 2]
- add word ptr es:[si + 60], 1
- adc word ptr es:[si + 62], 0
+ add word ptr es:[si + 62], 1
+ adc word ptr es:[si + 64], 0
_getc.done:
mov ax, cs:[_clustsize]
stosw
+ mov ax, cs:[_info_sector]
+ stosw
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Store the value 1 as the first word to indicate that we need
;; to be read
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure we're not write-only.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- cmp word ptr es:[si + 54], 1
+ cmp word ptr es:[si + 56], 1
je _read_file.error
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_read_file.loop:
+ and cx, cx
+ jz _read_file.done
+
call _getc
jc _read_file.error
jz _read_file.done
inc word ptr [bp - 2]
- loop _read_file.loop
+
+ dec cx
+ jnz _read_file.loop
_read_file.done:
xor ax, ax
- mov es:[si + 60], ax
mov es:[si + 62], ax
+ mov es:[si + 64], ax
jmp short _seek_file.offset
_seek_file.end:
- mov ax, es:[si + 64]
- mov es:[si + 60], ax
-
mov ax, es:[si + 66]
mov es:[si + 62], ax
+
+ mov ax, es:[si + 68]
+ mov es:[si + 64], ax
_seek_file.offset:
- mov ax, es:[si + 60]
+ mov ax, es:[si + 62]
add ax, cx
- mov di, es:[si + 62]
+ mov di, es:[si + 64]
adc di, dx
cmp di, 0
_seek_file.ptr_ok:
- mov es:[si + 60], ax
- mov es:[si + 62], di
+ mov es:[si + 62], ax
+ mov es:[si + 64], di
_seek_file.done:
mov word ptr es:[si + 52], 1
- mov ax, es:[si + 60]
- mov dx, es:[si + 62]
+ mov ax, es:[si + 62]
+ mov dx, es:[si + 64]
clc
pop di
% define HEX(y) 0x##y
%endif
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
;******************************************************************************
; @function _bcd2int
;******************************************************************************
lodsw
mov cs:[_clustsize], ax
+ lodsw
+ mov cs:[_info_sector], ax
+
pop ds
pop si
mov ax, offset _convert_cluster32
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free32
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat32
mov cs:[_next_cluster], ax
+
+ mov ax, offset _update_cluster32
+ mov cs:[_update_cluster], ax
_get_disk_info.done:
db HEX (30)
dw _int21_30
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Create Directory (mkdir).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (39)
+ dw _int21_39
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set Current Directory.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iret
+;******************************************************************************
+; @function _int21_39
+; @brief Create Directory (mkdir)
+;
+; @in DS:DX -> Pointer to ASCIIZ path name.
+;******************************************************************************
+_int21_39:
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov si, dx
+
+ call _get_disk_info
+ jc _int21_39.error_path
+
+ mov di, si
+
+ call _walk_path
+ jc _int21_39.error_path
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _int21_39.name_error
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag wasn't set then the entry already exists.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _int21_39.error_exists
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we get here then the path is okay and the entry doesn't exist
+ ;; so lets try and create it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, HEX (10)
+
+ call _make_dos_entry
+ jc _int21_39.error
+
+ jmp _int21_39.done
+
+_int21_39.name_error:
+
+ pop dx
+ pop ax
+
+_int21_39.error_exists:
+
+ mov ax, 5
+
+_int21_39.error_path:
+
+ mov ax, 3
+
+_int21_39.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ stc
+ jmp iretc
+
+_int21_39.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ xor ax, ax
+ clc
+
+ jmp iretc
+
;******************************************************************************
; @function _int21_3B
; @brief Set Current Directory
lodsw
mov cs:[_clustsize], ax
+ lodsw
+ mov cs:[_info_sector], ax
+
pop ds
pop si
pop es
mov ax, offset _convert_cluster32
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free32
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat32
mov cs:[_next_cluster], ax
+
+ mov ax, offset _update_cluster32
+ mov cs:[_update_cluster], ax
_int21_3B.get_path:
_int21_3B.get_prev:
- mov byte ptr es:[di - 1], 0
+ cmp di, offset _int21_3B.path
+ je _int21_3B.no_slash2
+
+ cmp byte ptr es:[di - 1], '\\'
+ jne _int21_3B.no_slash2
+ mov byte ptr es:[di - 1], 0
+
+_int21_3B.no_slash2:
+
push si
push ds
- mov ax, es
+ mov ax, cs
mov ds, ax
mov ax, '\\'
pop ds
pop si
+ and ax, ax
+ jnz _int21_3B.got_index
+
+ mov di, offset _int21_3B.path
+ jmp _int21_3B.zero
+
+_int21_3B.got_index:
+
mov di, ax
inc di
+
+_int21_3B.zero:
+
mov byte ptr es:[di], 0
-
jmp _int21_3B.loop
_int21_3B.char_ok:
push si
push ds
push ax
+ push cx
mov ds, ax
xor si, si
lodsw
mov cs:[_clustsize], ax
+ lodsw
+ mov cs:[_info_sector], ax
+
mov bx, cs:[_root_cluster]
mov cx, cs:[_root_cluster + 2]
mov ax, offset _convert_cluster32
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free32
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat32
mov cs:[_next_cluster], ax
+
+ mov ax, offset _update_cluster32
+ mov cs:[_update_cluster], ax
_int21_3F.read:
+ pop cx
pop ax
pop ds
pop si
mov ds, di
xor di, di
- mov ax, [di + 70]
+ mov ax, [di + 72]
cmp ax, dx
jne _int21_4C.next_file
- mov ax, [di + 68]
+ mov ax, [di + 70]
push es
mov es, ax
lodsw
mov cs:[_clustsize], ax
+ lodsw
+ mov cs:[_info_sector], ax
+
pop di
pop si
pop ds
mov ax, offset _convert_cluster32
mov cs:[_convert_cluster], ax
+ mov ax, offset _find_free32
+ mov cs:[_find_free], ax
+
mov ax, offset _nextcluster_fat32
mov cs:[_next_cluster], ax
+
+ mov ax, offset _update_cluster32
+ mov cs:[_update_cluster], ax
_int21_4F.find:
--- /dev/null
+;******************************************************************************
+; @file make.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function _generate_timestamp
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_generate_timestamp:
+
+ push si
+ push cx
+ push dx
+
+ mov ah, HEX (2C)
+ int HEX (21)
+
+ xor ah, ah
+ mov al, dh
+ shr ax
+ mov si, ax
+
+ push cx
+ xor ah, ah
+ mov al, cl
+ mov cl, 5
+ shl ax, cl
+ pop cx
+ add si, ax
+
+ push cx
+ xor ah, ah
+ mov al, ch
+ mov cl, 11
+ shl ax, cl
+ pop cx
+ add si, ax
+
+_generate_timestamp.done:
+
+ mov ax, si
+
+ pop dx
+ pop cx
+ pop si
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function _generate_datestamp
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_generate_datestamp:
+
+ push si
+ push cx
+ push dx
+
+ mov ah, HEX (2A)
+ int HEX (21)
+
+ xor ah, ah
+ mov al, dl
+ mov si, ax
+
+ push cx
+ xor ah, ah
+ mov al, dh
+ mov cl, 5
+ shl ax, cl
+ pop cx
+ add si, ax
+
+ push cx
+ mov ax, cx
+ sub ax, 1980
+ mov cl, 9
+ shl ax, cl
+ pop cx
+ add si, ax
+
+_generate_datestamp.done:
+
+ mov ax, si
+
+ pop dx
+ pop cx
+ pop si
+ ret
+
+
+;******************************************************************************
+; @function _make_dos_entry
+;******************************************************************************
+global _make_dos_entry
+_make_dos_entry:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 48
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov word ptr [bp - 48], ax
+ mov word ptr [bp - 46], dx
+
+ mov word ptr [bp - 36], cx
+ mov word ptr [bp - 32], bx
+
+ mov word ptr [bp - 20], 0
+ mov word ptr [bp - 16], 0
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _make_dos_entry.not_root
+
+ mov ax, cs:[_root_start]
+ mov dx, cs:[_root_start + 2]
+
+_make_dos_entry.got_root:
+
+ mov word ptr [bp - 30], 1
+ mov word ptr [bp - 24], 1
+
+ mov word ptr [bp - 28], ax
+ mov word ptr [bp - 26], dx
+
+ mov ax, 32
+ xor dx, dx
+
+ mov cx, cs:[_root_entries]
+ mul cx
+
+ mov cx, cs:[_bytes_per_sector]
+ div cx
+
+ xchg cx, ax
+ dec cx
+
+ xor dx, dx
+ mov word ptr [bp - 22], cx
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _make_dos_entry.read
+
+_make_dos_entry.not_root:
+
+ mov word ptr [bp - 30], 0
+ mov word ptr [bp - 24], 1
+
+ mov word ptr [bp - 28], ax
+ mov word ptr [bp - 26], dx
+
+ call cs:[_convert_cluster]
+ jc _make_dos_entry.error
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ xor ch, ch
+ mov cl, cs:[_sectors_per_cluster]
+
+ mov word ptr [bp - 34], cx
+ dec word ptr [bp - 34]
+
+_make_dos_entry.read:
+
+ mov bx, cs:[_disk_scratch]
+ mov es, bx
+ xor bx, bx
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ mov cx, word ptr [bp - 24]
+ call _read_sectors
+
+ mov ax, cs:[_bytes_per_sector]
+ xor dx, dx
+
+ mov cx, 32
+ div cx
+ xchg cx, ax
+
+ xor di, di
+
+_make_dos_entry.make:
+
+ cmp byte ptr es:[di], 0
+ je _make_dos_entry.found_free
+
+ cmp byte ptr es:[di], HEX (E5)
+ je _make_dos_entry.found_free
+
+_make_dos_entry.advance:
+
+ add di, 32
+ loop _make_dos_entry.make
+
+ cmp word ptr [bp - 30], 1
+ jne _make_dos_entry.check
+
+ mov ax, word ptr [bp - 22]
+
+ and ax, ax
+ jz _make_dos_entry.error
+
+ dec ax
+ mov word ptr [bp - 22], ax
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ add ax, word ptr [bp - 24]
+ adc dx, 0
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _make_dos_entry.read
+
+_make_dos_entry.check:
+
+ mov ax, word ptr [bp - 34]
+
+ and ax, ax
+ jz _make_dos_entry.next_clust
+
+ dec ax
+ mov word ptr [bp - 34], ax
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ add ax, word ptr [bp - 24]
+ adc dx, 0
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _make_dos_entry.read
+
+_make_dos_entry.next_clust:
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jmp _make_dos_entry.not_root
+
+_make_dos_entry.found_free:
+
+ call cs:[_find_free]
+ jc _make_dos_entry.error
+
+_make_dos_entry.got_clust:
+
+ mov word ptr [bp - 38], ax
+ mov word ptr [bp - 40], dx
+
+ call _generate_datestamp
+ mov word ptr [bp - 42], ax
+
+ call _generate_timestamp
+ mov word ptr [bp - 44], ax
+
+ push si
+ push ds
+
+ mov si, cs
+ mov ds, si
+
+ mov si, word ptr [bp - 32]
+
+ mov cx, 11
+ rep movsb
+
+ pop ds
+ pop si
+
+ mov ax, word ptr [bp - 36]
+ stosb
+
+ xor ax, ax
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 40]
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 38]
+ stosw
+
+ xor ax, ax
+ stosw
+ stosw
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ mov cx, word ptr [bp - 24]
+ call _write_sectors
+
+ mov ax, word ptr [bp - 38]
+ mov dx, word ptr [bp - 40]
+
+ mov bx, HEX (FFFF)
+ mov cx, HEX (FFF8)
+
+ call cs:[_update_cluster]
+
+ mov ax, cs:[_disk_scratch]
+ mov es, ax
+
+ xor al, al
+ xor di, di
+
+ mov cx, cs:[_clustsize]
+ rep stosb
+
+ xor di, di
+
+ mov al, '.'
+ stosb
+
+ mov al, ' '
+
+ mov cx, 10
+ rep stosb
+
+ mov al, HEX (10)
+ stosb
+
+ xor ax, ax
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 40]
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 38]
+ stosw
+
+ xor ax, ax
+ stosw
+ stosw
+
+ mov al, '.'
+
+ mov cx, 2
+ rep stosb
+
+ mov al, ' '
+
+ mov cx, 9
+ rep stosb
+
+ mov al, HEX (10)
+ stosb
+
+ xor ax, ax
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 46]
+ stosw
+
+ mov ax, word ptr [bp - 44]
+ stosw
+
+ mov ax, word ptr [bp - 42]
+ stosw
+
+ mov ax, word ptr [bp - 48]
+ stosw
+
+ xor ax, ax
+ stosw
+ stosw
+
+ mov ax, word ptr [bp - 38]
+ mov dx, word ptr [bp - 40]
+ call cs:[_convert_cluster]
+
+ xor ch, ch
+ mov cl, cs:[_sectors_per_cluster]
+
+ xor bx, bx
+ call _write_sectors
+
+ jmp _make_dos_entry.done
+
+_make_dos_entry.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 48
+ pop bp
+
+ mov ax, 5
+ stc
+
+ ret
+
+_make_dos_entry.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 48
+ pop bp
+
+ xor ax, ax
+ clc
+
+ ret
call _mangle_dos_name
jc _walk_path.not_found
+ cmp dx, cs:[_root_cluster + 2]
+ jne _walk_path.search
+
+ cmp ax, cs:[_root_cluster]
+ jne _walk_path.search
+
+_walk_path.compare_curr:
+
+ push ax
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ push bx
+
+ mov ax, offset _curr_check
+ push ax
+
+ call _strcmp
+ add sp, 4
+
+ and ax, ax
+ pop ds
+ pop ax
+ jz _walk_path.check
+
+_walk_path.compare_prev:
+
+ push ax
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ push bx
+
+ mov ax, offset _prev_check
+ push ax
+
+ call _strcmp
+ add sp, 4
+
+ and ax, ax
+ pop ds
+ pop ax
+ jz _walk_path.check
+
+_walk_path.search:
+
call _search_dos_dir
jc _walk_path.not_found
mov ax, es:[bx + 0]
mov dx, es:[bx + 2]
-
mov cl, es:[bx + 8]
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _walk_path.got_clust
+
+ mov ax, cs:[_root_cluster]
+ mov dx, cs:[_root_cluster + 2]
+
+_walk_path.got_clust:
+
pop es
pop bx
test cl, HEX (10)
jz _walk_path.not_found
-
+
+_walk_path.check:
+
cmp byte ptr [di - 1], '\\'
jne _walk_path.done
clc
ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_curr_check: db ". ", HEX (00)
+_prev_check: db ".. ", HEX (00)