utils/dosfstools/mcopy --arca --offset 17 -i $@ boot/freeldr/core/freeldr.sys ::
utils/dosfstools/mcopy --arca --offset 17 -i $@ kernel/kernel.sys ::
utils/dosfstools/mcopy --arca --offset 17 -i $@ apps/pcomm/pcomm.com ::command.com
+# utils/dosfstools/mcopy --arca --offset 17 -i $@ apps/hello/hello.com ::hello.com
run-qemu: chimaera.img chimaera.vhd
# qemu-system-i386 -cpu 486 -drive file="chimaera.img",format=raw,if=floppy,index=0 -m 4M
../../utils/binutils/slink --oformat msdos -o $@ $^
%.o: %.asm
- ../../utils/binutils/sasm -l $*.lst -o $@ $<
+ ../../utils/binutils/sasm -I$(SRCDIR)/../../lib/crt/include -l $*.lst -o $@ $<
% define HEX(y) 0x##y
%endif
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include stdio.inc.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <stdio.inc>
+
;******************************************************************************
; @function _free
;******************************************************************************
_main:
mov bx, offset msg_hello
-
call _writestr
- call _crlf
-
+
+; call _crlf
+;
; mov ah, HEX (08)
; int HEX (21)
;
;
; 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 (39)
- mov dx, offset _dir_exist
- int HEX (21)
-
- call _writehex
- call _crlf
-
- mov ah, HEX (39)
- mov dx, offset _dir_file
- int HEX (21)
-
- call _writehex
- call _crlf
-
+;
+; mov ah, HEX (39)
+; mov dx, offset _dir_non_exist
+; int HEX (21)
+;
+; call _writehex
+; call _crlf
+;
+; mov ah, HEX (39)
+; mov dx, offset _dir_exist
+; int HEX (21)
+;
+; call _writehex
+; call _crlf
+;
+; mov ah, HEX (39)
+; mov dx, offset _dir_file
+; int HEX (21)
+;
+; call _writehex
+; call _crlf
+;
+; mov si, offset msg_hello
+; xor ax, ax
+;
+; mov bx, stdout
+;
+;.loop:
+;
+; lodsb
+;
+; and al, al
+; jz .exit
+;
+; push bx
+; push ax
+;
+; call _fputc
+; add sp, 4
+;
+; jmp .loop
+;
+; mov bx, 1
+; mov cx, 15
+; mov dx, offset msg_hello
+;
+; mov ax, stdout
+; push ax
+;
+; push cx
+; push bx
+; push dx
+;
+; call _fwrite
+; add sp, 8
+;
+; call _writehex
+; call _crlf
+;
+; mov ax, stdout
+; push ax
+;
+; push bx
+; push cx
+; push dx
+;
+; call _fwrite
+; add sp, 8
+;
+; call _writehex
+; call _crlf
+
+.exit:
+
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)
db HEX (3F)
dw _int21_3F
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Write to File or Device Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (40)
+ dw _int21_40
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Delete/Unlink File.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jmp iretc
+;******************************************************************************
+; @function _int21_40
+; @brief Write to File or Device Using Handle
+;
+; @in BX -> File handle..
+; @in CX -> Number of bytes to write.
+; @in DS:DX -> Pointer to write buffer.
+;
+; @out AX -> Number of written. Error code if CF is set.
+;******************************************************************************
+_int21_40:
+
+ push bp
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First, lets check if we're writing to the console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 2
+ ja _int21_40.check
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If stdin was passed then we can't write to it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _int21_40.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Otherwise, lets write the bytes.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, dx
+
+_int21_40.console_loop:
+
+ and cx, cx
+ jz _int21_40.done
+
+ lodsb
+ call _writechr
+
+ dec cx
+ jmp _int21_40.console_loop
+
+_int21_40.check:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _int21_40.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _int21_40.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the correct file offset by subtracting 3.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub bx, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset into our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push cx
+
+ mov ax, bx
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+ pop cx
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Intialize the es register with address of our vector entries
+ ;; and zero out bx for the counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_vec_files + 0]
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the vector entry is zero then the file handle is invalid.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[bx], 0
+ je _int21_40.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-initialize the extra segment but this time with the address
+ ;; of the vector entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+_int21_40.copy:
+
+ push si
+ push ds
+ push ax
+ push cx
+
+ mov ds, ax
+ xor si, si
+
+ lodsw
+ mov cs:[_curr_cluster], ax
+
+ lodsw
+ mov cs:[_curr_cluster + 2], ax
+
+ mov di, offset _fat_bpb
+ mov ax, cs
+ mov es, ax
+
+ mov cx, 25
+ rep movsb
+
+ lodsb
+ mov cs:[_drive_no], al
+
+ lodsw
+ mov cs:[_root_cluster], ax
+
+ lodsw
+ mov cs:[_root_cluster + 2], ax
+
+ lodsw
+ mov cs:[_fat_start], ax
+
+ lodsw
+ mov cs:[_fat_start + 2], ax
+
+ lodsw
+ mov cs:[_root_start], ax
+
+ lodsw
+ mov cs:[_root_start + 2], ax
+
+ lodsw
+ mov cs:[_data_start], ax
+
+ lodsw
+ mov cs:[_data_start + 2], ax
+
+ lodsw
+ mov cs:[_fat_secmask], ax
+
+ lodsw
+ mov cs:[_fat_secshift], ax
+
+ lodsw
+ mov cs:[_clustsize], ax
+
+ lodsw
+ mov cs:[_info_sector], ax
+
+ mov bx, cs:[_root_cluster]
+ mov cx, cs:[_root_cluster + 2]
+
+ or bx, cx
+
+ and bx, bx
+ jnz _int21_40.fat32
+
+ call _getfattype
+ jmp _int21_40.write
+
+_int21_40.fat32:
+
+ 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_40.write:
+
+ pop cx
+ pop ax
+ pop ds
+ pop si
+
+ mov es, ax
+
+_int21_40.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ mov ax, 6
+ stc
+
+ jmp iretc
+
+_int21_40.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ mov ax, cx
+ clc
+
+ jmp iretc
+
;******************************************************************************
; @function _int21_42
; @brief Move File Pointer Using Handle
%define __SEOF 0x0020
%define __SAPP 0x0100
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Console file pointers.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define stdin 0x0001
+%define stdout 0x0002
+%define stderr 0x0003
+
%endif ; _STDIO_INC
--- /dev/null
+;******************************************************************************
+; @file fputc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fputc
+;******************************************************************************
+global _fputc
+_fputc:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the character off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ mov [_buffer], al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the file stream off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 6]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a file stream.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _fputc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're 2 or 3 then we're writing to the console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 2
+ jb _fputc.error
+
+ cmp bx, 3
+ ja _fputc.check
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement the value to get the correct file number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Write the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (40)
+ mov cx, 1
+ mov dx, offset _buffer
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was a carry then we failed.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _fputc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Otherwise we succeeded.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _fputc.done
+
+_fputc.check:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, bx
+ xor di, di
+
+ mov bx, es:[di + 0]
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Write the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (40)
+ mov cx, 1
+ mov dx, offset _buffer
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was a carry then we failed.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _fputc.error
+
+_fputc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fputc.error:
+
+ xor ax, -1
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_buffer: db 2 dup (0)
--- /dev/null
+;******************************************************************************
+; @file fread.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _fwrite
+;******************************************************************************
+global _fwrite
+_fwrite:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the reserved stack value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 2], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the file handle off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 10]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _fwrite.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're 2 or 3 then we're writing to the console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 2
+ jb _fwrite.error
+
+ cmp bx, 3
+ ja _fwrite.check
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement the value to get the correct file number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the amount of bytes to read.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 8]
+ xor dx, dx
+
+ mov cx, word ptr [bp + 6]
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the number of bytes are zero then we're done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and cx, cx
+ jz _fwrite.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the number of bytes into the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the dx register with the address of the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Write # no of bytes from the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (40)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was a carry then we failed.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _fwrite.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Otherwise we succeeded.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _fwrite.check2
+
+_fwrite.check:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the amount of bytes to read.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 8]
+ xor dx, dx
+
+ mov cx, word ptr [bp + 6]
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the number of bytes are zero then we're done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and cx, cx
+ jz _fwrite.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, bx
+ xor di, di
+
+ mov bx, es:[di + 0]
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the number of bytes into the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the dx register with the address of the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Write # no of bytes from the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (40)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If there was a carry then we failed.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _fwrite.error
+
+_fwrite.check2:
+
+ cmp word ptr [bp + 8], 1
+ jne _fwrite.check3
+
+ cmp ax, word ptr [bp + 6]
+ jne _fwrite.zero
+
+ mov ax, 1
+ jmp _fwrite.done
+
+_fwrite.check3:
+
+ cmp word ptr [bp - 6], 1
+ je _fwrite.done
+
+ xor dx, dx
+
+ mov cx, word ptr [bp + 6]
+ div cx
+
+ jmp _fwrite.done
+
+_fwrite.zero:
+
+ xor ax, ax
+
+_fwrite.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fwrite.error:
+
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret