From: Robert Pengelly Date: Mon, 5 Aug 2024 15:36:54 +0000 (+0100) Subject: Write to console X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=8717e916c0783613de67f84a8a2c74523b704a4e;p=chimaera.git Write to console --- diff --git a/build/chimaera.img b/build/chimaera.img index 759b619..c5dc8e7 100644 Binary files a/build/chimaera.img and b/build/chimaera.img differ diff --git a/build/chimaera.vhd b/build/chimaera.vhd index f3a04cb..dcb9b66 100644 Binary files a/build/chimaera.vhd and b/build/chimaera.vhd differ diff --git a/src/Makefile.unix b/src/Makefile.unix index ad0e40e..7c0b071 100644 --- a/src/Makefile.unix +++ b/src/Makefile.unix @@ -46,6 +46,7 @@ chimaera.vhd: all 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 diff --git a/src/apps/hello/Makefile.unix b/src/apps/hello/Makefile.unix index 07d771f..14cc203 100644 --- a/src/apps/hello/Makefile.unix +++ b/src/apps/hello/Makefile.unix @@ -18,4 +18,4 @@ hello.com: ../../lib/crt/crt0.o crlf.o hello.o writechr.o writehex.o writestr.o ../../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 $@ $< diff --git a/src/apps/hello/hello.asm b/src/apps/hello/hello.asm index cea0de6..ff2b84e 100644 --- a/src/apps/hello/hello.asm +++ b/src/apps/hello/hello.asm @@ -5,6 +5,11 @@ % define HEX(y) 0x##y %endif +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Include stdio.inc. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%include + ;****************************************************************************** ; @function _free ;****************************************************************************** @@ -12,10 +17,10 @@ global _main _main: mov bx, offset msg_hello - call _writestr - call _crlf - + +; call _crlf +; ; mov ah, HEX (08) ; int HEX (21) ; @@ -30,28 +35,80 @@ _main: ; ; 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 @@ -59,7 +116,3 @@ _main: ;; 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) diff --git a/src/kernel/int21.asm b/src/kernel/int21.asm index cb56f04..d9bf5f0 100644 --- a/src/kernel/int21.asm +++ b/src/kernel/int21.asm @@ -860,6 +860,12 @@ _int21_dispatch.list: db HEX (3F) dw _int21_3F + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Write to File or Device Using Handle. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + db HEX (40) + dw _int21_40 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Delete/Unlink File. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2518,6 +2524,237 @@ _int21_3F.done: 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 diff --git a/src/lib/crt/include/stdio.inc b/src/lib/crt/include/stdio.inc index 165b10a..701b5e3 100644 --- a/src/lib/crt/include/stdio.inc +++ b/src/lib/crt/include/stdio.inc @@ -10,4 +10,11 @@ %define __SEOF 0x0020 %define __SAPP 0x0100 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Console file pointers. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%define stdin 0x0001 +%define stdout 0x0002 +%define stderr 0x0003 + %endif ; _STDIO_INC diff --git a/src/lib/crt/stdio/fputc.asm b/src/lib/crt/stdio/fputc.asm new file mode 100644 index 0000000..401b2a8 --- /dev/null +++ b/src/lib/crt/stdio/fputc.asm @@ -0,0 +1,158 @@ +;****************************************************************************** +; @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) diff --git a/src/lib/crt/stdio/fwrite.asm b/src/lib/crt/stdio/fwrite.asm new file mode 100644 index 0000000..3d7f92d --- /dev/null +++ b/src/lib/crt/stdio/fwrite.asm @@ -0,0 +1,225 @@ +;****************************************************************************** +; @file fread.asm +;****************************************************************************** +%ifndef HEX +% define HEX(y) 0x##y +%endif + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Includes. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%include + +;****************************************************************************** +; @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