--- /dev/null
+[submodule "src/utils/dosfstools"]
+ path = src/utils/dosfstools
+ url = https://git.candlhat.org/dosfstools.git
+[submodule "src/utils/parted"]
+ path = src/utils/parted
+ url = https://git.candlhat.org/parted.git
+[submodule "src/utils/binutils/ar"]
+ path = src/utils/binutils/ar
+ url = https://git.candlhat.org/sar.git
+[submodule "src/utils/binutils/as"]
+ path = src/utils/binutils/as
+ url = https://git.candlhat.org/sasm.git
+[submodule "src/utils/binutils/ld"]
+ path = src/utils/binutils/ld
+ url = https://git.candlhat.org/slink.git
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+MAKE += -r --quiet --no-print-directory
+MAKEFLAGS += -r --quiet --no-print-directory
+
+OBJDIR ?= $(CURDIR)/build
+SRCDIR ?= $(CURDIR)/src
+
+PRIVATE-TARGETS := spotless
+MAKECMDGOALS ?= all
+
+.PHONY: $(filter-out $(PRIVATE-TARGETS), $(MAKECMDGOALS))
+$(filter-out $(PRIVATE-TARGETS), $(MAKECMDGOALS)):
+ if [ ! -d "$(OBJDIR)" ]; then mkdir -p "$(OBJDIR)"; fi
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/Makefile.unix" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)" $(MAKECMDGOALS)
+
+spotless:
+ if [ -d "$(OBJDIR)" ]; then rm -rf "$(OBJDIR)"; fi
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+MAKE += -r --quiet --no-print-directory
+MAKEFLAGS += -r --quiet --no-print-directory
+
+OBJDIR ?= $(CURDIR)/build
+SRCDIR ?= $(CURDIR)/src
+
+PRIVATE-TARGETS := spotless
+MAKECMDGOALS ?= all
+
+.PHONY: $(filter-out $(PRIVATE-TARGETS), $(MAKECMDGOALS))
+$(filter-out $(PRIVATE-TARGETS), $(MAKECMDGOALS)):
+ if not exist "$(OBJDIR)" ( mkdir "$(OBJDIR)" )
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/Makefile.w32" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)" $(MAKECMDGOALS)
+
+spotless:
+ if exist "$(OBJDIR)" ( rmdir /q /s "$(OBJDIR)" )
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := utils boot lib kernel apps
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for d in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$d" ]; then mkdir -p "$(OBJDIR)/$$d"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" all; \
+ done
+
+clean:
+ for d in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$d" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" clean; \
+ fi; \
+ done
+ if [ -f freeldr.cfg ]; then rm -rf freeldr.cfg; fi
+
+chimaera.img: all
+ if [ -f $@ ]; then rm -rf $@; fi
+
+ utils/dosfstools/mkdosfs --boot boot/freeldr/bootsect/fat12.bin --sectors 720 -F 12 -n "CHIMAERA OS" $@
+ utils/dosfstools/mmd -i $@ boot boot/freeldr
+
+ utils/dosfstools/mcopy -i $@ $(SRCDIR)/boot/freeldr/freeldr.cfg ::/boot/freeldr/
+ utils/dosfstools/mcopy -i $@ boot/freeldr/core/freeldr.sys ::
+ utils/dosfstools/mcopy -i $@ kernel/kernel.sys ::
+ utils/dosfstools/mcopy -i $@ apps/pcomm/pcomm.com ::command.com
+
+chimaera.vhd: all
+ if [ -f $@ ]; then rm -rf $@; fi
+
+ 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/
+ 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
+
+run-qemu: chimaera.img chimaera.vhd
+ qemu-system-i386 -cpu 486 -drive file="chimaera.img",format=raw,if=floppy,index=0 -m 4M
+ qemu-system-i386 -cpu 486 -drive file="chimaera.vhd",format=raw,if=ide,index=0 -m 4M
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := utils boot lib kernel apps
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%d in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%d" ( mkdir "$(OBJDIR)/%%d" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" all \
+ )
+
+clean:
+ for %%d in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%d" ( \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" clean \
+ ) \
+ )
+ if exist freeldr.cfg ( del /q freeldr.cfg )
+
+chimaera.img: all
+ if exist $@ ( del /q $@ )
+
+ utils/dosfstools/mkdosfs --boot boot/freeldr/bootsect/fat12.bin --sectors 320 -F 12 -n "CHIMAERA OS" $@
+ utils/dosfstools/mmd -i $@ boot boot/freeldr
+
+ utils/dosfstools/mcopy -i $@ $(SRCDIR)/boot/freeldr/freeldr.cfg ::/boot/freeldr/
+ utils/dosfstools/mcopy -i $@ boot/freeldr/core/freeldr.sys ::
+ utils/dosfstools/mcopy -i $@ kernel/kernel.sys ::
+
+chimaera.vhd: all
+ if exist $@ ( del /q $@ )
+
+ utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,11,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
+
+ utils/dosfstools/mcopy --arca --offset 17 -i $@ $(SRCDIR)/boot/freeldr/freeldr.cfg ::/boot/freeldr/
+ utils/dosfstools/mcopy --arca --offset 17 -i $@ boot/freeldr/core/freeldr.sys ::
+ utils/dosfstools/mcopy --arca --offset 17 -i $@ kernel/kernel.sys ::
+
+run-qemu: chimaera.img chimaera.vhd
+ qemu-system-i386 -cpu 486 -drive file="chimaera.img",format=raw,if=floppy,index=0 -m 4M
+ qemu-system-i386 -cpu 486 -drive file="chimaera.vhd",format=raw,if=ide,index=0 -m 4M
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := hello pcomm
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for t in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$t" ]; then mkdir -p "$(OBJDIR)/$$t"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" all; \
+ done
+
+clean:
+ for t in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$t" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" clean; \
+ fi; \
+ done
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := hello pcomm
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%t in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%t" ( mkdir "$(OBJDIR)/%%t" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" all \
+ )
+
+clean:
+ for %%t in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%t" ( \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" clean \
+ ) \
+ )
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+#all: hello.com test.asm
+all: hello.com
+
+clean:
+ for f in *.o; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ for f in *.lst; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ if [ -f hello.com ]; then rm -rf hello.com; fi
+
+hello.com: ../../lib/crt/crt0.o crlf.o hello.o writechr.o writehex.o writestr.o ../../lib/crt/libc.a
+ ../../utils/binutils/slink --oformat msdos -o $@ $^
+
+%.o: %.asm
+ ../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: hello.com
+
+clean:
+ for %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ for %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
+ if exist hello.com ( del /q hello.com )
+
+hello.com: ../../lib/crt/crt0.o crlf.o hello.o writechr.o writehex.o writestr.o ../../lib/crt/libc.a
+ ../../utils/binutils/slink --oformat msdos -o $@ $^
+
+%.o: %.asm
+ ../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file crlf.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _crlf
+;******************************************************************************
+global _crlf
+_crlf:
+
+ push ax
+ push bx
+ push dx
+ push bp
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (0A)
+ int HEX (21)
+
+ pop bp
+ pop dx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file hello.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _free
+;******************************************************************************
+global _main
+_main:
+
+ mov bx, offset msg_hello
+
+ call _writestr
+ call _crlf
+
+ 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)
+
+ xor ax, ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+msg_hello: db "Hello, world!", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file hello.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _free
+;******************************************************************************
+global _main
+_main:
+
+ mov bx, offset msg_hello
+
+ call _writestr
+ call _crlf
+
+ mov bx, offset msg_malloc1
+ call _writestr
+
+ mov ax, 64
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ call _writehex
+ call _crlf
+
+ mov bx, offset msg_free1
+ call _writestr
+
+ call _writehex
+ call _crlf
+
+ push ax
+
+ call _free
+ add sp, 2
+
+ mov bx, offset msg_malloc2
+ call _writestr
+
+ mov ax, 64
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ call _writehex
+ call _crlf
+
+ mov bx, offset msg_free2
+ call _writestr
+
+ call _writehex
+ call _crlf
+
+ push ax
+
+ call _free
+ add sp, 2
+
+ mov di, offset fn_config
+ push di
+
+ call _fopen
+ add sp, 2
+
+ call _writehex
+ call _crlf
+
+ mov di, offset fn_config
+ push di
+
+ call _fopen
+ add sp, 2
+
+ call _writehex
+ call _crlf
+
+ xor ax, ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+msg_hello: db "Hello, world!", HEX (0D), HEX (0A), HEX (00)
+fn_config: db "test.txt", HEX (00)
+
+msg_malloc1: db "First malloc: ", HEX (00)
+msg_free1: db "First free: ", HEX (00)
+
+msg_malloc2: db "Second malloc: ", HEX (00)
+msg_free2: db "Second free: ", HEX (00)
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file hello.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _main
+;******************************************************************************
+global _main
+_main:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 8
+
+; push es
+; push ds
+; push bx
+; push cx
+; push si
+;
+; mov ax, cs:[HEX (16)]
+;
+; and ax, ax
+; jnz yay
+;
+; xor ax, ax
+; int 0x19
+;
+;yay:
+;
+; mov ax, cs
+; call _writehex
+; call _crlf
+;
+; mov ax, ds
+; call _writehex
+; call _crlf
+;
+; mov ax, es
+; call _writehex
+; call _crlf
+
+; mov bx, offset msg_hello
+;
+; call _writestr
+; call _crlf
+
+; mov ax, HEX (0006)
+; int HEX (10)
+;
+; xor ax, ax
+; xor dx, dx
+;
+; mov cx, 320
+; mov si, 1
+;
+;test_loop:
+;
+; push si
+; push dx
+; push ax
+;
+; call _gdi_point
+; add sp, 6
+;
+; add ax, 1
+; add dx, 1
+;
+; loop test_loop
+;
+; xor ax, ax
+; int HEX (16)
+
+; mov ax, HEX (0006)
+; int HEX (10)
+;
+; xor ax, ax
+; xor dx, dx
+;
+; mov cx, 50
+; mov si, 1
+;
+;test_loop:
+;
+; push si
+; push dx
+; push ax
+;
+; call _gdi_point
+; add sp, 6
+;
+; add ax, 1
+; add dx, 1
+;
+; loop test_loop
+;
+; xor ax, ax
+; int HEX (16)
+
+ mov ax, HEX (0004)
+ int HEX (10)
+
+; mov ax, HEX (0B00)
+; mov bx, HEX (0001)
+; int HEX (10)
+
+ mov ax, cs
+ mov ds, ax
+ mov si, offset _cursor
+
+ lodsw
+ mov word ptr [bp - 8], ax
+
+ lodsw
+ mov word ptr [bp - 6], ax
+
+ mov ax, word ptr [bp - 8]
+ xor dx, dx
+
+ mul word ptr [bp - 6]
+ mov cx, ax
+
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 2], 0
+
+draw_loop:
+
+ and cx, cx
+ jz draw_done
+
+ mov ax, word ptr [bp - 2]
+
+ and ax, ax
+ jz draw_pixel
+
+ and ax, word ptr [bp - 8]
+ jz draw_pixel
+
+ mov word ptr [bp - 2], 0
+ inc word ptr [bp - 4]
+
+draw_pixel:
+
+ lodsw
+
+ cmp ah, 127
+ jae draw_next
+
+draw_fg:
+
+ xor ah, ah
+ push ax
+
+ push word ptr [bp - 4]
+ push word ptr [bp - 2]
+
+ call _gdi_point
+ add sp, 6
+
+draw_next:
+
+ inc word ptr [bp - 2]
+
+ dec cx
+ jmp draw_loop
+
+draw_done:
+
+ xor ax, ax
+ int HEX (16)
+
+ mov ax, HEX (0003)
+ int HEX (10)
+
+; mov si, word ptr [bp + 6]
+; mov bx, [si + 0]
+;
+; and bx, bx
+; jz after_name
+;
+; call _writestr
+; call _crlf
+
+after_name:
+
+; mov ah, HEX (3C)
+; mov cx, HEX (20)
+; mov dx, offset fn_config
+; int HEX (21)
+; jc .error
+;
+; mov bx, ax
+;
+; mov ah, HEX (40)
+; mov cx, 8
+; mov dx, offset msg_hello
+; int HEX (21)
+; jc .error
+;
+; mov ah, HEX (3E)
+; int HEX (21)
+; jc .error
+;
+; mov ax, offset fn_flags
+; push ax
+;
+; mov ax, offset fn_config
+; push ax
+;
+; call _fopen
+; add sp, 4
+;
+; and ax, ax
+; jz .error
+;
+; push ax
+;
+; call _fclose
+; add sp, 2
+;
+; and ax, ax
+; jnz .error
+;
+; mov ax, offset fn_flags
+; push ax
+;
+; mov ax, offset fn_config
+; push ax
+;
+; call _fopen
+; add sp, 4
+;
+; mov ah, HEX (0A)
+; mov dx, offset scratch_sz
+; int HEX (21)
+;
+; mov ax, cs:[HEX (2C)]
+;
+; and ax, ax
+; jz exit
+;
+; call _writehex
+; call _crlf
+;
+; xor ax, ax
+; int 0x16
+;
+; mov ds, ax
+; xor bx, bx
+;
+; xor cx, cx
+;
+;again:
+;
+; push bx
+;
+; call _strlen
+; add sp, 2
+;
+; and ax, ax
+; jz done
+;
+; add ax, 1
+; add bx, ax
+;
+; jmp again
+;
+;done:
+;
+; mov cx, bx
+; xor si, si
+;
+;print:
+;
+; and cx, cx
+; jz exit
+;
+; lodsb
+;
+; call _writechr
+; dec cx
+;
+; jmp print
+;
+;exit:
+;
+; pop si
+; pop cx
+; pop bx
+; pop ds
+; pop es
+; pop bp
+
+ xor ax, ax
+
+ add sp, 8
+ clc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _gdi_point
+;******************************************************************************
+_gdi_point:
+
+ push bp
+ mov bp, sp
+
+ push ax
+ push bx
+ push cx
+ push di
+ push es
+
+ mov ax, HEX (B800)
+ mov es, ax
+
+ mov bx, word ptr [bp + 6]
+ mov cx, word ptr [bp + 4]
+
+ mov ah, HEX (0F)
+ int HEX (10)
+
+ cmp al, HEX (04)
+ jb _gdi_point.done
+
+ cmp al, HEX (05)
+ jna _gdi_point.4ppb
+
+ cmp al, HEX (06)
+ jne _gdi_point.done
+
+_gdi_point.8ppb:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Offset = 4 * 8192 if y odd.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+ shr bx
+ rcr di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add 4 * 80 * (y / 2) to offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xchg bh, bl
+ add di, bx
+ shr bx
+ shr bx
+ add di, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide x by 2 and add it to the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cx
+ shr ax
+ add di, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Compute x mod 8 and divide di by 4.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ shr di
+ shr di
+ and cl, 7
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Compute color and mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, byte ptr [bp + 8]
+ mov al, HEX (7F)
+
+ ror al, cl
+ inc cl
+ ror ah, cl
+
+ jmp _gdi_point.draw_pixels
+
+_gdi_point.4ppb:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Offset = 4 * 8192 if y odd.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+ shr bx
+ rcr di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add 4 * 80 * (y / 2) to offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xchg bh, bl
+ add di, bx
+ shr bx
+ shr bx
+ add di, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Compute x mod 4 and divide di by 4.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, cx
+ shr di
+ shr di
+ and cl, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Compute color and mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, byte ptr [bp + 8]
+ mov al, HEX (3F)
+
+ shl cl
+ ror al, cl
+
+ inc cl
+ inc cl
+ ror ah, cl
+
+_gdi_point.draw_pixels:
+
+ and al, es:[di]
+ or al, ah
+ stosb
+
+_gdi_point.done:
+
+ pop es
+ pop di
+ pop cx
+ pop bx
+ pop ax
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_cursor:
+
+ dw HEX (0008), HEX (0008)
+
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (03), HEX (00)
+ db HEX (03), HEX (00)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+ db HEX (00), HEX (7f)
+
+;msg_hello: db "Hello, world!", HEX (00)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; int21/ah=0A variables.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;scratch_sz: db 32
+;scratch_len: db 0
+;
+;scratch: db 34 dup (0)
--- /dev/null
+/******************************************************************************
+ * @file hello.c
+ *****************************************************************************/
+int main (int argc, char **argv) {
+ return 0;
+}
--- /dev/null
+;******************************************************************************
+; @file writechr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function writechr
+;******************************************************************************
+global _writechr
+_writechr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push bp ; Some BIOSes destroy BP when the screen scrolls
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file writehex.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+global _writehex
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, cs:[_writehex_num_digits]
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _writehex_num_digits
+_writehex_num_digits: dw HEX (0004)
--- /dev/null
+;******************************************************************************
+; @file writestr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writestr
+;******************************************************************************
+global _writestr
+_writestr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push si
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize si with bx
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump over our printing code to get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _writestr.next
+
+_writestr.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 02h - MSDOS print chareacter
+ ;; DL - Character to print
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+_writestr.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _writestr.print
+
+_writestr.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop si
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: cmdhash.gen ver.inc pcomm.com
+
+clean:
+ for f in *.o; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ for f in *.lst; do if [ -f $$f ]; then rm -rf $$f; fi; done
+
+ if [ -f cmdhash.gen ]; then rm -rf cmdhash.gen; fi
+ if [ -f pcomm.com ]; then rm -rf pcomm.com; fi
+ if [ -f ver.inc ]; then rm -rf ver.inc; fi
+
+ifeq ($(OS), Windows_NT)
+cmdhash.gen: commands genhash.exe
+ ./genhash.exe < $< > $@
+ rm -rf genhash.exe
+
+ver.inc: genver.exe
+ ./genver.exe > $@
+ rm -rf genver.exe
+
+genhash.exe: genhash.c
+ gcc -o $@ $^
+
+genver.exe: genver.c
+ gcc -o $@ $^
+else
+cmdhash.gen: commands genhash
+ ./genhash < $< > $@
+ rm -rf genhash
+
+ver.inc: genver
+ ./genver > $@
+ rm -rf genver
+
+genhash: genhash.c
+ gcc -o $@ $^
+
+genver: genver.c
+ gcc -o $@ $^
+endif
+
+pcomm.com: ../../lib/crt/crt0.o cbreak.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
+ ../../utils/binutils/slink --oformat msdos -o $@ $^
+
+%.o: %.asm
+ ../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: cmdhash.gen ver.inc pcomm.com
+
+clean:
+ for %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ for %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
+
+ if exist cmdhash.gen ( del /q cmdhash.gen )
+ if exist pcomm.com ( del /q pcomm.com )
+ if exist ver.inc ( del /q ver.inc )
+
+cmdhash.gen: commands genhash.exe
+ genhash.exe < $< > $@
+ del /q genhash,exe
+
+ver.inc: genver.exe
+ genver.exe > $@
+ del /q genver.exe
+
+genhash.exe: genhash.c
+ gcc -o $@ $^
+
+genver.exe: genver.c
+ gcc -o $@ $^
+
+pcomm.com: ../../lib/crt/crt0.o cbreak.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
+ ../../utils/binutils/slink --oformat msdos -o $@ $^
+
+%.o: %.asm
+ ../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file cbreak.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _cbreak_handler
+;******************************************************************************
+global _cbreak_handler
+_cbreak_handler:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the extra segment is the same as the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up di and cx ready to clear the current command.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, offset _scratch
+ xor ch, ch
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the di and cx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out al and clear the current command.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor al, al
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the cx (command length and current offset) and di
+ ;; (current command address) registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop cx
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset our history index (bp should be unchanged).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_vec_history + 4]
+ mov cs:[_history_idx], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free the current command history if there is one.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_curr_scratch]
+
+ and ax, ax
+ jz .L1
+
+ push ax
+
+ call _free
+ add sp, 2
+
+ xor ax, ax
+ mov cs:[_curr_scratch], ax
+
+.L1:
+
+ call _prompt
+
+ pop ax
+ pop es
+
+ clc
+ retf 2
--- /dev/null
+cd
+cls
+date
+del
+dir
+echo
+exit
+help
+mkdir
+reboot
+rmdir
+shutdown
+time
+touch
+type
+ver
--- /dev/null
+;******************************************************************************
+; @file crlf.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _crlf
+;******************************************************************************
+global _crlf
+_crlf:
+
+ push ax
+ push bx
+ push dx
+ push bp
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (0A)
+ int HEX (21)
+
+ pop bp
+ pop dx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file date.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_date
+;******************************************************************************
+global _handler_date
+_handler_date:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ah, HEX (2A)
+ int HEX (21)
+ mov bx, dx
+
+ mov ax, cx
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, '-'
+ int HEX (21)
+
+ cmp bh, 10
+ jae _handler_date.got_month
+
+ mov ah, HEX (02)
+ mov dl, '0'
+ int HEX (21)
+
+_handler_date.got_month:
+
+ xor ah, ah
+ mov al, bh
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, '-'
+ int HEX (21)
+
+ cmp bl, 10
+ jae _handler_date.got_day
+
+ mov ah, HEX (02)
+ mov dl, '0'
+ int HEX (21)
+
+_handler_date.got_day:
+
+ xor ah, ah
+ mov al, bl
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (0A)
+ int HEX (21)
+
+_handler_date.done:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file dir.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_dir
+;******************************************************************************
+global _handler_dir
+_handler_dir:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 6
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov word ptr [bp - 6], 0
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 2], 0
+
+ mov ax, 64
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ mov cs:[_dta_addr], ax
+ push ds
+
+ mov ds, ax
+ xor dx, dx
+
+ mov ah, HEX (1A)
+ int HEX (21)
+
+ pop ds
+
+ cmp byte ptr [bx], 0
+ jne _handler_dir.got_path
+
+ mov bx, offset _fn_wild
+
+_handler_dir.got_path:
+
+ 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_dir.store_file:
+
+ cmp byte ptr [bx], 0
+ je _handler_dir.check2
+
+ mov si, bx
+ push si
+
+ mov ax, offset _vec_files
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+_handler_dir.check:
+
+ mov ax, ' '
+ push ax
+
+ mov si, bx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _handler_dir.check2
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ inc bx
+
+_handler_dir.skip:
+
+ cmp byte ptr [bx], 0
+ je _handler_dir.check2
+
+ cmp byte ptr [bx], ' '
+ ja _handler_dir.store_file
+
+ inc bx
+ jmp _handler_dir.skip
+
+_handler_dir.check2:
+
+ cmp word ptr cs:[_vec_files + 4], 1
+ jbe _handler_dir.next
+
+ mov word ptr [bp - 4], 2
+
+_handler_dir.next:
+
+ mov ax, word ptr [bp - 6]
+ inc ax
+
+ cmp ax, cs:[_vec_files + 4]
+ ja _handler_dir.free
+
+ mov word ptr [bp - 6], 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 dx, ax
+
+ pop es
+
+ call _walk_dir
+ jmp _handler_dir.next
+
+_handler_dir.free:
+
+ mov ax, cs:[_dta_addr]
+ push ax
+
+ call _free
+ add sp, 2
+
+_handler_dir.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_dir.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 6
+ pop bp
+
+ ret
+
+;******************************************************************************
+; @function _walk_dir
+;******************************************************************************
+_walk_dir:
+
+ push ax
+ push bx
+ push dx
+ push ds
+ push cx
+
+ mov word ptr [bp - 2], 0
+ mov si, offset _file_path
+
+ push dx
+ push si
+
+ call _xstrcpy
+ add sp, 4
+
+ cmp word ptr [bp - 4], 1
+ jb _walk_dir.find_first
+
+_walk_dir.find_first:
+
+ mov ah, HEX (4E)
+ xor cx, cx
+ int HEX (21)
+ jnc _walk_dir.check5
+
+ cmp ax, 2
+ jne _walk_dir.check3
+
+ mov bx, offset _err_no_file
+ jmp _walk_dir.error
+
+_walk_dir.check3:
+
+ cmp ax, 3
+ jne _walk_dir.unhandled
+
+ mov bx, offset _err_no_dir
+ jmp _walk_dir.error
+
+_walk_dir.unhandled:
+
+ mov bx, offset _err_unhandled
+
+_walk_dir.error:
+
+ pop cx
+ call _writestr
+
+ cmp ax, 3
+ ja _walk_dir.done
+
+ cmp ax, 2
+ jb _walk_dir.done
+
+ mov bx, offset _file_path
+
+ call _writestr
+ call _crlf
+
+ jmp _walk_dir.done
+
+_walk_dir.check5:
+
+ cmp word ptr [bp - 4], 2
+ jb _walk_dir.setup
+
+ mov bx, offset _file_path
+ call _writestr
+
+ mov ah, HEX (02)
+ mov dl, ':'
+ int HEX (21)
+
+ call _crlf
+
+_walk_dir.setup:
+
+ mov ax, cs:[_dta_addr]
+ mov ds, ax
+
+_walk_dir.find:
+
+ cmp word ptr [bp - 2], 0
+ je _walk_dir.ok
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, ':'
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+_walk_dir.ok:
+
+ mov si, 30
+ mov cx, 12
+
+_walk_dir.print:
+
+ lodsb
+
+ and al, al
+ jz _walk_dir.final_pad
+
+ cmp al, '.'
+ je _walk_dir.check
+
+ jmp short _walk_dir.output
+
+_walk_dir.check:
+
+ cmp cx, 12
+ jb _walk_dir.period_check
+
+ jmp short _walk_dir.output
+
+_walk_dir.period_check:
+
+ cmp byte ptr [si - 1], '.'
+ jne _walk_dir.pad
+
+_walk_dir.output:
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ dec cx
+ jnz _walk_dir.print
+
+_walk_dir.pad:
+
+ cmp cx, 4
+ jb _walk_dir.print
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+ dec cx
+ jmp short _walk_dir.pad
+
+_walk_dir.final_pad:
+
+ and cx, cx
+ jz _walk_dir.check2
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+ dec cx
+ jmp short _walk_dir.final_pad
+
+_walk_dir.check2:
+
+ inc word ptr [bp - 2]
+
+ cmp word ptr [bp - 2], 5
+ jb _walk_dir.next
+
+ mov word ptr [bp - 2], 0
+ call _crlf
+
+_walk_dir.next:
+
+ mov ah, HEX (4F)
+ int HEX (21)
+ jnc _walk_dir.find
+
+ cmp word ptr [bp - 2], 0
+ je _walk_dir.check4
+
+ call _crlf
+
+_walk_dir.check4:
+
+ pop cx
+
+ cmp word ptr [bp - 4], 2
+ jb _walk_dir.done
+
+ cmp cx, 1
+ jbe _walk_dir.done
+
+ call _crlf
+
+_walk_dir.done:
+
+ pop ds
+ pop dx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_vec_files: db 6 dup (0)
+_cmdline: db 256 dup (0)
+
+_file_path: db 256 dup (0)
+_dta_addr: dw HEX (0000)
+
+_fn_wild: db "*.*", HEX (00)
+
+_err_no_dir: db "Path not found: ", HEX (00)
+_err_no_file: db "File not found: ", HEX (00)
+
+_err_unhandled: db "Unhandled error code", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file erase.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _erase_char
+;******************************************************************************
+global _erase_char
+_erase_char:
+
+ mov ah, HEX (02)
+ mov dl, HEX (08)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (20)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (08)
+ int HEX (21)
+
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file exit.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_exit
+;******************************************************************************
+global _handler_exit
+_handler_exit:
+
+ push ax
+ mov ax, cs:[HEX (16)]
+
+ and ax, ax
+ jnz _handler_exit.kill
+
+ pop ax
+ ret
+
+_handler_exit.kill:
+
+ pop ax
+
+ mov ax, HEX (4C00)
+ int HEX (21)
--- /dev/null
+/******************************************************************************
+ * @file genhash.c
+ *****************************************************************************/
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct hash {
+
+ char *keywd;
+ unsigned value;
+
+ struct hash *next;
+ struct hash **prev;
+
+};
+
+static char *trim_whitespace (char *str) {
+
+ char *end;
+
+ while (isspace ((int) *str)) {
+ str++;
+ }
+
+ if (*str == '\0') {
+ return str;
+ }
+
+ end = str + strlen (str) - 1;
+
+ while (end > str && isspace ((int) *end)) {
+ end--;
+ }
+
+ end[1] = '\0';
+ return str;
+
+}
+
+static void hash_push (struct hash **head, struct hash *item) {
+
+ item->prev = head;
+
+ if (*head) {
+ (*head)->prev = &item->next;
+ }
+
+ item->next = *head;
+ *head = item;
+
+}
+
+int main (int argc, char **argv) {
+
+ struct hash *curr_hash, *seen_hashes = 0;
+
+ char ch, keywd[256], *p;
+ unsigned hash;
+
+ while ((fgets (keywd, sizeof (keywd), stdin))) {
+
+ p = trim_whitespace (keywd);
+ hash = 0;
+
+ while ((ch = *p++)) {
+ hash = (((hash << 5) | (hash >> 11)) ^ (ch | 0x20)) & 0xffff;
+ }
+
+ for (curr_hash = seen_hashes; curr_hash; curr_hash = curr_hash->next) {
+
+ if (curr_hash->value == hash) {
+
+ fprintf (stderr, "hash collision (0x%04x) %s %s\n", hash, keywd, curr_hash->keywd);
+ return 1;
+
+ }
+
+ }
+
+ if (!(curr_hash = (struct hash *) malloc (sizeof (*curr_hash)))) {
+
+ fprintf (stderr, "Out of memory");
+ return 1;
+
+ }
+
+ curr_hash->keywd = keywd;
+ curr_hash->value = hash;
+
+ curr_hash->next = 0;
+ hash_push (&seen_hashes, curr_hash);
+
+ printf ("hash_%s: equ 0x%04x\n", keywd, hash);
+
+ }
+
+ return 0;
+
+}
--- /dev/null
+/******************************************************************************
+ * @file genver.c
+ *****************************************************************************/
+#include <stdio.h>
+#include <time.h>
+
+int main (int argc, char **argv) {
+
+ time_t raw_time = time (0);
+ struct tm *ctime = localtime (&raw_time);
+
+ printf ("_welcome_message: db \"Welcome to PCOMM (build %u.%u)\", HEX (0D), HEX (0A), HEX (00)\n",
+ ctime->tm_mday + ((ctime->tm_mon + 1) << 5) + ((ctime->tm_year - 80) << 9),
+ (ctime->tm_sec >> 1) + (ctime->tm_min << 5) + (ctime->tm_hour << 11)
+ );
+
+ return 0;
+
+}
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file history.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _history_down
+;******************************************************************************
+global _history_down
+_history_down:
+
+ push es
+ push ds
+ push bx
+
+ mov ax, cs:[_history_idx]
+ mov dx, cs:[_vec_history + 4]
+
+ cmp ax, dx
+ jae .L7
+
+ xor dx, dx
+ inc ax
+ mov cs:[_history_idx], ax
+
+ mov bx, cs:[_curr_scratch]
+ mov ds, bx
+ xor si, si
+
+ cmp ax, cs:[_vec_history + 4]
+ jae .L10
+
+ push cx
+
+ mov cx, 2
+ mul cx
+
+ pop cx
+ push es
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_history]
+ mov es, ax
+
+ mov ax, es:[bx]
+ pop es
+
+ mov ds, ax
+ xor si, si
+
+.L10:
+
+ and ch, ch
+ jz .L9
+
+ xor ah, ah
+ mov al, cs:[_curr_col]
+
+ push cx
+ push dx
+ xor dx, dx
+
+ mov cl, ch
+ xor ch, ch
+ add ax, cx
+
+ mov cx, HEX (50)
+ div cx
+
+ xchg ax, dx
+ pop dx
+ pop cx
+
+ and ax, ax
+ jnz .L11
+
+ push ax
+ push bx
+ push dx
+ push cx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ pop cx
+ dec dh
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (50)
+ int HEX (10)
+
+ mov byte ptr es:[di], 0
+ call _erase_char
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (4F)
+ int HEX (10)
+
+ pop dx
+ pop bx
+ pop ax
+
+ dec ch
+ dec di
+
+ jmp short .L10
+
+.L11:
+
+ mov byte ptr es:[di], 0
+ call _erase_char
+
+ dec ch
+ dec di
+
+ jmp short .L10
+
+.L9:
+
+ lodsb
+
+ or al, al
+ jz .L7
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ stosb
+ inc ch
+
+ jmp short .L9
+
+.L7:
+
+ mov ax, ds
+
+ and ax, ax
+ jz .L8
+
+ cmp ax, cs:[_curr_scratch]
+ jne .L8
+
+ push ax
+
+ call _free
+ add sp, 2
+
+ xor ax, ax
+ mov cs:[_curr_scratch], ax
+
+.L8:
+
+ pop bx
+ pop ds
+ pop es
+
+ ret
+
+;******************************************************************************
+; @function _history_up
+;******************************************************************************
+global _history_up
+_history_up:
+
+ push es
+ push ds
+ push bx
+
+ mov ax, cs:[_history_idx]
+ xor dx, dx
+
+ cmp ax, dx
+ jbe .L1
+
+ mov bx, cs:[_curr_scratch]
+
+ and bx, bx
+ jnz .L2
+
+ push ax
+
+ xor ah, ah
+ mov al, ch
+
+ xor dx, dx
+ inc ax
+
+ push ax
+ push dx
+
+ call _malloc
+ add sp, 4
+
+ mov bx, ax
+ pop ax
+
+ and bx, bx
+ jz .L2
+
+ mov cs:[_curr_scratch], bx
+
+ push es
+ push di
+ push ds
+ push si
+ push cx
+ push ax
+
+ mov es, bx
+
+ mov si, offset _scratch
+ xor di, di
+
+ mov cl, ch
+ xor ch, ch
+ rep movsb
+
+ xor al, al
+ stosb
+
+ pop ax
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+
+.L2:
+
+ xor dx, dx
+ dec ax
+ mov cs:[_history_idx], ax
+
+ push cx
+
+ mov cx, 2
+ mul cx
+
+ pop cx
+ push es
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_history]
+ mov es, ax
+
+ mov ax, es:[bx]
+ pop es
+
+ mov ds, ax
+ xor si, si
+
+.L4:
+
+ and ch, ch
+ jz .L5
+
+ xor ah, ah
+ mov al, [_curr_col]
+
+ push cx
+ push dx
+ xor dx, dx
+
+ mov cl, ch
+ xor ch, ch
+ add ax, cx
+
+ mov cx, HEX (50)
+ div cx
+
+ xchg ax, dx
+ pop dx
+ pop cx
+
+ and ax, ax
+ jnz .L6
+
+ push ax
+ push bx
+ push dx
+ push cx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ pop cx
+ dec dh
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (50)
+ int HEX (10)
+
+ mov byte ptr es:[di], 0
+ call _erase_char
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (4F)
+ int HEX (10)
+
+ pop dx
+ pop bx
+ pop ax
+
+ dec ch
+ dec di
+
+ jmp short .L4
+
+.L6:
+
+ mov byte ptr es:[di], 0
+ call _erase_char
+
+ dec ch
+ dec di
+
+ jmp short .L4
+
+.L5:
+
+ lodsb
+
+ or al, al
+ jz .L1
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ stosb
+ inc ch
+
+ jmp short .L5
+
+.L1:
+
+ mov ax, ds
+
+ and ax, ax
+ jz .L3
+
+ cmp ax, cs:[_curr_scratch]
+ jne .L3
+
+ push ax
+
+ call _free
+ add sp, 2
+
+ xor ax, ax
+ mov cs:[_curr_scratch], ax
+
+.L3:
+
+ pop bx
+ pop ds
+ pop es
+
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file pcomm.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _main
+;******************************************************************************
+global _main
+_main:
+
+ mov ax, HEX (2523)
+ mov dx, offset _cbreak_handler
+ int HEX (21)
+
+ mov bx, offset _welcome_message
+ call _writestr
+
+.L5:
+
+ mov ah, HEX (19)
+ int HEX (21)
+
+ mov cs:[_curr_drive], al
+
+.L6:
+
+ mov si, offset _curr_path
+ xor dl, dl ; Default/Current directory.
+
+ mov ah, HEX (47)
+ int HEX (21)
+
+.L7:
+
+ call _prompt
+
+ mov cl, cs:[_scratch_size]
+ xor ch, ch
+
+ mov ax, cs:[_vec_history + 4]
+ mov cs:[_history_idx], ax
+
+ mov di, offset _scratch
+
+.L11:
+
+ mov ah, HEX (08)
+ int HEX (21)
+
+ and al, al
+ jnz .L10
+
+ mov ah, HEX (08)
+ int HEX (21)
+
+ cmp al, HEX (48)
+ je .L1
+
+ cmp al, HEX (4B)
+ je .L4
+
+ cmp al, HEX (50)
+ je .L2
+
+ jmp .L11
+
+.L10:
+
+ cmp al, HEX (09)
+ jne .L14
+
+ push ax
+ push cx
+ push dx
+
+ xor ah, ah
+ mov al, ch
+ xor dx, dx
+
+ mov cx, 4
+ div cx
+
+ mov cx, 4
+ sub cx, dx
+
+ mov al, ' '
+ push cx
+
+.L15:
+
+ and cx, cx
+ jz .L16
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ stosb
+ dec cx
+
+ jmp .L15
+
+.L16:
+
+ pop ax
+ pop dx
+ pop cx
+
+ add ch, al
+ pop ax
+
+ jmp .L11
+
+.L14:
+
+ cmp al, HEX (0D)
+ je .L3
+
+ cmp al, HEX (08)
+ je .L4
+
+ cmp ch, cl
+ jae .L11
+
+ cmp al, HEX (20)
+ jb .L11
+
+ cmp al, HEX (7F)
+ ja .L11
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ stosb
+ inc ch
+
+ jmp .L11
+
+.L4:
+
+ call _handle_backspace
+ jmp .L11
+
+.L3:
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (0A)
+ int HEX (21)
+
+ and ch, ch
+ jz .L7
+
+ xor ah, ah
+ mov al, ch
+
+ xor dx, dx
+ inc ax
+
+ push ax
+ push dx
+
+ call _malloc
+ add sp, 4
+
+ and ax, ax
+ jz .L20
+
+ push es
+ push di
+ push ds
+ push si
+ push cx
+ push bx
+
+ mov es, ax
+ push es
+
+ mov bx, offset _vec_history
+ push bx
+
+ call _vec_push
+ add sp, 4
+
+ mov si, offset _scratch
+ xor di, di
+
+ mov cl, ch
+ xor ch, ch
+ rep movsb
+
+ xor al, al
+ stosb
+
+ pop bx
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+
+.L20:
+
+ cmp ch, 2
+ jne .L21
+
+ mov si, offset _scratch
+
+ cmp byte ptr [si + 1], ':'
+ jne .L21
+
+ xor ah, ah
+ mov al, [si]
+
+ push ax
+
+ call _isalpha
+ add sp, 2
+
+ and ax, ax
+ jz .L7
+
+ xor ah, ah
+ mov al, [si]
+
+ push ax
+
+ call _toupper
+ add sp, 2
+
+.L22:
+
+ sub al, HEX (41)
+ mov dl, al
+
+ mov ah, HEX (0E)
+ int HEX (21)
+
+ jmp .L5
+
+.L21:
+
+ call _get_command
+ jc .L23
+
+ mov si, bx
+ xor ax, ax
+
+ push bx
+ xor bx, bx
+
+ lodsb
+
+ or al, al
+ jz .L7
+
+ or al, HEX (20)
+ mov bl, al
+
+.L28:
+
+ lodsb
+
+ or al, al
+ jz .L31
+
+ mov cl, 5
+ rol bx, cl
+
+ or al, HEX (20)
+ xor bx, ax
+
+ jmp .L28
+
+.L31:
+
+ mov di, bx
+ pop bx
+
+ mov si, offset _cmd_table
+ mov cx, offset _cmd_count
+
+.L29:
+
+ lodsw
+
+ cmp di, ax
+ je .L30
+
+ lodsw
+ lodsw
+ loop .L29
+
+ jmp .L23
+
+.L30:
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ add bx, ax
+ inc bx
+
+.L33:
+
+ cmp byte ptr [bx], 0
+ je .L32
+
+ cmp byte ptr [bx], ' '
+ ja .L32
+
+ inc bx
+ jmp .L33
+
+.L32:
+
+ lodsw
+
+ call cs:[si]
+ jmp .L5
+
+.L23:
+
+ mov di, offset _app_path
+
+ mov ax, '\\'
+ push ax
+
+ mov si, bx
+ push bx
+
+ call _strrchr
+ add sp, 4
+
+ and ax, ax
+ jz .L27
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ call _format_path
+
+ mov al, '\\'
+ stosb
+
+ inc bx
+
+.L27:
+
+ mov ax, '.'
+ push ax
+
+ mov si, bx
+ push bx
+
+ call _strrchr
+ add sp, 4
+
+ and ax, ax
+ jnz .L24
+
+.L26:
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ rep movsb
+
+ add bx, ax
+
+ mov al, '.'
+ stosb
+
+ mov al, 'c'
+ stosb
+
+ mov al, 'o'
+ stosb
+
+ mov al, 'm'
+ stosb
+
+ jmp .L25
+
+.L24:
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ rep movsb
+
+ add bx, ax
+
+.L25:
+
+ xor al, al
+ stosb
+
+ mov dx, offset _app_path
+
+ add bx, 1
+ mov di, bx
+
+ mov bx, offset _param_blk
+
+ mov word ptr [bx + 2], di
+ mov word ptr [bx + 4], ds
+
+ mov ax, HEX (4B00)
+ int HEX (21)
+ jnc .L5
+
+ jmp .L5
+
+.L1:
+
+ call _history_up
+ jmp .L11
+
+.L2:
+
+ call _history_down
+ jmp .L11
+
+;******************************************************************************
+; @function _format_path
+;******************************************************************************
+_format_path:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov dx, di
+ jmp short _format_path.loop
+
+_format_path.store:
+
+ stosb
+
+ cmp al, '\\'
+ jne _format_path.loop
+
+_format_path.skip:
+
+ lodsb
+
+ cmp al, '\\'
+ je _format_path.skip
+
+ dec si
+
+_format_path.loop:
+
+ mov ax, di
+ sub ax, dx
+
+ cmp ax, 250
+ ja _format_path.done
+
+ lodsb
+
+ and al, al
+ jz _format_path.done
+
+ cmp al, 127
+ ja _format_path.done
+
+ cmp al, 32
+ jb _format_path.done
+
+ jmp short _format_path.store
+
+_format_path.done:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _get_command
+;******************************************************************************
+_get_command:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push si
+ push ax
+ push dx
+
+ mov word ptr [bp - 2], 0
+ mov si, offset _scratch
+
+_get_command.loop:
+
+ lodsb
+
+ and al, al
+ jz _get_command.done
+
+ cmp al, ' '
+ jbe _get_command.null
+
+ cmp al, ':'
+ je _get_command.not_internal
+
+ cmp al, '\\'
+ je _get_command.not_internal
+
+ cmp al, '.'
+ je _get_command.not_internal
+
+_get_command.check:
+
+ xor ah, ah
+
+ mov dx, ax
+ push dx
+
+ call _isalpha
+ add sp, 2
+
+ and ax, ax
+ jz _get_command.loop
+
+ push dx
+
+ call _tolower
+ add sp, 2
+
+ mov [si - 1], al
+ jmp _get_command.loop
+
+_get_command.not_internal:
+
+ mov word ptr [bp - 2], 1
+ jmp _get_command.loop
+
+_get_command.null:
+
+ mov byte ptr [si - 1], 0
+
+_get_command.done:
+
+ mov bx, word ptr [bp - 2]
+
+ pop dx
+ pop ax
+ pop si
+ pop bp
+
+ add sp, 2
+ clc
+
+ and bx, bx
+ jz _get_command.ret
+
+ stc
+
+_get_command.ret:
+
+ mov bx, offset _scratch
+ ret
+
+;******************************************************************************
+; @function _handle_backspace
+;******************************************************************************
+_handle_backspace:
+
+ and ch, ch
+ jz .L12
+
+ xor ah, ah
+ mov al, cs:[_curr_col]
+
+ push cx
+ push dx
+ xor dx, dx
+
+ mov cl, ch
+ xor ch, ch
+ add ax, cx
+
+ mov cx, HEX (50)
+ div cx
+
+ xchg ax, dx
+ pop dx
+ pop cx
+
+ and ax, ax
+ jnz .L13
+
+ push ax
+ push bx
+ push dx
+ push cx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ pop cx
+ dec dh
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (50)
+ int HEX (10)
+
+ call _erase_char
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (4F)
+ int HEX (10)
+
+ pop dx
+ pop bx
+ pop ax
+
+ dec ch
+ dec di
+
+ mov byte ptr es:[di], 0
+ ret
+
+.L13:
+
+ call _erase_char
+
+ dec ch
+ dec di
+
+ mov byte ptr es:[di], 0
+
+.L12:
+
+ ret
+
+;******************************************************************************
+; @function _handler_cd
+;******************************************************************************
+_handler_cd:
+
+ push ax
+ push bx
+ push si
+
+ mov ax, ' '
+ push ax
+
+ mov si, bx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _handler_cd.change
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ inc bx
+
+_handler_cd.skip:
+
+ cmp byte ptr [bx], 0
+ je _handler_cd.change
+
+ cmp byte ptr [bx], ' '
+ ja _handler_cd.error
+
+ inc bx
+ jmp _handler_cd.skip
+
+_handler_cd.change:
+
+ mov ah, HEX (3B)
+ mov dx, si
+ int HEX (21)
+
+ jmp _handler_cd.done
+
+_handler_cd.error:
+
+ mov bx, offset _handler_cd.errmsg
+ call _writestr
+
+_handler_cd.done:
+
+ pop si
+ pop bx
+ pop ax
+ ret
+
+_handler_cd.errmsg: db "cd: too many arguments", HEX (0D), HEX (0A), HEX (00)
+
+;******************************************************************************
+; @function _handler_cls
+;******************************************************************************
+_handler_cls:
+
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ xor cx, cx
+ mov dx, HEX (184F)
+ int HEX (10)
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ xor dx, dx
+ int HEX (10)
+
+ ret
+
+;******************************************************************************
+; @function _handler_echo
+;******************************************************************************
+_handler_echo:
+
+ call _writestr
+ call _crlf
+
+ ret
+
+;******************************************************************************
+; @function _handler_help
+;******************************************************************************
+_handler_help:
+
+ push ax
+ push bx
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _handler_help.msg
+ call _writestr
+
+_handler_help.done:
+
+ pop ds
+ pop bx
+ pop ax
+ ret
+
+_handler_help.msg:
+
+ db "CD Change the current directory to the specified path.", HEX (0D), HEX (0A)
+ db "CLS Clears the screen.", HEX (0D), HEX (0A)
+ db "DATE Displays the system date.", HEX (0D), HEX (0A)
+ 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 "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)
+
+ db HEX (00)
+
+;******************************************************************************
+; @function _handler_reboot
+;******************************************************************************
+_handler_reboot:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Stop floppy motor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, HEX (03F2)
+ xor al, al
+ out dx, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0003)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cold reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov bx, HEX (0472)
+ mov word ptr es:[bx], 0
+
+ jmp HEX (F000) : HEX (FFF0)
+
+;******************************************************************************
+; @function _prompt
+;******************************************************************************
+global _prompt
+_prompt:
+
+ push ax
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+.L19:
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ mov cs:[_curr_row], dh ; byte ptr [bp - 2]
+ mov cs:[_curr_col], dl ; byte ptr [bp - 1]
+
+.L17:
+
+ mov di, offset _scratch
+ xor al, al
+
+ mov cl, cs:[_scratch_size]
+ xor ch, ch
+
+ rep stosb
+
+ xor al, al
+ mov cs:[_scratch_len], al
+
+ mov al, cs:[_curr_drive]
+ add al, 'A'
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, ':'
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, '\\'
+ int HEX (21)
+
+.L8:
+
+ mov bx, offset _curr_path
+ call _writestr
+
+.L9:
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, '>'
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, ' '
+ int HEX (21)
+
+.L18:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "ver.inc"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; int21/ah=0A variables.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_scratch_size: db 255
+_scratch_len: db 0
+
+global _scratch
+_scratch: db 257 dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Variables for executing application.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;_formatted_cmd: db 255 dup (0)
+_app_path: db 255 dup (0)
+_param_blk: db 16 dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _vec_history
+_vec_history: db 6 dup (0)
+
+global _curr_row
+_curr_row: db HEX (00)
+
+global _curr_col
+_curr_col: db HEX (00)
+
+global _history_idx
+_history_idx: dw HEX (0000)
+
+global _curr_scratch
+_curr_scratch: dw HEX (0000)
+
+_curr_path: db 65 dup (0)
+_curr_drive: db HEX (00)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Commands.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "cmdhash.gen"
+_cmd_size: equ 6
+
+align 4
+_cmd_table:
+
+ dw hash_cd
+ dw 0
+ dw _handler_cd
+
+ dw hash_cls
+ dw 0
+ dw _handler_cls
+
+ dw hash_date
+ dw 0
+ dw _handler_date
+
+ dw hash_dir
+ dw 0
+ dw _handler_dir
+
+ dw hash_echo
+ dw 0
+ dw _handler_echo
+
+ dw hash_exit
+ dw 0
+ dw _handler_exit
+
+ dw hash_help
+ dw 0
+ dw _handler_help
+
+ dw hash_reboot
+ dw 0
+ dw _handler_reboot
+
+ dw hash_time
+ dw 0
+ dw _handler_time
+
+ dw hash_type
+ dw 0
+ dw _handler_type
+
+_cmd_count: equ ($ - _cmd_table) / _cmd_size
--- /dev/null
+;******************************************************************************
+; @file time.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_time
+;******************************************************************************
+global _handler_time
+_handler_time:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ah, HEX (2C)
+ int HEX (21)
+ mov bx, dx
+
+ cmp ch, 10
+ jae _handler_time.got_hour
+
+ mov ah, HEX (02)
+ mov dl, '0'
+ int HEX (21)
+
+_handler_time.got_hour:
+
+ xor ah, ah
+ mov al, ch
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, ':'
+ int HEX (21)
+
+ cmp cl, 10
+ jae _handler_time.got_minute
+
+ mov ah, HEX (02)
+ mov dl, '0'
+ int HEX (21)
+
+_handler_time.got_minute:
+
+ xor ah, ah
+ mov al, cl
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, ':'
+ int HEX (21)
+
+ cmp bh, 10
+ jae _handler_time.got_second
+
+ mov ah, HEX (02)
+ mov dl, '0'
+ int HEX (21)
+
+_handler_time.got_second:
+
+ xor ah, ah
+ mov al, bh
+ xor dx, dx
+ call _writedec
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ mov ah, HEX (02)
+ mov dl, HEX (0A)
+ int HEX (21)
+
+_handler_time.done:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file type.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_type
+;******************************************************************************
+global _handler_type
+_handler_type:
+
+ 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
+
+ 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_type.store_file:
+
+ cmp byte ptr [bx], 0
+ je _handler_type.next
+
+ mov si, bx
+ push si
+
+ mov ax, offset _vec_files
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+_handler_type.check:
+
+ mov ax, ' '
+ push ax
+
+ mov si, bx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _handler_type.next
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ inc bx
+
+_handler_type.skip:
+
+ cmp byte ptr [bx], 0
+ je _handler_type.next
+
+ cmp byte ptr [bx], ' '
+ ja _handler_type.store_file
+
+ inc bx
+ jmp _handler_type.skip
+
+_handler_type.next:
+
+ mov ax, word ptr [bp - 4]
+ inc ax
+
+ cmp ax, cs:[_vec_files + 4]
+ ja _handler_type.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_type.open:
+
+ mov ax, HEX (3D02)
+ mov dx, bx
+ int HEX (21)
+ jc _handler_type.cleanup
+
+ mov bx, ax
+
+_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
+ int HEX (21)
+ jc _handler_type.close
+
+ and ax, ax
+ jz _handler_type.close
+
+ mov si, offset _buffer
+
+_handler_type.print_loop:
+
+ lodsb
+
+ and al, al
+ jz _handler_type.clear_and_read
+
+ cmp al, HEX (0A)
+ jne _handler_type.char_ok
+
+ push ax
+
+ mov ah, HEX (02)
+ mov dl, HEX (0D)
+ int HEX (21)
+
+ pop ax
+
+_handler_type.char_ok:
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ jmp _handler_type.print_loop
+
+_handler_type.close:
+
+ mov ah, HEX (3E)
+ int HEX (21)
+
+ jmp _handler_type.next
+
+_handler_type.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_type.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)
+_buffer: db 256 dup (0)
+
--- /dev/null
+;******************************************************************************
+; @file vector.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _vec_adjust
+;******************************************************************************
+_vec_adjust:
+
+ push bp
+ mov bp, sp
+
+ push bx
+ push cx
+ push dx
+
+ mov bx, word ptr [bp + 4]
+
+_vec_adjust.check:
+
+ mov cx, [bx + 2]
+
+ cmp cx, word ptr [bp + 6]
+ ja _vec_adjust.done
+
+_vec_adjust.check2:
+
+ and cx, cx
+ jnz _vec_adjust.shift
+
+ mov cx, 16
+ jmp short _vec_adjust.set
+
+_vec_adjust.shift:
+
+ shl cx
+
+_vec_adjust.set:
+
+ mov [bx + 2], cx
+
+_vec_adjust.alloc:
+
+ mov ax, 2
+ xor dx, dx
+
+ mul cx
+
+ push ax
+ push dx
+
+ mov ax, [bx + 0]
+ push ax
+
+ call _realloc
+ add sp, 6
+
+ mov [bx + 0], ax
+
+_vec_adjust.done:
+
+ xor ax, ax
+
+ pop dx
+ pop cx
+ pop bx
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _vec_push
+;******************************************************************************
+global _vec_push
+_vec_push:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ mov bx, word ptr [bp + 4]
+
+_vec_push.alt:
+
+ mov ax, [bx + 4]
+ push ax
+
+ push word ptr [bp + 4]
+
+ call _vec_adjust
+ add sp, 4
+
+ mov word ptr [bp - 2], ax
+
+ and ax, ax
+ jnz _vec_push.done
+
+_vec_push.set:
+
+ mov ax, [bx + 0]
+ mov es, ax
+
+ mov ax, [bx + 4]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov di, ax
+
+ mov ax, [bp + 6]
+ mov es:[di], ax
+
+ mov cx, [bx + 4]
+ add cx, 1
+
+ mov [bx + 4], cx
+
+_vec_push.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file writechr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function writechr
+;******************************************************************************
+global _writechr
+_writechr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push bp ; Some BIOSes destroy BP when the screen scrolls
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file writedec.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writedec
+;******************************************************************************
+global _writedec
+_writedec:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+ push bp
+
+ mov bx, 10
+ xor cx, cx
+
+_writedec.cloop:
+
+ div bx
+ inc cx
+
+ push dx
+ xor dx, dx
+
+ and ax, ax
+ jnz _writedec.cloop
+
+_writedec.dloop:
+
+ pop ax
+ add al, '0'
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ loop _writedec.dloop
+
+_writedec.done:
+
+ pop bp
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file writehex.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+global _writehex
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, 4
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file writestr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writestr
+;******************************************************************************
+global _writestr
+_writestr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push si
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize si with bx
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump over our printing code to get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _writestr.next
+
+_writestr.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (02)
+ mov dl, al
+ int HEX (21)
+
+_writestr.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _writestr.print
+
+_writestr.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop si
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file xmalloc.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function _xmalloc
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _xmalloc
+_xmalloc:
+
+ push bp
+ mov bp, sp
+
+ push es
+ push cx
+ push di
+
+ push word ptr [bp + 6]
+ push word ptr [bp + 4]
+
+ call _malloc
+ add sp, 4
+
+ and ax, ax
+ jnz _xmalloc.ok
+
+ pop ax
+ pop di
+ pop cx
+ pop es
+ pop bp
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _err_malloc
+ call _writestr
+
+ mov ax, HEX (4C01)
+ int HEX (21)
+
+_xmalloc.ok:
+
+ push ax
+ push bx
+
+ dec ax
+ mov es, ax
+
+ xor bx, bx
+ mov cx, es:[bx + 3]
+
+ pop bx
+ pop ax
+
+ push ax
+ mov es, ax
+
+_xmalloc.loop:
+
+ xor di, di
+
+ push ax
+ push cx
+
+ xor al, al
+ mov cx, 16
+ rep stosb
+
+ pop cx
+ pop ax
+
+ inc ax
+ mov es, ax
+
+ loop _xmalloc.loop
+
+_xmalloc.done:
+
+ pop ax
+ pop di
+ pop cx
+ pop es
+ pop bp
+ ret
+
+_err_malloc: db "Memory full (malloc)", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file xstrcpy.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function _xstrcpy
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _xstrcpy
+_xstrcpy:
+
+ push bp
+ mov bp, sp
+
+ push ax
+ push si
+ push di
+
+ mov si, [bp + 6]
+ mov di, [bp + 4]
+
+_xstrcpy.loop:
+
+ lodsb
+
+ or al, al
+ jz _xstrcpy.done
+
+ cmp al, 90
+ ja _xstrcpy.got_char
+
+ cmp al, 65
+ jb _xstrcpy.got_char
+
+ or al, HEX (20)
+
+_xstrcpy.got_char:
+
+ stosb
+ jmp short _xstrcpy.loop
+
+_xstrcpy.done:
+
+ xor al, al
+ stosb
+
+ pop di
+ pop si
+ pop ax
+ pop bp
+ ret
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := mbr freeldr
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for t in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$t" ]; then mkdir -p "$(OBJDIR)/$$t"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" all; \
+ done
+
+clean:
+ for t in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$t" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" clean; \
+ fi; \
+ done
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := mbr freeldr
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%t in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%t" ( mkdir "$(OBJDIR)/%%t" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" all \
+ )
+
+clean:
+ for %%t in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%t" ( \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" clean \
+ ) \
+ )
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := bootsect libc core
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: kwdhash.gen
+ for t in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$t" ]; then mkdir -p "$(OBJDIR)/$$t"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" all; \
+ done
+
+clean:
+ if [ -f kwdhash.gen ]; then rm -rf kwdhash.gen; fi
+ if [ -f genhash.exe ]; then rm -rf genhash.exe; fi
+ if [ -f genhash ]; then rm -rf genhash; fi
+
+ for t in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$t" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$t" -f "$(SRCDIR)/$$t/Makefile.unix" OBJDIR="$(OBJDIR)/$$t" SRCDIR="$(SRCDIR)/$$t" clean; \
+ fi; \
+ done
+
+ifeq ($(OS), Windows_NT)
+kwdhash.gen: keywords genhash.exe
+ ./genhash.exe < $< > $@
+
+genhash.exe: genhash.c
+ gcc -o $@ $^
+else
+kwdhash.gen: keywords genhash
+ ./genhash < $< > $@
+
+genhash: genhash.c
+ gcc -o $@ $^
+endif
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := bootsect libc core
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: kwdhash.gen
+ for %%t in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%t" ( mkdir "$(OBJDIR)/%%t" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" all \
+ )
+
+clean:
+ if exist kwdhash.gen ( del /q kwdhash.gen )
+ if exist genhash.exe ( del /q genhash.exe )
+ if exist genhash ( del /q genhash )
+
+ for %%t in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%t" ( \
+ $(MAKE) -C "$(OBJDIR)/%%t" -f "$(SRCDIR)/%%t/Makefile.w32" OBJDIR="$(OBJDIR)/%%t" SRCDIR="$(SRCDIR)/%%t" clean \
+ ) \
+ )
+
+kwdhash.gen: keywords genhash.exe
+ genhash.exe < $< > $@
+
+genhash.exe: genhash.c
+ gcc -o $@ $^
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: fat12.bin fat16.bin fat32_chs.bin
+
+clean:
+ if [ -f fat12.bin ]; then rm -rf fat12.bin; fi
+ if [ -f fat12.lst ]; then rm -rf fat12.lst; fi
+
+ if [ -f fat16.bin ]; then rm -rf fat16.bin; fi
+ if [ -f fat16.lst ]; then rm -rf fat16.lst; fi
+
+ if [ -f fat32_chs.bin ]; then rm -rf fat32_chs.bin; fi
+ if [ -f fat32_chs.lst ]; then rm -rf fat32_chs.lst; fi
+
+fat12.bin: oldfat.asm
+ ../../../utils/binutils/sasm -D__FAT12__ -f bin -l fat12.lst -o $@ $<
+
+fat16.bin: oldfat.asm
+ ../../../utils/binutils/sasm -D__FAT16__ -f bin -l fat16.lst -o $@ $<
+
+fat32_chs.bin: fat32_chs.asm
+ ../../../utils/binutils/sasm -f bin -l fat32_chs.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: fat12.bin fat16.bin fat32_chs.bin
+
+clean:
+ if exist fat12.bin ( del /q fat12.bin )
+ if exist fat12.lst ( del /q fat12.lst )
+
+ if exist fat16.bin ( del /q fat16.bin )
+ if exist fat16.lst ( del /q fat16.lst )
+
+ if exist fat32_chs.bin ( del /q fat32_chs.bin )
+ if exist fat32_chs.lst ( del /q fat32_chs.lst )
+
+fat12.bin: oldfat.asm
+ ../../../utils/binutils/sasm -D__FAT12__ -f bin -l fat12.lst -o $@ $<
+
+fat16.bin: oldfat.asm
+ ../../../utils/binutils/sasm -D__FAT16__ -f bin -l fat16.lst -o $@ $<
+
+fat32_chs.bin: fat32_chs.asm
+ ../../../utils/binutils/sasm -f bin -l fat32_chs.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file fat32_chs.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory layout.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Mem.Stage1: equ HEX (7C00)
+Mem.Stage2: equ HEX (0600)
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ jmp short _after_bpb
+ nop
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; System Identifier.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;system_id: db HEX (08) dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BIOS Parameter Block.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;bytes_per_sector: dw HEX (0000)
+;sectors_per_cluster: db HEX (00)
+;reserved_sectors: dw HEX (0000)
+;number_of_fats: db HEX (00)
+;root_entries: dw HEX (0000)
+;total_sectors16: dw HEX (0000)
+;media_descriptor: db HEX (00)
+;sectors_per_fat: dw HEX (0000)
+;sectors_per_track: dw HEX (0000)
+;heads_per_cylinder: dw HEX (0000)
+;hidden_sectors: dw HEX (0000), HEX (0000)
+;total_sectors32: dw HEX (0000), HEX (0000)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Extended BIOS Parameter Block.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;sectors_per_fat32: dw HEX (0000), HEX (0000)
+;flags: dw HEX (0000)
+;version: dw HEX (0000)
+;root_cluster: dw HEX (0000), HEX (0000)
+;info_sector: dw HEX (0000)
+;backup_boot: dw HEX (0000)
+;reserved2: dw 6 dup (0)
+;drive_no: db HEX (00)
+;boot_flags: db HEX (00)
+;ext_boot_sign: db HEX (00)
+;volume_id: dw HEX (0000), HEX (0000)
+;volume_label: db HEX (0B) dup (0)
+;fs_type: db HEX (08) dup (0)
+
+
+db HEX (5A) - (. - _start) dup (0)
+
+%define _bytes_per_sector (bp + 11)
+%define _sectors_per_cluster (bp + 13)
+%define _reserved_sectors (bp + 14)
+%define _number_of_fats (bp + 16)
+%define _sectors_per_track (bp + 24)
+%define _heads_per_cylinder (bp + 26)
+%define _hidden_sectors (bp + 28)
+%define _sectors_per_fat32 (bp + 36)
+%define _root_cluster (bp + 44)
+%define _drive_no (bp + 64)
+
+;******************************************************************************
+; @function _after_bpb
+;******************************************************************************
+_after_bpb:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Far jump to the next instruction to fix the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp (Mem.Stage1 >> 4) : _real_start
+
+loadseg_60:
+
+ dw HEX (0000)
+ dw Mem.Stage2 >> 4
+
+;******************************************************************************
+; @function _real_start
+;******************************************************************************
+_real_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push cs
+ pop ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the stack segment and the base and stack pointers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov ss, ax
+
+ mov bp, Mem.Stage1
+ lea sp, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no. passed to us from them BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], dl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get drive parameters (HDD only).
+ ;;
+ ;; If a drive is moved between different systems, its geometry may
+ ;; differ in the eyes of the different BIOSes, more so when it's a
+ ;; disk image for a VM.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (08) ; clobbers AX, BL, CX, DX, ES:DI
+ int HEX (13)
+ jc .calc_offsets
+
+ and cx, HEX (3F)
+ mov [_sectors_per_track], cx
+
+ mov cl, dh
+ inc cx
+ mov [_heads_per_cylinder], cx
+
+ .calc_offsets:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset ready for the fathelper at the start of
+ ;; freeldr.sys.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [bp - 24], si
+ mov [bp - 22], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+ push ax
+
+ mul word ptr [_sectors_per_fat32 + 2]
+ add di, ax
+
+ pop ax
+ mul word ptr [_sectors_per_fat32]
+
+ add ax, si
+ adc dx, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [bp - 20], ax
+ mov [bp - 18], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [_bytes_per_sector]
+ shr ax
+ shr ax
+ dec ax
+ mov [bp - 16], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+
+ xchg ax, cx
+ inc cx
+
+ .secshift:
+
+ inc ax
+ shr cx
+
+ cmp cx, 1
+ jne .secshift
+
+ mov [bp - 14], ax
+ dec cx
+
+ mov ax, [_root_cluster]
+ mov dx, [_root_cluster + 2]
+
+ .ff_next_cluster:
+
+ push dx
+ push ax
+
+ call _convert_cluster
+ jnc .ff_next_sector
+
+ call _error
+ db "NF", HEX (0D), HEX (0A), HEX (00)
+
+ .ff_next_sector:
+
+ push bx
+ les bx, [loadseg_60]
+
+ push es
+ call _read_sectors
+
+ pop es
+ push dx
+ push ax
+
+ mov ax, [_bytes_per_sector]
+
+ .ff_next_entry:
+
+ mov si, offset Entry.Filename
+ mov cx, offset Entry.Filename.Length
+
+ mov di, ax
+ sub di, HEX (20)
+
+ repe cmpsb
+ jz .ff_done
+
+ sub ax, HEX (20)
+ jnz .ff_next_entry
+
+ pop ax
+ pop dx
+ pop bx
+
+ dec bx
+ jnz .ff_next_sector
+
+ .ff_find_next_cluster:
+
+ pop ax
+ pop dx
+
+ call _next_cluster
+ jmp short .ff_next_cluster
+
+ .ff_done:
+
+ mov ax, es:[di + HEX (1A) - 11]
+ mov dx, es:[di + HEX (14) - 11]
+
+ .c4:
+
+ sub bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the number of sectors per cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ch, ch
+ mov cl, [_sectors_per_cluster]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with the value i the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we read at least 4 sectors.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp si, 4
+ jae .c5
+
+ mov si, 4
+
+ .c5:
+
+ push dx
+ push ax
+ push bx
+
+ call _convert_cluster
+ jc .execute
+
+ mov di, bx
+ sub si, bx
+ pop bx
+
+ .c6:
+
+ call _read_sectors
+
+ dec di
+ jnz .c6
+
+ pop ax
+ pop dx
+
+ and si, si
+ jz .execute
+
+ call _next_cluster
+ jmp short .c5
+
+ .execute:
+
+ mov cl, [_drive_no]
+ jmp far ptr [loadseg_60]
+
+;******************************************************************************
+; @function _convert_cluster
+;******************************************************************************
+_convert_cluster:
+
+ cmp dx, HEX (0FFF)
+ jne _convert_cluster.c3
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster.c3
+
+ stc
+ ret
+
+_convert_cluster.c3:
+
+ mov cx, dx
+
+ sub ax, 2
+ sbb cx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ xchg cx, ax
+ mul bx
+
+ xchg ax, cx
+ mul bx
+
+ add dx, cx
+
+ add ax, [bp - 20]
+ add dx, [bp - 18]
+
+ ret
+
+;******************************************************************************
+; @function _error
+;******************************************************************************
+_error:
+
+ pop si
+ jmp short _error.next
+
+_error.print:
+
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_error.next:
+
+ lodsb
+
+ and al, al
+ jnz _error.print
+
+_error.done:
+
+ xor ax, ax
+ int HEX (16)
+ int HEX (19)
+
+;******************************************************************************
+; @function _next_cluster
+;******************************************************************************
+_next_cluster:
+
+ mov di, ax
+ and di, [bp - 16]
+
+ mov cx, [bp - 14]
+
+_next_cluster.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _next_cluster.cn_loop
+
+ shl di
+ shl di
+
+ add ax, [bp - 24]
+ adc dx, [bp - 22]
+
+ push es
+ push bx
+
+ ;mov bx, (Mem.Stage2 >> 4) - HEX (20)
+ ;mov es, bx
+ ;xor bx, bx
+
+ call _read_sectors
+
+_next_cluster.cn_exit:
+
+ pop bx
+ pop es
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ ret
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push dx
+
+ div word ptr [_sectors_per_track]
+ ; ax = LBA / SPT
+ ; dx = LBA % SPT = sector - 1
+
+ xchg cx, dx
+ inc cx
+ ; cx = sector no.
+
+ xor dx, dx
+ div word ptr [_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 ; excess bits of cylinder no. must be 0 anyway
+
+ or cl, ah
+ ; cl = MSB 8...9 of cylinder no. + sector no.
+
+ mov dh, dl
+ ; dh = head no.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, [_drive_no]
+ int HEX (13)
+ jnc _read_sectors.success ; CF = 0 if no _error
+
+_read_sectors.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ mov ax, [_bytes_per_sector]
+ mov cl, 4
+ shr ax, cl
+
+ mov cx, es
+ add cx, ax
+ mov es, cx
+
+_read_sectors.no_incr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 1
+ adc dx, 0
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Entry.Filename: db "FREELDR SYS"
+Entry.Filename.Length: equ ($ - Entry.Filename)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pad until 510 bytes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+db HEX (01FE) - (. - _start) dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Boot signature.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+dw HEX (AA55)
--- /dev/null
+;******************************************************************************
+; @file oldfat.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory layout.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Mem.Stage1: equ HEX (7C00)
+Mem.Stage2: equ HEX (0600)
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ jmp short after_bpb
+ nop
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; System Identifier.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;system_id: db HEX (08) dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BIOS Parameter Block.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;bytes_per_sector: dw HEX (0000)
+;sectors_per_cluster: db HEX (00)
+;reserved_sectors: dw HEX (0000)
+;number_of_fats: db HEX (00)
+;root_entries: dw HEX (0000)
+;total_sectors16: dw HEX (0000)
+;media_descriptor: db HEX (00)
+;sectors_per_fat: dw HEX (0000)
+;sectors_per_track: dw HEX (0000)
+;heads_per_cylinder: dw HEX (0000)
+;hidden_sectors: dw HEX (0000), HEX (0000)
+;total_sectors32: dw HEX (0000), HEX (0000)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Extended BIOS Parameter Block.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;drive_no: db HEX (00)
+;boot_flags: db HEX (00)
+;ext_boot_sign: db HEX (00)
+;volume_id: dw HEX (0000), HEX (0000)
+;volume_label: db HEX (0B) dup (0)
+;fs_type: db HEX (08) dup (0)
+
+
+db HEX (3E) - (. - _start) dup (0)
+
+%define _bytes_per_sector (bp + 11)
+%define _sectors_per_cluster (bp + 13)
+%define _reserved_sectors (bp + 14)
+%define _number_of_fats (bp + 16)
+%define _root_entries (bp + 17)
+%define _sectors_per_fat (bp + 22)
+%define _sectors_per_track (bp + 24)
+%define _heads_per_cylinder (bp + 26)
+%define _hidden_sectors (bp + 28)
+%define _drive_no (bp + 36)
+
+;******************************************************************************
+; @function after_bpb
+;******************************************************************************
+after_bpb:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Far jump to the next instruction to fix the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp (Mem.Stage1 >> 4) : real_start
+
+;******************************************************************************
+; @function real_start
+;******************************************************************************
+real_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the stack segment and the base and stack pointers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov ss, ax
+
+ mov bp, Mem.Stage1
+ lea sp, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no. passed to us from them BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], dl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get drive parameters (HDD only).
+ ;;
+ ;; If a drive is moved between different systems, its geometry may
+ ;; differ in the eyes of the different BIOSes, more so when it's a
+ ;; disk image for a VM.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test dl, HEX (80)
+ jz .calc_offsets ; skip if it's a flopy (dl < 80h)
+
+ mov ah, HEX (08) ; clobbers AX, BL, CX, DX, ES:DI
+ int HEX (13)
+ jc .calc_offsets
+
+ and cx, HEX (3F)
+ mov [_sectors_per_track], cx
+
+ mov cl, dh
+ inc cx
+ mov [_heads_per_cylinder], cx
+
+ .calc_offsets:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset ready for the fathelper at the start of
+ ;; freeldr.sys.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [bp - 24], si
+ mov [bp - 22], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+ mul word ptr [_sectors_per_fat]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; As we'll only need the root directory in this file
+ ;; we'll just push the offset to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr [_root_entries]
+ div word ptr [_bytes_per_sector]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [bp - 20], si
+ mov [bp - 18], di
+
+ .find_stage2:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax register should contain the total amount of sectors
+ ;; of the root directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the root directory offset off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+
+ .find_stage2.read:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll read the sector into memory 0000:0500.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, HEX (0050)
+ mov es, bx
+ xor bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the root directory in it's entirety.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push bx
+ call _read_sectors
+
+ pop bx
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The rep cmpsb uses di instead of bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, bx
+ mov dx, [_root_entries]
+
+ .find_stage2.compare:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the current offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the si and cx with out entry values.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset Entry.Filename
+ mov cx, offset Entry.Filename.Length
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Perform the compare.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ repe cmpsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the entries match then we've found our entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ je .entry_found
+
+ .find_stage2.advance:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, 32
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement the counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we haven't read all th entries then compare this entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz .find_stage2.compare
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we reach here we failed to find our entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp .error
+
+ .entry_found:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check that the entry has the archive bit set.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test byte ptr es:[di + 11], HEX (18)
+ jnz .error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the starting cluster into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[di + 26]
+ mov dx, es:[di + 20]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the number of sectors per cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ch, ch
+ mov cl, [_sectors_per_cluster]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with the value i the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we read at least 4 sectors.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp di, 4
+ jae .got_count
+
+ mov di, 4
+
+ .got_count:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll read the sector/cluster into Mem.Stage2.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, (Mem.Stage2 >> 4)
+ mov es, bx
+ xor bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push bx
+
+ .read_entry:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax, dx and bx registers
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push ax
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the cluster to LBA.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _convert_cluster
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in the bx register to cx (sectors per cluster)
+ ;; and restore the bx register (offset to read into).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, bx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then we've reached the end of the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc .execute
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement our sectors count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the cluster into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _read_sectors
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If di is zero the we've read all the sectors we need.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and di, di
+ jz .execute
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _next_cluster
+ jmp short .read_entry
+
+ .execute:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax, dx and bx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll pass the drive no. in cl.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to the new code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ retf
+
+ .error:
+
+ call _error
+ db "NF", HEX (0D), HEX (0A), HEX (00)
+
+;******************************************************************************
+; @function _error
+;******************************************************************************
+_error:
+
+ pop si
+ jmp short _error.next
+
+_error.print:
+
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_error.next:
+
+ lodsb
+
+ and al, al
+ jnz _error.print
+
+_error.done:
+
+ xor ax, ax
+ int HEX (16)
+ int HEX (19)
+
+%ifdef __FAT12__
+;******************************************************************************
+; @function _convert_cluster
+;******************************************************************************
+_convert_cluster:
+
+ cmp ax, HEX (0FF8)
+ jb _convert_cluster.c3
+
+ stc
+ ret
+
+_convert_cluster.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [bp - 20]
+ add dx, [bp - 18]
+
+ ret
+
+;******************************************************************************
+; @function _next_cluster
+;******************************************************************************
+_next_cluster:
+
+ push cx
+ push si
+
+ mov si, ax
+
+_next_cluster.secoff:
+
+ mov ax, 3
+ mul si
+ shr ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_next_cluster.read_fat:
+
+ push es
+ push bx
+
+ ;mov bx, (Mem.Stage2 >> 4) - HEX (40)
+ ;mov es, bx
+ ;xor bx, bx
+
+ mov ax, [bp - 24]
+ mov dx, [bp - 22]
+
+ add ax, si
+ adc dx, 0
+
+ mov cx, 2
+ call _read_sectors
+
+ pop bx
+ pop es
+
+_next_cluster.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, es
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _next_cluster.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_next_cluster.even_cluster:
+
+ and ax, HEX (0FFF)
+
+_next_cluster.compare:
+
+ cmp ax, HEX (0FF8)
+ cmc
+
+_next_cluster.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+%endif
+
+%ifdef __FAT16__
+;******************************************************************************
+; @function _convert_cluster
+;******************************************************************************
+_convert_cluster:
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster.c3
+
+ stc
+ ret
+
+_convert_cluster.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [bp - 20]
+ add dx, [bp - 18]
+
+ ret
+
+;******************************************************************************
+; @function _next_cluster
+;******************************************************************************
+_next_cluster:
+
+ push cx
+ push si
+
+_next_cluster.secoff:
+
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_next_cluster.read_fat:
+
+ push es
+ push bx
+
+ ;mov bx, (Mem.Stage2 >> 4) - HEX (40)
+ ;mov es, bx
+ ;xor bx, bx
+
+ mov ax, [bp - 24]
+ mov dx, [bp - 22]
+
+ add ax, si
+ adc dx, 0
+
+ mov cx, 2
+ call _read_sectors
+
+ pop bx
+ pop es
+
+_next_cluster.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, es
+ jnc _next_cluster.first64
+
+ add ax, HEX (1000)
+
+_next_cluster.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+_next_cluster.compare:
+
+ cmp ax, HEX (FFF8)
+ cmc
+
+_next_cluster.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+%endif
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+
+_read_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_read_sectors.retry:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push cx
+ push dx
+
+ div word ptr [_sectors_per_track]
+ ; ax = LBA / SPT
+ ; dx = LBA % SPT = sector - 1
+
+ xchg cx, dx
+ inc cx
+ ; cx = sector no.
+
+ xor dx, dx
+ div word ptr [_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 ; excess bits of cylinder no. must be 0 anyway
+
+ or cl, ah
+ ; cl = MSB 8...9 of cylinder no. + sector no.
+
+ mov dh, dl
+ ; dh = head no.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, [_drive_no]
+ stc
+ int HEX (13)
+ jnc _read_sectors.success ; CF = 0 if no error
+
+_read_sectors.failure:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ah, ah
+ mov dl, [_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 _read_sectors.retry
+
+_read_sectors.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ mov ax, [_bytes_per_sector]
+ mov cl, 4
+ shr ax, cl
+
+ mov cx, es
+ add cx, ax
+ mov es, cx
+
+_read_sectors.no_incr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 _read_sectors.next
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Entry.Filename: db "FREELDR SYS"
+Entry.Filename.Length: equ ($ - Entry.Filename)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pad until 510 bytes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+db HEX (01FE) - (. - _start) dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Boot signature.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+dw HEX (AA55)
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: freeldr.sys
+
+clean:
+ for f in *.o; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ for f in *.lst; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ if [ -f freeldr.sys ]; then rm -rf freeldr.sys; fi
+
+freeldr.sys: bootstrap.o config.o crlf.o disk.o error.o fat.o file.o freeldr.o int21.o ll.o mangle.o mem.o menu.o screen.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o xmalloc.o xrealloc.o ../libc/libc.a
+ ../../../utils/binutils/slink --oformat binary -o $@ $^
+
+%.o: %.asm
+ ../../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: freeldr.sys
+
+clean:
+ for %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ for %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
+ if exist freeldr.sys ( del /q freeldr.sys )
+
+freeldr.sys: bootstrap.o config.o crlf.o disk.o error.o fat.o file.o freeldr.o int21.o ll.o mangle.o mem.o menu.o screen.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o xmalloc.o xrealloc.o ../libc/libc.a
+ ../../../utils/binutils/slink --oformat binary -o $@ $^
+
+%.o: %.asm
+ ../../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file bootstrap.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory layout.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Mem.Stack.Top: equ HEX (0840)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Define some offsets for the BPB.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _bytes_per_sector (bp - 64)
+%define _sectors_per_cluster (bp - 62)
+%define _reserved_sectors (bp - 61)
+%define _number_of_fats (bp - 59)
+%define _root_entries (bp - 58)
+%define _total_sectors16 (bp - 56)
+%define _media_descriptor (bp - 54)
+%define _sectors_per_fat (bp - 53)
+%define _sectors_per_track (bp - 51)
+%define _heads_per_cylinder (bp - 49)
+%define _hidden_sectors (bp - 47)
+%define _total_sectors32 (bp - 43)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; FAT32 EBPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _sectors_per_fat32 (bp - 39)
+%define _root_cluster (bp - 35)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Other offsets used within this file.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _edd_available (bp - 28)
+%define _drive_no (bp - 26)
+
+%define _fat_start (bp - 24)
+%define _data_start (bp - 20)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; FAT32 offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _fat_secmask (bp - 16)
+%define _fat_secshift (bp - 14)
+%define _fat_sector (bp - 12)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Offsets of FAT12 and FAT16 convert cluster and next cluster functions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _convert_cluster (bp - 8)
+%define _next_cluster (bp - 6)
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and cx register as well as the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push cx
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the convertional memory (in KBs) ...
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; ... And convert it into 16-byte paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, 6
+ shl ax, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reserve memory for a stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, (Mem.Stack.Top >> 4)
+ sub ax, cx
+
+ mov di, ax
+
+ popf
+ pop cx
+ pop ax
+
+ mov ss, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base and stack pointers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, Mem.Stack.Top
+ lea sp, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no. passed to us.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax, bx, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push dx
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Transfer the drive no. into the dl register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dl, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure our edd_avaiable variable is zero by default.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [_edd_available], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Only check if we're booted from a hard disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test dl, HEX (70)
+ jnz _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (41)
+ mov bx, HEX (55AA)
+ stc
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then disk extensions a unavailable.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Bit 1 in the cx register should be set if disk extensions
+ ;; are present.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ shr cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Test for carry (from shr) too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sbb bx, HEX (AA55) - 1
+ jne _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indicate that we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [_edd_available], 1
+
+_no_edd:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax, bx, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ popf
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and si register as they
+ ;; get clobbered by movsb.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push si
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB just above the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, ss
+ mov es, di
+
+ mov si, 11
+ lea di, [bp - 64]
+
+ mov cx, 25
+ rep movsb
+
+ cmp byte ptr [HEX (01)], HEX (58)
+ jne _not_fat32
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we get here then we're dealing with FAT32, so first
+ ;; preserve the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the number of sectors per FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [HEX (24)]
+ stosw
+
+ mov ax, [HEX (26)]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the root cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [HEX (2C)]
+ stosw
+
+ mov ax, [HEX (2E)]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+ push ax
+ push dx
+
+_calc_offsets:
+
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_fat_start], si
+ mov [_fat_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+
+ push ax
+
+ mul word ptr [_sectors_per_fat32 + 2]
+ add di, ax
+
+ pop ax
+ mul word ptr [_sectors_per_fat32]
+
+ add ax, si
+ adc dx, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_data_start], ax
+ mov [_data_start + 2], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+ pop di
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [_bytes_per_sector]
+ shr ax
+ shr ax
+ dec ax
+
+ mov [_fat_secmask], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+
+ xchg ax, cx
+ inc cx
+
+_secshift:
+
+ inc ax
+ shr cx
+
+ cmp cx, 1
+ jne _secshift
+
+ mov [_fat_secshift], ax
+ dec cx
+
+ mov [_fat_sector], cx
+ mov [_fat_sector + 2], cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_after_copy:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ popf
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers (need as _next_cluster pops both).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L6
+
+.L4:
+
+ push dx
+ push ax
+ push bx
+
+ call _convert_cluster32
+ jc .L7
+
+ mov cx, bx
+ pop bx
+
+.L5:
+
+ call _read_sectors
+
+.L6:
+
+ pop ax
+ pop dx
+
+ call _nextcluster_fat32
+ jmp short .L4
+
+.L7:
+
+ pop bx
+ pop ax
+ pop dx
+
+ mov cl, 4
+ shr bx, cl
+
+ mov cx, es
+ add cx, bx
+ mov es, cx
+
+ xor dh, dh
+ mov dl, [_drive_no]
+
+ xor bx, bx
+ stc
+
+ jmp _all_read
+
+;******************************************************************************
+; @function _not_fat32
+;******************************************************************************
+_not_fat32:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push ax
+ push dx
+
+ xor ax, ax
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset ready for the fathelper at the start of
+ ;; freeldr.sys.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_fat_start], si
+ mov [_fat_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+ mul word ptr [_sectors_per_fat]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr [_root_entries]
+ div word ptr [_bytes_per_sector]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_data_start], si
+ mov [_data_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+ pop di
+
+ popf
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Previded we've got a clean stack, the carry flag should be set from
+ ;; the boot sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc .L3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the address of the next cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _getfattype
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers (need as _next_cluster pops both).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L1
+
+.L2:
+
+ push dx
+ push ax
+ push bx
+
+ call [_convert_cluster]
+ jc .L3
+
+ mov cx, bx
+ pop bx
+
+.L8:
+
+ push bp
+ push ax
+ push bx
+
+ mov ax, HEX (0E2E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop ax
+ pop bp
+ call _read_sectors
+
+.L1:
+
+ pop ax
+ pop dx
+
+ call [_next_cluster]
+ jmp short .L2
+
+.L3:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the screen.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ xor cx, cx
+ mov dx, HEX (184F)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the cursor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the value in the bx register to a segment and add
+ ;; it to the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, 4
+ shr bx, cl
+
+ mov cx, es
+ add cx, bx
+ mov es, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Pass the drive no. in dl.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dh, dh
+ mov dl, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor bx, bx
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to the main code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _all_read
+
+;******************************************************************************
+; @function _convert_cluster12
+;******************************************************************************
+_convert_cluster12:
+
+ cmp ax, HEX (0FF8)
+ jb _convert_cluster12.c3
+
+ stc
+ ret
+
+_convert_cluster12.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [_data_start]
+ add dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster16
+;******************************************************************************
+_convert_cluster16:
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster16.c3
+
+ stc
+ ret
+
+_convert_cluster16.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [_data_start]
+ add dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster32
+;******************************************************************************
+_convert_cluster32:
+
+ cmp dx, HEX (0FFF)
+ jne _convert_cluster32.c3
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster32.c3
+
+ stc
+ ret
+
+_convert_cluster32.c3:
+
+ mov cx, dx
+
+ sub ax, 2
+ sbb cx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ xchg cx, ax
+ mul bx
+
+ xchg ax, cx
+ mul bx
+
+ add dx, cx
+
+ add ax, [_data_start]
+ adc dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _getfattype
+;******************************************************************************
+_getfattype:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ xor ax, ax
+
+_getfattype.init:
+
+ mov al, [_sectors_per_cluster]
+ cbw
+ mov si, ax
+
+ mov di, [_bytes_per_sector]
+
+ xor dx, dx
+ xor cx, cx
+
+ mov ax, [_total_sectors16]
+ and ax, ax
+ jnz _getfattype.have_secs
+
+ mov ax, [_total_sectors32]
+ mov dx, [_total_sectors32 + 2]
+
+_getfattype.have_secs:
+
+ sub ax, [_reserved_sectors]
+ sbb dx, 0
+
+ mov cl, [_number_of_fats]
+
+_getfattype.sec_fat_loop:
+
+ sub ax, [_sectors_per_fat]
+ sbb dx, 0
+ loop _getfattype.sec_fat_loop
+
+ push ax
+ push dx
+
+ mov ax, [_root_entries]
+ mov bx, 32
+ mul bx
+
+ add ax, di
+ adc dx, 0
+
+ sub ax, 1
+ sbb dx, 0
+
+ div di
+ mov bx, ax
+
+ pop dx
+ pop ax
+
+ sub ax, bx
+ sbb dx, 0
+
+ div si
+
+ cmp ax, 4096
+ ja _getfattype.fat16
+
+_getfattype.fat12:
+
+ mov ax, offset _convert_cluster12
+ mov [_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat12
+ mov [_next_cluster], ax
+
+ jmp short _getfattype.done
+
+_getfattype.fat16:
+
+ mov ax, offset _convert_cluster16
+ mov [_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat16
+ mov [_next_cluster], ax
+
+_getfattype.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat12
+;******************************************************************************
+_nextcluster_fat12:
+
+ push cx
+ push si
+
+ mov si, ax
+
+_nextcluster_fat12.secoff:
+
+ mov ax, 3
+ mul si
+ shr ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat12.read_fat:
+
+ push es
+ push bx
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ mov ax, [_fat_start]
+ mov dx, [_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat12.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat12.cn_exit
+
+_nextcluster_fat12.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat12.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat12.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, ss
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _nextcluster_fat12.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_nextcluster_fat12.even_cluster:
+
+ and ax, HEX (0FFF)
+
+_nextcluster_fat12.compare:
+
+ cmp ax, HEX (0FF8)
+ cmc
+
+_nextcluster_fat12.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat16
+;******************************************************************************
+_nextcluster_fat16:
+
+ push cx
+ push si
+
+_nextcluster_fat16.secoff:
+
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat16.read_fat:
+
+ push es
+ push bx
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ mov ax, [_fat_start]
+ mov dx, [_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat16.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat16.cn_exit
+
+_nextcluster_fat16.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat16.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat16.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, ss
+ jnc _nextcluster_fat16.first64
+
+ add ax, HEX (1000)
+
+_nextcluster_fat16.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+_nextcluster_fat16.compare:
+
+ cmp ax, HEX (FFF8)
+ cmc
+
+_nextcluster_fat16.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat32
+;******************************************************************************
+_nextcluster_fat32:
+
+ push es
+ push bx
+ push cx
+ push di
+
+ mov di, ax
+ and di, [_fat_secmask]
+
+ mov cx, [_fat_secshift]
+
+_nextcluster_fat32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _nextcluster_fat32.cn_loop
+
+ shl di
+ shl di
+
+ add ax, [_fat_start]
+ adc dx, [_fat_start + 2]
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat32.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat32.cn_exit
+
+_nextcluster_fat32.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 1
+ call _read_sectors
+
+_nextcluster_fat32.cn_exit:
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ cmp dx, HEX (0FFF)
+ jne _nextcluster_fat32.no_carry
+
+ cmp ax, HEX (FFF8)
+ jb _nextcluster_fat32.no_carry
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ stc
+ ret
+
+_nextcluster_fat32.no_carry:
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+
+_read_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_read_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 [_edd_available], 1
+ jb _read_sectors.chs
+
+_read_sectors.lba:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll create the LBA read 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, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need to set si to sp as the LBA read 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
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (42)
+ 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 read the sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _read_sectors.success
+
+_read_sectors.chs:
+
+ div word ptr [_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 [_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.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, [_drive_no]
+ stc
+ int HEX (13)
+ jnc _read_sectors.success
+
+_read_sectors.failure:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ah, ah
+ mov dl, [_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 _read_sectors.retry
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ add bx, [_bytes_per_sector]
+ jnc _read_sectors.no_incr
+
+ mov cx, es
+ add ch, HEX (10)
+ mov es, cx
+
+_read_sectors.no_incr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 _read_sectors.next
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, 4
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (0E)
+
+ push bp
+ push bx
+
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop bp
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Make sure we fit inside 2048 bytes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+db HEX (0800) - (. - _start) dup (0)
--- /dev/null
+;******************************************************************************
+; @file config.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _get_command
+;******************************************************************************
+_get_command:
+
+ push ax
+ push cx
+
+ xor ax, ax
+ xor bx, bx
+
+_get_command.loop:
+
+ call _is_name_part
+ jc _get_command.done
+
+ mov cl, 5
+ rol bx, cl
+
+ lodsb
+
+ or al, HEX (20)
+ xor bx, ax
+
+ jmp _get_command.loop
+
+_get_command.done:
+
+ pop cx
+ pop ax
+
+ ret
+
+;******************************************************************************
+; @function _is_name_beginner
+;******************************************************************************
+_is_name_beginner:
+
+ push ax
+
+_is_name_beginner.check:
+
+ lodsb
+
+ cmp al, '.'
+ je .L2
+
+ cmp al, '_'
+ je .L2
+
+ cmp al, 'z'
+ ja .L1
+
+ cmp al, 'a'
+ jae .L2
+
+ cmp al, 'Z'
+ ja .L1
+
+ cmp al, 'A'
+ jae .L2
+
+.L1:
+
+ pop ax
+ dec si
+
+ stc
+ ret
+
+.L2:
+
+ pop ax
+ dec si
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _is_name_part
+;******************************************************************************
+_is_name_part:
+
+ push ax
+
+_is_name_part.check:
+
+ lodsb
+
+ cmp al, '.'
+ je .L4
+
+ cmp al, '_'
+ je .L4
+
+ cmp al, 'z'
+ ja .L3
+
+ cmp al, 'a'
+ jae .L4
+
+ cmp al, 'Z'
+ ja .L3
+
+ cmp al, 'A'
+ jae .L4
+
+ cmp al, '9'
+ ja .L3
+
+ cmp al, '0'
+ jae .L4
+
+.L3:
+
+ pop ax
+ dec si
+
+ stc
+ ret
+
+.L4:
+
+ pop ax
+ dec si
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _is_digit
+;******************************************************************************
+_is_digit:
+
+ push ax
+
+_is_digit.check:
+
+ lodsb
+
+ cmp al, '0'
+ jb .L6
+
+ cmp al, '9'
+ ja .L6
+
+.L5:
+
+ pop ax
+ dec si
+
+ clc
+ ret
+
+.L6:
+
+ pop ax
+ dec si
+
+ stc
+ ret
+
+;******************************************************************************
+; @function _skip_whitespace
+;******************************************************************************
+_skip_whitespace:
+
+ push ax
+
+_skip_whitespace.loop:
+
+ lodsb
+
+ cmp al, ' '
+ je _skip_whitespace.loop
+
+ cmp al, '\t'
+ je _skip_whitespace.loop
+
+_skip_whitespace.done:
+
+ dec si
+
+ pop ax
+ ret
+
+
+;******************************************************************************
+; @function _pc_default
+;******************************************************************************
+_pc_default:
+
+ push ax
+ push bx
+ push cx
+
+ xor ax, ax
+ xor bx, bx
+ mov cx, 5
+
+ call _is_name_beginner
+ jc _pc_default.done
+
+_pc_default.loop:
+
+ call _is_name_part
+ jc _pc_default.done
+
+ lodsb
+
+ rol bx, cl
+ xor bx, ax
+
+ jmp _pc_default.loop
+
+_pc_default.done:
+
+ mov cs:[_pc_menu_default], bx
+
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _pc_kernel
+;******************************************************************************
+_pc_kernel:
+
+ push ax
+ push bx
+
+_pc_kernel.init:
+
+ mov bx, si
+
+_pc_kernel.next:
+
+ lodsb
+
+ and al, al
+ je _pc_kernel.unget
+
+ cmp al, HEX (0A)
+ je _pc_kernel.unget
+
+ cmp al, ' '
+ je _pc_kernel.unget
+
+ jmp short _pc_kernel.next
+
+_pc_kernel.unget:
+
+ dec si
+
+ cmp word ptr cs:[_curr_entry], 0
+ jne _pc_kernel.alloc
+
+ push ax
+ push bx
+ push dx
+ push ds
+
+ mov bx, cs
+ mov ds, bx
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ mov bx, offset _error_kernel_without_label
+ call _writestr
+
+ pop ds
+ pop dx
+ pop bx
+ pop ax
+ jmp _pc_kernel.done
+
+_pc_kernel.alloc:
+
+ mov ax, si
+ sub ax, bx
+ xor dx, dx
+
+ add ax, 1
+ adc dx, 0
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ push di
+ push es
+
+ mov di, cs:[_curr_entry]
+ mov es, di
+ xor di, di
+
+ mov es:[di + 4], ax
+ pop es
+ pop di
+
+ push si
+ push di
+ push es
+ push ds
+
+ mov es, ax
+ xor di, di
+
+ mov ah, [si]
+ mov byte ptr [si], 0
+
+ mov si, bx
+
+_pc_kernel.copy:
+
+ lodsb
+
+ or al, al
+ jz _pc_kernel.all_copied
+
+ stosb
+ jmp short _pc_kernel.copy
+
+_pc_kernel.all_copied:
+
+ xor al, al
+ stosb
+
+ pop ds
+ pop es
+ pop di
+ pop si
+
+ mov [si], ah
+
+_pc_kernel.done:
+
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _pc_label
+;******************************************************************************
+_pc_label:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ xor ax, ax
+ xor bx, bx
+ mov cx, 5
+
+ call _is_name_beginner
+ jc _pc_label.done
+
+_pc_label.loop:
+
+ call _is_name_part
+ jc _pc_label.check
+
+ lodsb
+
+ rol bx, cl
+ xor bx, ax
+
+ jmp _pc_label.loop
+
+_pc_label.check:
+
+ mov cx, cs:[_vec_seen_hashes + 4]
+ xor di, di
+
+_pc_label.check_loop:
+
+ and cx, cx
+ jz _pc_label.alloc
+
+ mov ax, cs:[_vec_seen_hashes + 0]
+ mov es, ax
+ xor di, di
+
+ mov ax, es:[di]
+ add di, 2
+
+ cmp ax, bx
+ je _pc_label.collision
+
+ dec cx
+ jmp _pc_label.check_loop
+
+_pc_label.alloc:
+
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov ax, bx
+ push ax
+
+ mov ax, offset _vec_seen_hashes
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+ pop ds
+
+ mov ax, 16
+ xor dx, dx
+
+ push ds
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ mov cs:[_curr_entry], ax
+ push ax
+
+ mov es, ax
+ xor di, di
+
+ mov ax, bx
+ stosw
+
+ mov ax, offset _menu_entries
+ push ax
+
+ mov ax, cs
+ mov ds, ax
+
+ call _vec_push
+ add sp, 4
+
+ pop ds
+
+ cmp cs:[_pc_menu_default], bx
+ jne _pc_label.done
+
+ mov ax, cs:[_menu_entries + 4]
+ dec ax
+ mov cs:[_menu_default], ax
+
+_pc_label.done:
+
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+_pc_label.collision:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ call _error
+ db "duplicate entry name found", HEX (0D), HEX (0A), HEX (00)
+
+;******************************************************************************
+; @function _pc_timeout
+;******************************************************************************
+_pc_timeout:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ xor ax, ax
+ xor bx, bx
+ xor dx, dx
+
+ mov cx, 10
+ xor di, di
+
+_pc_timeout.convert:
+
+ call _is_digit
+ jc _pc_timeout.done
+
+ lodsb
+ push ax
+
+ mov ax, di
+ mul cx
+ mov di, ax
+
+ pop ax
+
+ test dx, dx
+ jnz _pc_timeout.cap
+
+ sub al, '0'
+ add di, ax
+
+ cmp di, 60
+ jb _pc_timeout.convert
+
+_pc_timeout.check:
+
+ cmp di, 60
+ jbe _pc_timeout.done
+
+_pc_timeout.cap:
+
+ mov di, 60
+
+_pc_timeout.done:
+
+ mov cs:[_menu_timeout], di
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _pc_title
+;******************************************************************************
+_pc_title:
+
+ push ax
+ push bx
+
+_pc_title.init:
+
+ mov bx, si
+
+_pc_title.next:
+
+ lodsb
+
+ and al, al
+ je _pc_title.unget
+
+ cmp al, HEX (0A)
+ je _pc_title.unget
+
+ jmp short _pc_title.next
+
+_pc_title.unget:
+
+ dec si
+
+ cmp word ptr cs:[_curr_entry], 0
+ jne _pc_title.alloc
+
+ push ax
+ push bx
+ push dx
+ push ds
+
+ mov bx, cs
+ mov ds, bx
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ mov bx, offset _error_title_without_label
+ call _writestr
+
+ pop ds
+ pop dx
+ pop bx
+ pop ax
+ jmp _pc_title.done
+
+_pc_title.alloc:
+
+ mov ax, si
+ sub ax, bx
+ xor dx, dx
+
+ add ax, 1
+ adc dx, 0
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ push di
+ push es
+
+ mov di, cs:[_curr_entry]
+ mov es, di
+ xor di, di
+
+ mov es:[di + 2], ax
+ pop es
+ pop di
+
+ push si
+ push di
+ push es
+ push ds
+
+ mov es, ax
+ xor di, di
+
+ mov ah, [si]
+ mov byte ptr [si], 0
+
+ mov si, bx
+
+_pc_title.copy:
+
+ lodsb
+
+ or al, al
+ jz _pc_title.all_copied
+
+ stosb
+ jmp short _pc_title.copy
+
+_pc_title.all_copied:
+
+ xor al, al
+ stosb
+
+ pop ds
+ pop es
+ pop di
+ pop si
+
+ mov [si], ah
+
+_pc_title.done:
+
+ pop bx
+ pop ax
+ ret
+
+
+;******************************************************************************
+; @function _parse_config
+;******************************************************************************
+global _parse_config
+_parse_config:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 4
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ mov ax, word ptr [bp + 4]
+ mov cs:[_filename], ax
+
+ mov word ptr [bp - 2], 0
+
+ call _load_line_create_internal_data
+
+ and ax, ax
+ jz _parse_config.done
+
+ mov word ptr [bp - 4], ax
+
+_parse_config.read_line:
+
+ mov ax, word ptr [bp - 4]
+ push ax
+
+ mov ax, word ptr [bp + 6]
+ push ax
+
+ xor ax, ax
+ push ax
+ push ax
+
+ mov ax, offset _line
+ push ax
+
+ call _load_line
+ add sp, 10
+
+ and ax, ax
+ jnz _parse_config.cleanup
+
+ add word ptr cs:[_line_number], 1
+
+_parse_config.got_line:
+
+ push ds
+
+ mov ax, [_line]
+ mov ds, ax
+ xor si, si
+
+ call _skip_whitespace
+
+ call _is_name_beginner
+ jc _parse_config.check_eof
+
+ call _get_command
+
+_parse_config.find:
+
+ push cx
+ push si
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov si, offset _pc_keywd_table
+ mov cx, offset _pc_keywd_count
+
+_parse_config.search:
+
+ lodsw
+
+ cmp bx, ax
+ je _parse_config.found
+
+ lodsw
+ lodsw
+ loop _parse_config.search
+
+ inc word ptr [bp - 2]
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ push ax
+ push dx
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ pop dx
+ pop ax
+
+ mov bx, offset _error_badcfg
+ call _writestr
+
+ pop ds
+ pop si
+ pop cx
+ jmp _parse_config.next
+
+_parse_config.found:
+
+ lodsw
+ lodsw
+
+ mov bx, ax
+ pop ds
+ pop si
+ pop cx
+
+ call _skip_whitespace
+ mov al, [si]
+
+ and al, al
+ jz _parse_config.noparam
+
+ cmp al, HEX (0A)
+ je _parse_config.noparam
+
+ call bx
+ jmp _parse_config.check_eof
+
+_parse_config.noparam:
+
+ pop ds
+
+ mov ax, cs
+ mov ds, ax
+
+ inc word ptr [bp - 2]
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ push ax
+ push dx
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ pop dx
+ pop ax
+
+ mov bx, offset _error_noparam
+ call _writestr
+
+ jmp _parse_config.read_line
+
+_parse_config.check_eof:
+
+ call _skip_whitespace
+ lodsb
+
+ and al, al
+ jz _parse_config.next
+
+ cmp al, HEX (0A)
+ je _parse_config.next
+
+ inc word ptr [bp - 2]
+ pop ds
+
+ mov bx, cs:[_filename]
+ call _writestr
+
+ push ax
+ push dx
+
+ mov al, ':'
+ call _writechr
+
+ mov ax, cs:[_line_number]
+ xor dx, dx
+ call _writedec
+
+ mov al, ':'
+ call _writechr
+
+ mov al, ' '
+ call _writechr
+
+ pop dx
+ pop ax
+
+ mov bx, offset _error_junk
+ mov [bx + 6], al
+
+ call _writestr
+ jmp _parse_config.read_line
+
+_parse_config.next:
+
+ pop ds
+ jmp _parse_config.read_line
+
+_parse_config.cleanup:
+
+ push word ptr [bp - 4]
+
+ call _load_line_destroy_internal_data
+ add sp, 2
+
+_parse_config.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 4
+ clc
+
+ and ax, ax
+ jz _parse_config.got_carry
+
+ stc
+
+_parse_config.got_carry:
+
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_error_kernel_without_label: db "kernel specified outside label", HEX (0D), HEX (0A), HEX (00)
+_error_title_without_label: db "title specified outside label", HEX (0D), HEX (0A), HEX (00)
+
+_error_noparam: db "missing parameter in lilo.cfg", HEX (0D), HEX (0A), HEX (00)
+_error_badcfg: db "unknown keyword in lilo.cfg", HEX (0D), HEX (0A), HEX (00)
+_error_junk: db "junk '", HEX (00), "' at the end of line", HEX (0D), HEX (0A), HEX (00)
+
+_filename: dw HEX (0000)
+_line_number: dw HEX (0000)
+
+_curr_entry: dw HEX (0000)
+_line: dw HEX (0000)
+
+_pc_menu_default: dw HEX (0000)
+_vec_seen_hashes: db HEX (0006) dup (0)
+
+%include "../kwdhash.gen"
+_pc_keywd_size: equ 6
+
+align 4
+_pc_keywd_table:
+
+ dw hash_default
+ dw 0
+ dw _pc_default
+
+ dw hash_kernel
+ dw 0
+ dw _pc_kernel
+
+ dw hash_label
+ dw 0
+ dw _pc_label
+
+ dw hash_timeout
+ dw 0
+ dw _pc_timeout
+
+ dw hash_title
+ dw 0
+ dw _pc_title
+
+_pc_keywd_count: equ ($ - _pc_keywd_table) / _pc_keywd_size
--- /dev/null
+;******************************************************************************
+; @file crlf.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _crlf
+;******************************************************************************
+global _crlf
+_crlf:
+
+ push ax
+ push bx
+ push dx
+ push bp
+
+ mov ah, HEX (0E)
+ mov al, HEX (0D)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ mov ah, HEX (0E)
+ mov al, HEX (0A)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bp
+ pop dx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file disk.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+global _read_sectors
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+_read_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_read_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 _read_sectors.chs
+
+_read_sectors.lba:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll create the LBA read 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 read 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
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (42)
+ 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 read the sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _read_sectors.success
+
+_read_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.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, cs:[_drive_no]
+ stc
+ int HEX (13)
+ jnc _read_sectors.success
+
+_read_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 _read_sectors.retry
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the bytes per sector to bx to get the next offset to read 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 _read_sectors.next
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _drive_no
+_drive_no: db HEX (00)
+
+global _edd_available
+_edd_available: dw HEX (0000)
+
+global _disk_scratch
+_disk_scratch: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file _error.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _error
+;******************************************************************************
+global _error
+_error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the address of the string from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump passed printing so that we get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _error.next
+
+_error.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character using int 21/ah=02.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_error.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _error.print
+
+_error.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Wait for a keypress.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ int HEX (16)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Stop floppy motor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, HEX (03F2)
+ xor al, al
+ out dx, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0003)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cold reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov bx, HEX (0472)
+ mov word ptr es:[bx], 0
+
+ jmp HEX (F000) : HEX (FFF0)
--- /dev/null
+;******************************************************************************
+; @file fat.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _convert_cluster12
+;******************************************************************************
+global _convert_cluster12
+_convert_cluster12:
+
+ cmp ax, HEX (0FF8)
+ jb _convert_cluster12.c3
+
+ stc
+ ret
+
+_convert_cluster12.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster16
+;******************************************************************************
+global _convert_cluster16
+_convert_cluster16:
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster16.c3
+
+ stc
+ ret
+
+_convert_cluster16.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster32
+;******************************************************************************
+global _convert_cluster32
+_convert_cluster32:
+
+ cmp dx, HEX (0FFF)
+ jne _convert_cluster32.c3
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster32.c3
+
+ stc
+ ret
+
+_convert_cluster32.c3:
+
+ mov cx, dx
+
+ sub ax, 2
+ sbb cx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ xchg cx, ax
+ mul bx
+
+ xchg ax, cx
+ mul bx
+
+ add dx, cx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat12
+;******************************************************************************
+global _nextcluster_fat12
+_nextcluster_fat12:
+
+ push cx
+ push si
+
+ mov si, ax
+
+_nextcluster_fat12.secoff:
+
+ 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
+
+_nextcluster_fat12.read_fat:
+
+ push es
+ push bx
+
+ 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
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat12.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat12.cn_exit
+
+_nextcluster_fat12.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat12.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat12.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, cs:[_fat_seg]
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _nextcluster_fat12.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_nextcluster_fat12.even_cluster:
+
+ and ax, HEX (0FFF)
+
+_nextcluster_fat12.compare:
+
+ cmp ax, HEX (0FF8)
+ cmc
+
+_nextcluster_fat12.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat16
+;******************************************************************************
+global _nextcluster_fat16
+_nextcluster_fat16:
+
+ push cx
+ push si
+
+_nextcluster_fat16.secoff:
+
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat16.read_fat:
+
+ push es
+ push bx
+
+ 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
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat16.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat16.cn_exit
+
+_nextcluster_fat16.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat16.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat16.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, cs:[_fat_seg]
+ jnc _nextcluster_fat16.first64
+
+ add ax, HEX (1000)
+
+_nextcluster_fat16.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+_nextcluster_fat16.compare:
+
+ cmp ax, HEX (FFF8)
+ cmc
+
+_nextcluster_fat16.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat32
+;******************************************************************************
+global _nextcluster_fat32
+_nextcluster_fat32:
+
+ push es
+ push bx
+ push cx
+ push di
+
+ mov di, ax
+ and di, cs:[_fat_secmask]
+
+ mov cx, cs:[_fat_secshift]
+
+_nextcluster_fat32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _nextcluster_fat32.cn_loop
+
+ shl di
+ shl di
+
+ add ax, cs:[_fat_start]
+ adc dx, cs:[_fat_start + 2]
+
+ mov bx, cs:[_fat_seg]
+ mov es, bx
+ xor bx, bx
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat32.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat32.cn_exit
+
+_nextcluster_fat32.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 1
+ call _read_sectors
+
+_nextcluster_fat32.cn_exit:
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ cmp dx, HEX (0FFF)
+ jne _nextcluster_fat32.no_carry
+
+ cmp ax, HEX (FFF8)
+ jb _nextcluster_fat32.no_carry
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ stc
+ ret
+
+_nextcluster_fat32.no_carry:
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ clc
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _fat_bpb
+_fat_bpb:
+
+ db 25 dup (0)
+
+global _fat_jump
+_fat_jump:
+
+ db HEX (EB)
+ db HEX (00)
+ db HEX (90)
+
+global _fat_seg
+_fat_seg:
+
+ dw HEX (0000)
+
+global _next_cluster
+_next_cluster:
+
+ dw HEX (0000)
+
+global _convert_cluster
+_convert_cluster:
+
+ dw HEX (0000)
+
+global _fat_secmask
+_fat_secmask:
+
+ dw HEX (0000)
+
+global _fat_secshift
+_fat_secshift:
+
+ dw HEX (0000)
+
+global _fat_sector
+_fat_sector:
+
+ dw HEX (0000)
+
+global _secsperclust
+_secsperclust:
+
+ dw HEX (0000)
+
+global _clustsize
+_clustsize:
+
+ dw HEX (0000)
+
+global _sectors_per_fat32
+_sectors_per_fat32:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _root_cluster
+_root_cluster:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _fat_start
+_fat_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _root_start
+_root_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _data_start
+_data_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
--- /dev/null
+%ifndef _FAT_INC
+%define _FAT_INC
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Offsets into the BPB.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _bytes_per_sector (_fat_bpb + 0)
+%define _sectors_per_cluster (_fat_bpb + 2)
+%define _reserved_sectors (_fat_bpb + 3)
+%define _number_of_fats (_fat_bpb + 5)
+%define _root_entries (_fat_bpb + 6)
+%define _total_sectors16 (_fat_bpb + 8)
+%define _media_descriptor (_fat_bpb + 10)
+%define _sectors_per_fat (_fat_bpb + 11)
+%define _sectors_per_track (_fat_bpb + 13)
+%define _heads_per_cylinder (_fat_bpb + 15)
+%define _hidden_sectors (_fat_bpb + 17)
+%define _total_sectors32 (_fat_bpb + 21)
+
+%endif ; _FAT_INC
--- /dev/null
+;******************************************************************************
+; @file file.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _read_cluster
+;******************************************************************************
+_read_cluster:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer to the stack pointer and reserve
+ ;; some space.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 36
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need to preserve the data segment and the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment and initialize the
+ ;; si register with the offset of our BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+ mov si, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the stack segment and load the
+ ;; address that we're saving at.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss
+ mov es, ax
+ lea di, [bp - 36]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Also save the drive number and the edd flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, cs:[_drive_no]
+ stosb
+
+ mov ax, cs:[_edd_available]
+ stosw
+
+ mov ax, cs:[_fat_start]
+ stosw
+
+ mov ax, cs:[_fat_start + 2]
+ stosw
+
+ mov ax, cs:[_data_start]
+ stosw
+
+ mov ax, cs:[_data_start + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the si register and the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and the si register again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the data segment to the extra segment and add 4 to si.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es
+ mov ds, ax
+ add si, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the extra segment to the code segment and set the di register
+ ;; to the offset of our BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov es, ax
+ mov di, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the si register and the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the drive number and edd available flag from the info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, es:[si + 29]
+ mov cs:[_drive_no], al
+
+ mov ax, es:[si + 44]
+ mov cs:[_fat_start], ax
+
+ mov ax, es:[si + 46]
+ mov cs:[_fat_start + 2], ax
+
+ mov ax, es:[si + 48]
+ mov cs:[_data_start], ax
+
+ mov ax, es:[si + 50]
+ mov cs:[_data_start + 2], ax
+
+ mov ax, es:[si + 52]
+ mov cs:[_edd_available], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_read_cluster.find:
+
+ push si
+
+ mov bx, es:[si + 54]
+
+_read_cluster.walk:
+
+ and ax, ax
+ jz _read_cluster.read
+
+ call bx
+ jnc _read_cluster.found
+
+ pop si
+ pop cx
+ pop bx
+
+ jmp _read_cluster.done
+
+_read_cluster.found:
+
+ dec ax
+ jnz _read_cluster.walk
+
+_read_cluster.read:
+
+ pop si
+ pop dx
+ pop ax
+
+ mov bx, es:[si + 56]
+
+ call bx
+ jc _read_cluster.done
+
+ mov cx, bx
+
+ mov bx, es:[si + 58]
+ mov es, bx
+ xor bx, bx
+
+ call _read_sectors
+
+_read_cluster.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the stack segment and load the
+ ;; address that we stored the BPB too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss
+ mov ds, ax
+ lea si, [bp - 36]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the code segment and initialize the
+ ;; si register with the offset of our BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov es, ax
+ mov di, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the drive number and edd available flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+ mov cs:[_drive_no], al
+
+ lodsw
+ mov cs:[_edd_available], ax
+
+ lodsw
+ mov cs:[_fat_start], ax
+
+ lodsw
+ mov cs:[_fat_start + 2], ax
+
+ lodsw
+ mov cs:[_data_start], ax
+
+ lodsw
+ mov cs:[_data_start + 2], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 36
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _getc
+;******************************************************************************
+_getc:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push si
+
+ mov word ptr [bp - 2], 0
+
+_getc.is_eof:
+
+ mov ax, es:[si + 38]
+ mov dx, es:[si + 40]
+
+ mov cx, ax
+ or cx, dx
+ jz _getc.done
+
+_getc.check:
+
+ cmp dx, es:[si + 36]
+ ja _getc.check2
+
+ cmp dx, es:[si + 36]
+ jne _getc.done
+
+ cmp ax, es:[si + 34]
+ jbe _getc.done
+
+_getc.check2:
+
+ mov ax, es:[si + 34]
+ mov dx, es:[si + 36]
+
+ mov cx, es:[si + 42]
+ div cx
+
+ and dx, dx
+ jnz _getc.loaded
+
+ mov bx, es:[si + 30]
+ mov cx, es:[si + 32]
+ call _read_cluster
+
+_getc.loaded:
+
+ push es
+
+ mov bx, es:[si + 58]
+ mov es, bx
+ mov bx, dx
+ mov al, es:[bx]
+
+ mov bx, ds
+ mov es, bx
+ stosb
+
+ mov bx, es
+ mov ds, bx
+
+ pop es
+ inc word ptr [bp - 2]
+
+ add word ptr es:[si + 34], 1
+ adc word ptr es:[si + 36], 0
+
+_getc.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ clc
+
+ pop bp
+ ret
+
+_getc.error:
+
+ xor ax, ax
+
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ stc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _get_file_handle
+;******************************************************************************
+_get_file_handle:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push es
+
+ mov word ptr [bp - 2], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Intialize the es register with address of our vector entries
+ ;; and zero out bx for the counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs:[_vec_files + 0]
+ mov es, bx
+ xor bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check to see if our vector is empty.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs:[_vec_files + 2]
+
+ and cx, cx
+ jz _get_file_handle.done
+
+_get_file_handle.search:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the vector entry is zero then we have a free entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[bx], 0
+ je _get_file_handle.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add bx, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Increase our counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc word ptr [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ loop _get_file_handle.search
+
+_get_file_handle.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set ax to the index of the file plus 3.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp - 2]
+ add ax, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and clear the carry flag to indicate success.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and eturn to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+
+;******************************************************************************
+; @function _close_file
+;******************************************************************************
+global _close_file
+_close_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push di
+ push si
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _close_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _close_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the correct file offset by subtracting 3.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub bx, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset into our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 we have a free entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[bx], 0
+ jne _close_file.ok
+
+_close_file.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop si
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 6
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_close_file.ok:
+
+ push es
+
+ mov ax, es:[bx]
+ mov es, ax
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Our file handle info contains a pointer to a buffer so free it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[di + 58]
+ push ax
+
+ call _free
+ add sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free our entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+
+ call _free
+ add sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the entry to zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es:[bx], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract 1 from the length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec word ptr cs:[_vec_files + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop si
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Not sure what ax should be so just clear it for now and clear the
+ ;; carray flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _open_file
+;******************************************************************************
+global _open_file
+_open_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with the file name.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out bh and set bl to the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor bh, bh
+ mov bl, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Walk the path until we hit the last '\'.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _walk_path
+ jnc _open_file.found_dir
+
+_open_file.not_found:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 3
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.found_dir:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _open_file.name_error
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then we couldn't find the specified file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _open_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax register should contain information about the file so
+ ;; copy it into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment as the code segment and copy the value
+ ;; in the ax register into the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The info passed back to us from _search_dos_dir should contain the
+ ;; entry type at offset 8 so move that into the cl register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, es:[bx + 8]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Was the entry a file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test cl, HEX (18)
+ jz _open_file.got_file
+
+_open_file.name_error:
+
+ pop bx
+ pop di
+
+_open_file.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 2
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.got_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get an available file info entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _get_file_handle
+ jnc _open_file.got_handle
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 4
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.got_handle:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax register
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate memory for the file info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 64
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ mov es, ax
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value 1 as the first word to indicate that we need
+ ;; to be read
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value in the code segment into the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, cs
+ mov ds, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the si register with the address of our BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB to the file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the drive number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, cs:[_drive_no]
+ stosb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the starting cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 0]
+ stosw
+
+ mov ax, cs:[si + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; File pointer starts at zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the file size.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 4]
+ stosw
+
+ mov ax, cs:[si + 6]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the size of a cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_clustsize]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the FAT start.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_fat_start]
+ stosw
+
+ mov ax, cs:[_fat_start + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the data start.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_data_start]
+ stosw
+
+ mov ax, cs:[_data_start + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store wheither edd features are available.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_edd_available]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the address of our next cluster function.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_next_cluster]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the address of our convert cluster function.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_convert_cluster]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate memory for a buffer that will be used to keep track of
+ ;; the current data read.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_clustsize]
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore ax and re-push it to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ push ax
+
+_open_file.check:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the capacity of our "vector array"?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp ax, cs:[_vec_files + 2]
+ jb _open_file.no_push
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so add the file info to our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+
+ mov bx, offset _vec_files
+ push bx
+
+ call _vec_push
+ add sp, 4
+
+ jmp short _open_file.done
+
+_open_file.no_push:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value that in the extra segment into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the address of our vector array.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs:[_vec_files + 0]
+ mov es, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the dx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiply by two to get the offset into the vector array.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the offset into bx and set it to the value that we copied into
+ ;; the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+ mov es:[bx], si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add one to our vector length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc word ptr cs:[_vec_files + 4]
+
+_open_file.done:
+
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Ckear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _read_file
+;******************************************************************************
+global _read_file
+_read_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the base pointer to the stack pointer and make some room to store
+ ;; some values within this function.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push es
+ push ds
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure our total bytes read is zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 2], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _close_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _close_file.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 _read_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-initialize the extra segment but this time with the address
+ ;; of the vector entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+ mov es, ax
+ xor si, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we're not write-only.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[si + 2], 1
+ je _read_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the buffer offset (dx) into the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, dx
+
+_read_file.loop:
+
+ call _getc
+ jc _read_file.error
+
+ and ax, ax
+ jz _read_file.done
+
+ inc word ptr [bp - 2]
+ loop _read_file.loop
+
+_read_file.done:
+
+ mov ax, [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ 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
+
+_read_file.error:
+
+ mov ax, 6
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ 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.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_vec_files: db 6 dup (0)
--- /dev/null
+;******************************************************************************
+; @file freeldr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory layout.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Mem.Kernel: equ HEX (0600)
+
+;******************************************************************************
+; @function _all_read
+;******************************************************************************
+global _all_read
+_all_read:
+
+ jnc _not_fat32
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the value that's in the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the offset of our _fat_bpb in the di register (where we want to
+ ;; copy the BPB to).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the stack segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load the address of the base pointer minus 64 (start of the BPB).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lea si, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB to our _fat_bpb offset
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy some other variables.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (58)
+ mov [_fat_jump + 1], al
+
+ mov ax, word ptr [bp - 39]
+ mov [_sectors_per_fat32], ax
+
+ mov ax, word ptr [bp - 37]
+ mov [_sectors_per_fat32 + 2], ax
+
+ mov ax, word ptr [bp - 35]
+ mov [_root_cluster], ax
+
+ mov ax, word ptr [bp - 33]
+ mov [_root_cluster + 2], ax
+
+ mov ax, word ptr [bp - 28]
+ mov [_edd_available], ax
+
+ mov ax, word ptr [bp - 24]
+ mov [_fat_start], ax
+
+ mov ax, word ptr [bp - 22]
+ mov [_fat_start + 2], ax
+
+ mov ax, word ptr [bp - 20]
+ mov [_data_start], ax
+
+ mov ax, word ptr [bp - 18]
+ mov [_data_start + 2], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], dl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the stack segment with the value stored in bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ss, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We should only need a little room for the stack so set the
+ ;; stack pointer to 512.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov sp, HEX (0200)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_bytes_per_sector]
+ shr ax
+ shr ax
+ dec ax
+
+ mov cs:[_fat_secmask], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+ xchg ax, cx
+
+.L5:
+
+ inc ax
+ shr cx
+
+ cmp cx, 1
+ jne .L5
+
+ mov cs:[_fat_secshift], ax
+ dec cx
+
+; mov cs:[_fat_sector], cx
+; mov cs:[_fat_sector + 2], cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set our next cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, offset _nextcluster_fat32
+ mov cs:[_next_cluster], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set our convert cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, offset _convert_cluster32
+ mov cs:[_convert_cluster], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to our main code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _real_start
+
+_not_fat32:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the value that's in the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the offset of our _fat_bpb in the di register (where we want to
+ ;; copy the BPB to).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the stack segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load the address of the base pointer minus 64 (start of the BPB).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lea si, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB to our _fat_bpb offset
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], dl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy some other variables.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (3C)
+ mov [_fat_jump + 1], al
+
+ mov ax, word ptr [bp - 28]
+ mov [_edd_available], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the stack segment with the value stored in bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ss, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We should only need a little room for the stack so set the
+ ;; stack pointer to 512.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov sp, HEX (0200)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next cluster FAT type.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ mov al, [_sectors_per_cluster]
+ cbw
+ mov si, ax
+
+ mov di, [_bytes_per_sector]
+
+ xor dx, dx
+ xor cx, cx
+
+ mov ax, [_total_sectors16]
+ and ax, ax
+ jnz .L1
+
+ mov ax, [_total_sectors32]
+ mov dx, [_total_sectors32 + 2]
+
+.L1:
+
+ sub ax, [_reserved_sectors]
+ sbb dx, 0
+
+ mov cl, [_number_of_fats]
+
+.L2:
+
+ sub ax, [_sectors_per_fat]
+ sbb dx, 0
+ loop .L2
+
+ push ax
+ push dx
+
+ mov ax, [_root_entries]
+ mov bx, 32
+ mul bx
+
+ add ax, di
+ adc dx, 0
+
+ sub ax, 1
+ sbb dx, 0
+
+ div di
+ mov bx, ax
+
+ pop dx
+ pop ax
+
+ sub ax, bx
+ sbb dx, 0
+
+ div si
+
+ cmp ax, 4096
+ ja .L3
+
+ mov ax, offset _nextcluster_fat12
+ mov cs:[_next_cluster], ax
+
+ mov ax, offset _convert_cluster12
+ mov cs:[_convert_cluster], ax
+
+ jmp short .L4
+
+.L3:
+
+ mov ax, offset _nextcluster_fat16
+ mov cs:[_next_cluster], ax
+
+ mov ax, offset _convert_cluster16
+ mov cs:[_convert_cluster], ax
+
+.L4:
+
+ xor ax, ax
+ xor dx, dx
+
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ mov [_fat_start], si
+ mov [_fat_start + 2], di
+
+ mov al, [_number_of_fats]
+ cbw
+ mul word ptr [_sectors_per_fat]
+
+ add si, ax
+ adc di, dx
+
+ mov [_root_start], si
+ mov [_root_start + 2], di
+
+ mov ax, 32
+ mul word ptr [_root_entries]
+ div word ptr [_bytes_per_sector]
+
+ add si, ax
+ adc si, dx
+
+ mov [_data_start], si
+ mov [_data_start + 2], di
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ jmp _real_start
+
+;******************************************************************************
+; @function _restore_and_jump
+;******************************************************************************
+_restore_and_jump:
+
+ cld
+
+ mov ax, cs
+ mov ds, ax
+
+ xor ax, ax
+ mov es, ax
+
+ mov si, offset _interrupts_list
+ mov bx, offset _interrupts_list_end
+
+ cli
+
+_restore_and_jump.next:
+
+ cmp si, bx
+ je _restore_and_jump.done
+
+ lodsb
+
+ mov di, ax
+ shl di
+ shl di
+
+ movsw
+ movsw
+
+ jmp short _restore_and_jump.next
+
+_restore_and_jump.done:
+
+ pop di
+ pop es
+ pop ds
+ pop cx
+ pop bx
+ pop ax
+ pop si
+ pop dx
+
+ push es
+ push di
+ retf
+
+;******************************************************************************
+; @function _bootstrap
+;******************************************************************************
+_bootstrap:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment to the segment we'll load the
+ ;; kernel too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, Mem.Kernel >> 4
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the di register and push the segment:offset to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+ push es
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the cluster again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the data from DS:SI to ES:DI.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Transfer registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, dx
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Far jump to execute the kernel.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ retf
+
+_bootstrap_len: equ ($ - offset _bootstrap)
+
+;******************************************************************************
+; @function _clear_kbd
+;******************************************************************************
+_clear_kbd:
+
+ push ax
+
+_clear_kbd.loop:
+
+ mov ah, HEX (01)
+ int HEX (16)
+ jz _clear_kbd.done
+
+ xor ah, ah
+ int HEX (16)
+
+ jmp short _clear_kbd.loop
+
+_clear_kbd.done:
+
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _int19_handler
+;******************************************************************************
+_int19_handler:
+
+ cld
+
+ mov ax, cs
+ mov ds, ax
+
+ xor ax, ax
+ mov es, ax
+
+ mov si, offset _interrupts_list
+ mov bx, offset _interrupts_list_end
+
+ cli
+
+_int19_handler.next:
+
+ cmp si, bx
+ je _int19_handler.done
+
+ lodsb
+
+ mov di, ax
+ shl di
+ shl di
+
+ movsw
+ movsw
+
+ jmp short _int19_handler.next
+
+_int19_handler.done:
+
+ int HEX (19)
+
+;******************************************************************************
+; @function _real_start
+;******************************************************************************
+_real_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure that the keyboard buffer is cleared.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _clear_kbd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the sectors per cluster to a word.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_sectors_per_cluster]
+ cbw
+ mov [_secsperclust], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; How big is a cluster, really?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mul word ptr [_bytes_per_sector]
+ mov [_clustsize], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the screen size.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _adjust_screen
+
+_setup_malloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First we'll move the value in the stack pointer into the ax register
+ ;; and clear the dx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, sp
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Do we have any left over bytes (size % 16).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so we got the right segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jz _segment_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Yep, we have linguring bytes so increase the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the zero flag is set then we have overflowed
+ ;; (greater than 65535 bytes)
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _segment_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Just for good measure set the data segment to the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print an error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "segment overflow", HEX (0D), HEX (0A), HEX (00)
+
+_segment_ok:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Now that we have the amount of segments that the stack pointer takes
+ ;; up we need to add the stack segment to get the first available segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ss
+ add ax, bx
+
+ mov [_free_seg], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the total memory (in KBs) and convert it to paragrahps for the
+ ;; maximum segment value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ mov cl, 6
+ shl ax, cl
+
+ mov [_max_seg], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with our free segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, [_free_seg]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register ready for stosw.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+
+_clear_memory:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we've reached out max segment then we've cleared all our
+ ;; free memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp di, [_max_seg]
+ je _setup_interrupts
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve some registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push cx
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the value in the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll be clearing 128 words (i.e 128 * 2) at a time.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 128
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value in the ax register into es:di unitl cx is zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ rep stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore our registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add 16 to get the next segment.
+ ;;
+ ;; E.g. (0050:00ff -> 0x05ff) + 1 = 0060:0000 -> 0x0600.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, 16
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop back to the clear the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _clear_memory
+
+_setup_interrupts:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts while we set everything up.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Setup si and bx to point to our list and list end.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _interrupts_list
+ mov bx, offset _interrupts_list_end
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+.L6:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we're not at the end of our interrupts list.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp si, bx
+ je .L7
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a byte from DS:SI to the al register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value into the DI register and multiple by 4 to get the
+ ;; correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, ax
+ shl di
+ shl di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the address at the memory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, es:[di]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value of DS:SI to ES:DI.
+ ;;
+ ;; Note: This will increment both the SI and DI registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ movsw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the address we previously got.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [si - 2], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the segment at the memory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, es:[di]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The segment of the new interrupt will be our code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es:[di], cs
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the segment we previously got.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [si], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to the SI register to account for the saved segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop back for the next entry (if there is one).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L6
+
+.L7:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop bx
+ pop ax
+
+_reserve_fat:
+
+ mov ax, [_bytes_per_sector]
+ shl ax
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ mov [_fat_seg], ax
+
+_reserve_scratch:
+
+ mov ax, [_bytes_per_sector]
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ mov [_disk_scratch], ax
+
+_main:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load configuration File.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, offset _freeldr_cfg1
+ push di
+
+ call _fopen
+ add sp, 2
+
+ and ax, ax
+ jnz _config_open
+
+ mov di, offset _freeldr_cfg2
+ push di
+
+ call _fopen
+ add sp, 2
+
+ and ax, ax
+ jnz _config_open
+
+ mov di, offset _freeldr_cfg3
+ push di
+
+ call _fopen
+ add sp, 2
+
+ and ax, ax
+ jnz _config_open
+
+ call _error
+ db "error: failed to find configuration file", HEX (0D), HEX (0A), HEX (00)
+
+_config_open:
+
+ push ax
+ push di
+
+ call _parse_config
+ jnc _config_ok
+
+ add sp, 2
+
+ call _fclose
+ add sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Wait for a keypress.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ int HEX (16)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Stop floppy motor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, HEX (03F2)
+ xor al, al
+ out dx, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0003)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cold reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov bx, HEX (0472)
+ mov word ptr es:[bx], 0
+
+ jmp HEX (F000) : HEX (FFF0)
+
+_config_ok:
+
+ add sp, 2
+
+ call _fclose
+ add sp, 2
+
+ mov cx, cs:[_menu_entries + 4]
+
+ and cx, cx
+ jnz .L8
+
+ call _error
+ db "error: no entries found in config file", HEX (0D), HEX (0A), HEX (00)
+
+.L8:
+
+ call _run_menu
+
+ push ds
+ push es
+
+ mov es, ax
+ xor bx, bx
+
+ mov ax, es:[bx + 4]
+ mov ds, ax
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Walk the path until we hit the last '/'.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _walk_path
+ jc _kernel_not_found
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _name_error
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then we couldn't find the specified file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _kernel_not_found
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax register should contain information about the file so
+ ;; copy it into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment as the code segment and copy the value
+ ;; in the ax register into the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The info passed back to us from _search_dos_dir should contain
+ ;; information about the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, es:[bx + 0]
+ mov cl, es:[bx + 8]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Was the entry a file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test cl, HEX (18)
+ jnz _kernel_not_found
+
+ pop es
+ pop ds
+ jnc _kernel_open
+
+_name_error:
+
+ pop bx
+ pop di
+
+_kernel_not_found:
+
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _error_not_found1
+ call _writestr
+
+ pop ds
+
+ xor bx, bx
+ call _writestr
+
+ pop es
+ pop ds
+
+ mov bx, offset _error_not_found2
+ call _writestr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Wait for a keypress.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ int HEX (16)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Stop floppy motor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, HEX (03F2)
+ xor al, al
+ out dx, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0003)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cold reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov bx, HEX (0472)
+ mov word ptr es:[bx], 0
+
+ jmp HEX (F000) : HEX (FFF0)
+
+_error_not_found1: db "error: kernel '", HEX (00)
+_error_not_found2: db "' not found", HEX (0D), HEX (0A), HEX (00)
+
+_kernel_open:
+
+ mov di, cs:[_clustsize]
+
+ xor dh, dh
+ mov dl, cs:[_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the number of paragrahs of the memory available.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ mov cl, 6
+ shl ax, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract some memory for a stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, HEX (0840) >> 4
+ sub ax, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the cluster size into paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, di
+ shl bx
+ shl bx
+
+ mov cl, 4
+ shr bx, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the segment offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub ax, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store some variable on the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with our calcaulted segment and
+ ;; clear the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ xor bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the cluster into the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the sectors per cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, cs:[_secsperclust]
+
+ cmp si, 4
+ jae .L9
+
+ mov si, 4
+
+.L9:
+
+ push dx
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the cluster into LBA.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call cs:[_convert_cluster]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the sectors per cluster into the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag was set then we've reached the end of the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc .L10
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the cluster into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _read_sectors
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract the sectors per cluster from our counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub si, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add bx, cs:[_clustsize]
+ jnc .L12
+
+ mov cx, es
+ add ch, HEX (10)
+ mov es, cx
+
+.L12:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the count is zero then we're done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz .L10
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the cluster size to di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, cs:[_clustsize]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get next cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call cs:[_next_cluster]
+ jmp .L9
+
+.L10:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Figure out how much space is needed for the BPP and the bootstrap
+ ;; code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, offset _bootstrap_len
+ xor dx, dx
+
+ add ax, 64
+ adc dx, 0
+
+ mov cx, 16
+ div cx
+
+ and dx, dx
+ jz _segment_ok2
+
+ inc ax
+
+_segment_ok2:
+
+ push bx
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We want to copy the information just below where we read the
+ ;; cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ds
+ sub bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the value in the bx register
+ ;; and push it to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the jump.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_fat_jump + 0]
+ stosb
+
+ mov ax, cs:[_fat_jump + 1]
+ stosb
+
+ mov ax, cs:[_fat_jump + 2]
+ stosb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the si register with the address of the BPB info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; As we're mimicking a FAT boot sector we need to make sure
+ ;; di is set to 11 as thats where the BPB actually starts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, 11
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy 25 bytes from DS:SI to ES:DI.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're not FAT32 then jump passed the next couple of copies.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp byte ptr [_fat_jump + 1], HEX (58)
+ jne .L13
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the sectors per FAT (FAT32 only).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_sectors_per_fat32]
+ stosw
+
+ mov ax, cs:[_sectors_per_fat32 + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Flags and version can just be zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the root cluster (FAT32 only).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_root_cluster]
+ stosw
+
+ mov ax, cs:[_root_cluster + 2]
+ stosw
+
+.L13:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the si register with the address of the bootstrap code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _bootstrap
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the code to the new location.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, offset _bootstrap_len
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call to a help function which restores the interrupts, restores
+ ;; the values on the stack and then jumps to the bootstrap code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _restore_and_jump
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_freeldr_cfg1: db "/boot"
+_freeldr_cfg2: db "/freeldr"
+_freeldr_cfg3: db "/freeldr.cfg", HEX (00)
+
+_interrupts_list:
+
+ db HEX (19)
+ dw _int19_handler
+ dw HEX (0000)
+
+ db HEX (21)
+ dw _int21_dispatch
+ dw HEX (0000)
+
+_interrupts_list_end:
--- /dev/null
+;******************************************************************************
+; @file int21.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _int21_dispatch
+;******************************************************************************
+global _int21_dispatch
+_int21_dispatch:
+
+ cld ; Make sure direction flag is always clean
+
+ push bx
+ push bp
+
+ mov bp, offset _int21_dispatch.list
+ mov bx, offset _int21_dispatch.list_end
+
+_int21_dispatch.L:
+
+ cmp bp, bx
+ jae _int21_dispatch.unimpl
+
+ cmp ah, cs:[bp]
+ jne _int21_dispatch.next
+
+ mov bx, cs:[bp + 1]
+
+ mov bp, sp
+ xchg [bp + 2], bx
+
+ pop bp
+ ret
+
+_int21_dispatch.next:
+
+ add bp, 3
+
+ cmp bp, bx
+ jb _int21_dispatch.L
+
+_int21_dispatch.unimpl:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ and dl, dl
+ jz _int21_dispatch.col_ok
+
+ mov al, HEX (0D)
+ call _writechr
+
+ mov al, HEX (0A)
+ call _writechr
+
+_int21_dispatch.col_ok:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Unimplemented syscall.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _int21_dispatch.err
+ call _writestr
+
+ pop ds
+ pop ax
+ push di
+
+ mov word ptr [_writehex_num_digits], 2
+ call _writehex
+ mov word ptr [_writehex_num_digits], 4
+
+ pop di
+ call _crlf
+
+ pop bp
+ pop bx
+ iret
+
+_int21_dispatch.halt:
+
+ hlt
+ jmp short _int21_dispatch.halt
+
+_int21_dispatch.err:
+
+ db "Not implemented: INT 21h/AH=", 0x00
+
+_int21_dispatch.list:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Open File Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3D)
+ dw int21_3D
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Close File Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3E)
+ dw int21_3E
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read From File or Device Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3F)
+ dw int21_3F
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (48)
+ dw int21_48
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free Allocated Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (49)
+ dw int21_49
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Modify Allocated Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4A)
+ dw int21_4A
+
+_int21_dispatch.list_end:
+
+;******************************************************************************
+; @function iretc
+;******************************************************************************
+iretc:
+
+ push bp
+
+ mov bp, sp
+ jc iretc.c
+
+ and byte ptr [bp + 6], HEX (FE) ; clear carry
+ jmp short iretc.ret
+
+iretc.c:
+
+ or byte ptr [bp + 6], 1 ; set carry
+
+iretc.ret:
+
+ pop bp
+ iret
+
+
+;******************************************************************************
+; @function int21_3D
+; @brief Open File Using Handle
+;
+; @in AL -> Open access mode.
+; @in DS:DX -> Pointer to an ASCIIZ file name.
+;
+; @out AX -> File handle. Error code if CF is set.
+;******************************************************************************
+int21_3D:
+
+ call _open_file
+ jmp iretc
+
+;******************************************************************************
+; @function int21_3E
+; @brief Close File Using Handle
+;
+; @in BX -> File handle to close..
+; @out AX -> Clear. Error code if CF is set.
+;******************************************************************************
+int21_3E:
+
+ call _close_file
+ jmp iretc
+
+;******************************************************************************
+; @function int21_3F
+; @brief Read From File or Device Using Handle
+;
+; @in BX -> File handle..
+; @in CX -> Number of bytes to read.
+; @in DS:DX -> Pointer to read buffer.
+;
+; @out AX -> Number of bytes read. Error code if CF is set.
+;******************************************************************************
+int21_3F:
+
+ call _read_file
+ jmp iretc
+
+;******************************************************************************
+; @function int21_48
+; @brief Allocate Memory Blocks
+;
+; @in BX -> Number of memory paragraphs requested.
+;
+; @out AX -> Segment address of allocated memory block
+; (MCB + lpara). Error code if CF is set.
+; @out BX -> Size in paras of the largets block of memory
+; available if CF is set and AX = 08 (Not enough mem).
+;******************************************************************************
+int21_48:
+
+ call _alloc_mem
+ jmp iretc
+
+;******************************************************************************
+; @function int21_49
+; @brief Free Allocated Memeory Blocks
+;
+; @in ES -> Segment of the block to be returned (MCB + lpara).
+; @out AX -> Clear.
+;******************************************************************************
+int21_49:
+
+ call _free_mem
+ jmp iretc
+
+;******************************************************************************
+; @function int21_4A
+; @brief Resize Allocated Memory Blocks
+;
+; @in BX -> New requested block size in paragraphs.
+; @in ES -> Segment of block to resize.
+;
+; @out AX -> Segment address of memory block (MCB + lpara).
+; Error code if CF is set.
+; @out BX -> Set to maximum block size possible if the request
+; block size is greater than what available.
+;******************************************************************************
+int21_4A:
+
+ call _resize_mem
+ jmp iretc
--- /dev/null
+;******************************************************************************
+; @file ll.asm
+;******************************************************************************
+%define CAPACITY_INCREMENT 256
+
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _load_line
+;******************************************************************************
+global _load_line
+_load_line:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 12
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov bx, word ptr [bp + 12]
+
+ and bx, bx
+ jz .L18
+
+ mov cx, ds
+
+ push es
+ push ds
+ push si
+ push di
+
+ mov es, cx
+ mov ds, bx
+
+ mov di, offset _load_line_data
+ xor si, si
+
+ mov cx, 14
+ rep movsb
+
+ pop di
+ pop si
+ pop ds
+ pop es
+
+ mov ax, ss
+ mov es, ax
+
+ xor ax, ax
+ lea di, word ptr [bp - 12]
+
+ mov cx, 12
+ rep stosb
+
+ mov cx, word ptr [_load_line_data + 12]
+
+ and cx, cx
+ jz .L1
+
+ push es
+ push ds
+
+ mov ax, word ptr [_load_line_data + 8]
+ sub ax, word ptr [_load_line_data + 12]
+
+ push ax
+
+ mov ax, word ptr [_load_line_data + 2]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [_load_line_data + 12]
+ adc dx, 0
+
+ div cx
+ push dx
+
+ xor bx, bx
+ push bx
+
+ mov bx, word ptr [_load_line_data + 2]
+ mov es, bx
+
+ mov ds, ax
+
+ call _memmove
+ add sp, 6
+
+ pop ds
+ pop es
+
+ mov cx, word ptr [_load_line_data + 12]
+ sub word ptr [_load_line_data + 8], cx
+
+.L1:
+
+ mov ax, word ptr [_load_line_data + 4]
+
+ cmp ax, word ptr [bp - 12]
+ jb .L2
+
+ cmp ax, word ptr [bp - 8]
+ ja .L3
+
+.L2:
+
+ mov ax, word ptr [_load_line_data + 4]
+ xor dx, dx
+
+ add ax, CAPACITY_INCREMENT
+ mov word ptr [_load_line_data + 4], ax
+
+ mov bx, ax
+ xor cx, cx
+
+ add bx, 2
+ adc cx, 0
+
+ push ax
+ push dx
+
+ push bx
+ push cx
+ push word ptr word ptr [_load_line_data + 0]
+
+ call _xrealloc
+ add sp, 6
+
+ mov word ptr [_load_line_data + 0], ax
+ pop dx
+ pop ax
+
+ mov bx, ax
+ mov cx, dx
+
+ add bx, 1
+ adc cx, 0
+
+ push ax
+ push dx
+
+ push bx
+ push cx
+ push word ptr word ptr [_load_line_data + 2]
+
+ call _xrealloc
+ add sp, 6
+
+ mov word ptr [_load_line_data + 2], ax
+ pop dx
+ pop ax
+
+.L3:
+
+ mov ax, word ptr [_load_line_data + 8]
+
+ cmp ax, word ptr [bp - 8]
+ ja .L4
+
+ push ds
+ push word ptr [bp + 10]
+
+ mov ax, word ptr [_load_line_data + 4]
+ sub ax, word ptr [bp - 8]
+
+ push ax
+
+ mov ax, 1
+ push ax
+
+ mov ax, word ptr [_load_line_data + 2]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [bp - 8]
+ adc dx, 0
+
+ div cx
+
+ mov ds, ax
+ push dx
+
+ call _fread
+ add sp, 8
+
+ pop ds
+ jc .L5
+
+ add ax, word ptr [bp - 8]
+ mov word ptr [_load_line_data + 8], ax
+
+ mov ax, word ptr [_load_line_data + 2]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [_load_line_data + 8]
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ xor al, al
+ mov es:[di], al
+
+ pop di
+ pop es
+
+.L15:
+
+ cmp word ptr [bp - 4], 1
+ jne .L4
+
+.L17:
+
+ mov ax, word ptr [_load_line_data + 8]
+
+ cmp ax, word ptr [bp - 8]
+ jb .L4
+
+ mov ax, word ptr [_load_line_data + 2]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [bp - 8]
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, es:[di]
+ pop di
+ pop es
+
+ cmp bl, HEX (0A)
+ jne .L16
+
+ mov word ptr [bp - 4], 0
+ jmp .L4
+
+.L16:
+
+ add word ptr [bp - 8], 1
+ jmp .L17
+
+.L4:
+
+ mov ax, word ptr [_load_line_data + 8]
+
+ cmp ax, word ptr [bp - 8]
+ jbe .L6
+
+.L10:
+
+ mov ax, word ptr [_load_line_data + 4]
+
+ cmp ax, word ptr [bp - 12]
+ jbe .L6
+
+.L11:
+
+ push es
+ push di
+
+ mov ax, word ptr [_load_line_data + 2]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [bp - 8]
+ adc dx, 0
+
+ div cx
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, es:[di]
+ pop di
+ pop es
+
+ add word ptr [bp - 8], 1
+
+ push es
+ push di
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [bp - 12]
+ adc dx, 0
+
+ div cx
+
+ mov es, ax
+ mov di, dx
+
+ mov es:[di], bl
+
+ pop di
+ pop es
+
+ cmp bl, '#'
+ jne .L14
+
+ mov word ptr [bp - 4], 1
+ jmp .L15
+
+.L14:
+
+ cmp bl, HEX (0A)
+ jne .L7
+
+ mov si, word ptr [bp - 12]
+
+ and si, si
+ jz .L12
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, si
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, es:[di]
+ pop di
+ pop es
+
+ cmp bl, HEX (0D)
+ jne .L13
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, HEX (0A)
+ mov es:[di], bl
+
+ pop di
+ pop es
+
+ mov word ptr [bp - 12], si
+
+.L13:
+
+ and si, si
+ jz .L12
+
+ dec si
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, si
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, es:[di]
+ pop di
+ pop es
+
+ cmp bl, ' '
+ jne .L12
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov bl, HEX (0A)
+ mov es:[di], bl
+
+ pop di
+ pop es
+
+ mov word ptr [bp - 12], si
+ jmp .L13
+
+.L12:
+
+ mov bx, word ptr [bp - 12]
+ inc bx
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, bx
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ xor al, al
+ mov es:[di], al
+
+ pop di
+ pop es
+
+ mov bx, word ptr [bp - 8]
+ mov word ptr [_load_line_data + 12], bx
+
+ mov bx, word ptr [bp + 4]
+
+ mov ax, word ptr [_load_line_data + 0]
+ mov [bx], ax
+
+ jmp .L8
+
+.L7:
+
+ add word ptr [bp - 12], 1
+ jmp .L4
+
+.L6:
+
+ push word ptr [bp + 10]
+
+ call _feof
+ add sp, 2
+
+ and ax, ax
+ jz .L1
+
+ mov cx, word ptr [_load_line_data + 8]
+
+ and cx, cx
+ jz .L5
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, word ptr [bp - 12]
+ adc dx, 0
+
+ div cx
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ mov al, HEX (0A)
+ mov es:[di], al
+
+ pop di
+ pop es
+
+ mov bx, word ptr [bp - 12]
+ inc bx
+
+ mov ax, word ptr [_load_line_data + 0]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ add ax, bx
+ adc dx, 0
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, dx
+
+ xor ax, ax
+ mov es:[di], al
+
+ pop di
+ pop es
+
+ mov word ptr [_load_line_data + 12], ax
+ mov word ptr [_load_line_data + 8], ax
+
+ mov bx, word ptr [bp + 4]
+
+ mov ax, word ptr [_load_line_data + 0]
+ mov [bx], ax
+
+ jmp .L8
+
+.L5:
+
+ mov ax, word ptr [bp + 12]
+ mov es, ax
+
+ mov si, offset _load_line_data
+ xor di, di
+
+ mov cx, 14
+ rep movsb
+
+.L18:
+
+ mov ax, 1
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 12
+ stc
+
+ pop bp
+ ret
+
+.L8:
+
+ mov ax, word ptr [bp + 12]
+ mov es, ax
+
+ mov si, offset _load_line_data
+ xor di, di
+
+ mov cx, 14
+ rep movsb
+
+ xor ax, ax
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 12
+ clc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _load_line_create_internal_data
+;******************************************************************************
+global _load_line_create_internal_data
+_load_line_create_internal_data:
+
+ push ax
+ push dx
+
+.L19:
+
+ mov ax, 16
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+.L20:
+
+ pop dx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _load_line_destroy_internal_data
+;******************************************************************************
+global _load_line_destroy_internal_data
+_load_line_destroy_internal_data:
+
+ push bp
+ mov bp, sp
+
+ push es
+ push bx
+ push si
+
+ mov bx, word ptr [bp + 4]
+
+ and bx, bx
+ jz .L21
+
+ mov es, bx
+ xor bx, bx
+
+ mov si, es:[bx + 0]
+
+ and si, si
+ jz .L22
+
+ push si
+
+ call _free
+ add sp, 2
+
+.L22:
+
+ mov si, es:[bx + 2]
+
+ and si, si
+ jz L23
+
+ push si
+
+ call _free
+ add sp, 2
+
+L23:
+
+ push es
+
+ call _free
+ add sp, 2
+
+.L21:
+
+ pop si
+ pop bx
+ pop es
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_load_line_data: db 14 dup (0)
--- /dev/null
+;******************************************************************************
+; @file mangle.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _mangle_dos_name
+;******************************************************************************
+global _mangle_dos_name
+_mangle_dos_name:
+
+ push ax
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov cx, cs
+ mov es, cx
+
+ mov di, offset _mangled_name
+ mov cx, 11
+
+_mangle_dos_name.loop:
+
+ lodsb
+
+ cmp al, ' '
+ jna _mangle_dos_name.end
+
+ cmp al, '/'
+ je _mangle_dos_name.end
+
+ cmp al, '.'
+ je _mangle_dos_name.is_period
+
+ cmp al, HEX (61)
+ jb _mangle_dos_name.no_conv
+
+ cmp al, HEX (7A)
+ ja _mangle_dos_name.no_conv
+
+ mov dl, HEX (20)
+ not dl
+
+ and al, dl
+
+_mangle_dos_name.no_conv:
+
+ mov bx, offset _invalid_chars
+ mov ah, cl
+
+ cmp ax, HEX (0BE5)
+ jne _mangle_dos_name.check
+
+ mov al, HEX (05)
+
+_mangle_dos_name.check:
+
+ cmp byte ptr cs:[bx], 0
+ je _mangle_dos_name.store
+
+ cmp byte ptr cs:[bx], al
+ je _mangle_dos_name.error
+
+ inc bx
+ jmp short _mangle_dos_name.check
+
+_mangle_dos_name.store:
+
+ stosb
+ loop _mangle_dos_name.loop
+
+_mangle_dos_name.find_end:
+
+ lodsb
+
+ cmp al, ' '
+ jna _mangle_dos_name.end
+
+ cmp al, '/'
+ jne _mangle_dos_name.find_end
+
+_mangle_dos_name.end:
+
+ mov al, ' '
+ rep stosb
+
+_mangle_dos_name.done:
+
+ mov bx, offset _mangled_name
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop ax
+
+ clc
+ ret
+
+_mangle_dos_name.is_period:
+
+ cmp cx, 11
+ jb _mangle_dir.period_check
+
+ mov al, '.'
+ stosb
+
+ dec cx
+ jmp _mangle_dos_name.loop
+
+_mangle_dir.period_check:
+
+ cmp di, offset _mangled_name
+ je _mangle_dir.add_period
+
+ cmp byte ptr es:[di - 1], '.'
+ jne _mangle_dir.need_padding
+
+_mangle_dir.add_period:
+
+ mov al, '.'
+ stosb
+
+ dec cx
+ jmp _mangle_dos_name.loop
+
+_mangle_dir.need_padding:
+
+ mov al, ' '
+
+_mangle_dos_name.period_loop:
+
+ cmp cx, 3
+ jbe _mangle_dos_name.loop
+
+ stosb
+ loop _mangle_dos_name.period_loop
+
+_mangle_dos_name.error:
+
+ mov di, offset _mangled_name
+ xor al, al
+
+ mov cx, 11
+ rep stosb
+
+ mov bx, offset _mangled_name
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop ax
+
+ stc
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_invalid_chars: db "\"*+,:;<=>?[\\]|", HEX (00)
+_mangled_name: db 12 dup (0)
--- /dev/null
+;******************************************************************************
+; @file mem.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _alloc_mem
+;******************************************************************************
+global _alloc_mem
+_alloc_mem:
+
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov ax, cs:[_free_seg]
+ mov es, ax
+
+ push es
+
+ mov ax, bx
+ xor di, di
+
+_alloc_mem.search:
+
+ mov cx, es
+
+ cmp cx, cs:[_free_seg]
+ jb _alloc_mem.error
+
+ cmp cx, cs:[_max_seg]
+ jae _alloc_mem.error
+
+ cmp byte ptr es:[di], 'M'
+ je _alloc_mem.check
+
+ jmp short _alloc_mem.next
+
+_alloc_mem.check:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _alloc_mem.check2
+
+ jmp short _alloc_mem.next
+
+_alloc_mem.check2:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _alloc_mem.retry
+
+_alloc_mem.next:
+
+ mov si, es
+ inc si
+ mov es, si
+
+ dec ax
+ jnz _alloc_mem.search
+
+ cmp byte ptr es:[di], 'M'
+ je _alloc_mem.check3
+
+ cmp si, cs:[_free_seg]
+ jb _alloc_mem.error
+
+ cmp si, cs:[_max_seg]
+ jae _alloc_mem.error
+
+ jmp short _alloc_mem.success
+
+_alloc_mem.check3:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _alloc_mem.check4
+
+ jmp short _alloc_mem.success
+
+_alloc_mem.check4:
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _alloc_mem.success
+
+_alloc_mem.retry:
+
+ mov cx, es:[di + 3]
+ inc cx
+
+ mov si, es
+ add si, cx
+ mov es, si
+
+ pop si
+ push es
+
+ mov ax, bx
+ jmp _alloc_mem.search
+
+_alloc_mem.success:
+
+ xor di, di
+ pop es
+
+ mov byte ptr es:[di], 'M'
+ mov byte ptr es:[di + 1], 'C'
+ mov byte ptr es:[di + 2], 'B'
+
+ mov word ptr es:[di + 3], bx
+ ;mov ax, cs:[_curr_psp]
+ ;mov word ptr es:[di + 5], ax
+
+ mov ax, es
+ inc ax
+
+ clc
+ jmp short _alloc_mem.done
+
+_alloc_mem.error:
+
+ mov bx, es
+ pop ax
+ sub bx, ax
+
+ mov ax, 8
+ stc
+
+_alloc_mem.done:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _free_mem
+;******************************************************************************
+global _free_mem
+_free_mem:
+
+ push bx
+ push cx
+ push di
+ push es
+
+ mov di, es
+
+ and di, di
+ jz _free_mem.error
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _free_mem.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _free_mem.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _free_mem.error
+
+ xor al, al
+ mov cx, 16
+ rep movsb
+
+ xor ax, ax
+ clc
+
+ jmp short _free_mem.done
+
+_free_mem.error:
+
+ mov ax, 9
+ stc
+
+_free_mem.done:
+
+ pop es
+ pop di
+ pop cx
+ pop bx
+ ret
+
+;******************************************************************************
+; @function _resize_mem
+;******************************************************************************
+global _resize_mem
+_resize_mem:
+
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov di, es
+
+ and di, di
+ jz _resize_mem.error
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _resize_mem.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _resize_mem.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _resize_mem.error
+
+ mov cx, word ptr es:[di + 3]
+
+ cmp cx, bx
+ jae _resize_mem.success
+
+ mov di, es
+ add di, cx
+ mov es, di
+
+ mov ax, bx
+ sub ax, cx
+
+ xor di, di
+
+_resize_mem.search:
+
+ mov cx, es
+
+ cmp cx, cs:[_max_seg]
+ jae _resize_mem.ins
+
+ cmp byte ptr es:[di], 'M'
+ je _resize_mem.check
+
+ jmp short _resize_mem.next
+
+_resize_mem.check:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _resize_mem.check2
+
+ jmp short _resize_mem.next
+
+_resize_mem.check2:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _resize_mem.ins
+
+_resize_mem.next:
+
+ mov si, es
+ inc si
+ mov es, si
+
+ dec ax
+ jnz _resize_mem.search
+
+ cmp si, cs:[_max_seg]
+ jae _resize_mem.max
+
+ cmp byte ptr es:[di], 'M'
+ je _resize_mem.check3
+
+ jmp short _resize_mem.success
+
+_resize_mem.check3:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _resize_mem.check4
+
+ jmp short _resize_mem.success
+
+_resize_mem.check4:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _resize_mem.ins
+
+_resize_mem.success:
+
+ pop es
+
+ mov di, es
+ dec di
+ mov es, di
+
+ xor di, di
+ mov word ptr es:[di + 3], bx
+
+ mov di, es
+ inc di
+ mov es, di
+
+ mov ax, es
+ clc
+
+ jmp short _resize_mem.done
+
+_resize_mem.max:
+
+ mov bx, cs:[_max_seg]
+ jmp short _resize_mem.got_seg
+
+_resize_mem.ins:
+
+ mov bx, es
+
+_resize_mem.got_seg:
+
+ pop es
+
+ mov ax, es
+ sub bx, ax
+
+ push es
+
+ mov di, es
+ dec di
+ mov es, di
+
+ xor di, di
+ mov word ptr es:[di + 3], bx
+
+ mov ax, 8
+ stc
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+_resize_mem.error:
+
+ mov ax, 9
+ stc
+
+ pop es
+
+_resize_mem.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _free_seg
+_free_seg: dw HEX (0000)
+
+global _max_seg
+_max_seg: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file menu.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _run_menu_timeout
+;******************************************************************************
+_run_menu_timeout:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push ds
+
+ mov dx, cs:[_menu_timeout]
+
+ xor ax, ax
+ mov ds, ax
+
+ mov bx, HEX (046C)
+
+_run_menu_timeout.sec:
+
+ mov al, dl
+ aam
+ or ax, HEX (3030)
+
+ mov cx, ax
+ push bx
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _menu_footer1
+ call _writestr
+
+ mov al, ch
+ call _writechr
+
+ mov al, cl
+ call _writechr
+
+ mov bx, offset _menu_footer2
+
+ cmp dx, 1
+ jne _run_menu_timeout.got_secs
+
+ mov bx, offset _menu_footer3
+
+_run_menu_timeout.got_secs:
+
+ call _writestr
+
+ cmp dx, 1
+ jne _run_menu_timeout.check
+
+ xor al, al
+ call _writechr
+
+_run_menu_timeout.check:
+
+ mov al, HEX (0D)
+ call _writechr
+
+ pop ds
+ pop bx
+ clc
+
+ dec dx
+ js _run_menu_timeout.done
+
+ mov cx, HEX (12)
+
+_run_menu_timeout.tick:
+
+ mov si, [bx]
+
+_run_menu_timeout.wait:
+
+ stc
+
+ mov ah, HEX (01)
+ int HEX (16)
+ jnz _run_menu_timeout.done
+
+ cmp si, [bx]
+ je _run_menu_timeout.wait
+
+ loop _run_menu_timeout.tick
+ jmp short _run_menu_timeout.sec
+
+_run_menu_timeout.done:
+
+ pop ds
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _convert_entry
+;******************************************************************************
+_convert_entry:
+
+ push bp
+ mov bp, sp
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push es
+ push ds
+
+ mov ax, cs:[_menu_entry_list]
+
+ and ax, ax
+ jz _convert_entry.init
+
+ push es
+ push di
+
+ mov es, ax
+ mov di, cs:[_list_idx]
+
+ mov al, ','
+ stosb
+
+ mov cs:[_list_idx], di
+
+ xor al, al
+ stosb
+
+ pop di
+ pop es
+
+_convert_entry.init:
+
+ mov ax, word ptr [bp + 4]
+ mov es, ax
+ xor bx, bx
+
+ xor ch, ch
+ mov cl, cs:[_video_cols]
+
+ inc cx
+ sub cx, 8
+
+ xor dx, dx
+
+_convert_entry.check:
+
+ mov ax, es:[bx + 2]
+ mov ds, ax
+ xor si, si
+
+ push si
+
+ call _strlen
+ add sp, 2
+
+ cmp ax, cx
+ jbe _convert_entry.length_ok
+
+ mov ax, cx
+
+_convert_entry.length_ok:
+
+ push cx
+ push ax
+ push bx
+ push es
+
+ mov ax, cs:[_menu_entry_list]
+ mov es, ax
+ xor bx, bx
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ pop es
+ pop bx
+ pop ax
+
+ add ax, cx
+ adc dx, 0
+ pop cx
+
+ add ax, 2
+ adc dx, 0
+
+ push ax
+ push dx
+
+ mov ax, cs:[_menu_entry_list]
+ push ax
+
+ call _xrealloc
+ add sp, 6
+
+ mov cs:[_menu_entry_list], ax
+
+ mov es, ax
+ mov di, cs:[_list_idx]
+
+_convert_entry.loop:
+
+ and cx, cx
+ jz _convert_entry.done
+
+ lodsb
+
+ or al, al
+ jz _convert_entry.done
+
+ stosb
+
+ dec cx
+ jmp short _convert_entry.loop
+
+_convert_entry.done:
+
+ mov cs:[_list_idx], di
+
+ xor al, al
+ stosb
+
+ pop ds
+ pop es
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _move_cursor
+;******************************************************************************
+_move_cursor:
+
+ push ax
+ push bx
+
+ mov ah, HEX (02)
+ xor bl, bl
+ int HEX (10)
+
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _draw_black_bar
+;******************************************************************************
+_draw_black_bar:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+_draw_black_bar.move:
+
+ mov dl, 3
+ call _move_cursor
+
+ xor ch, ch
+ mov cl, cs:[_video_cols]
+
+ inc cx
+ sub cx, 3
+
+_draw_black_bar.draw:
+
+ mov ax, HEX (0920)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_draw_black_bar.done:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _draw_white_bar
+;******************************************************************************
+_draw_white_bar:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+_draw_white_bar.move:
+
+ mov dl, HEX (03)
+ call _move_cursor
+
+ xor ch, ch
+ mov cl, cs:[_video_cols]
+
+ inc cx
+ sub cx, 6
+
+_draw_white_bar.draw:
+
+ mov ax, HEX (0920)
+ mov bx, HEX (0070)
+ int HEX (10)
+
+_draw_white_bar.done:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _hide_cursor
+;******************************************************************************
+_hide_cursor:
+
+ push ax
+ push cx
+
+ mov ax, HEX (0103)
+ mov ch, 32
+ int HEX (10)
+
+ pop cx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _show_cursor
+;******************************************************************************
+_show_cursor:
+
+ push ax
+ push cx
+
+ mov ax, HEX (0103)
+ mov cx, HEX (0607)
+ int HEX (10)
+
+ pop cx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _draw_list
+;******************************************************************************
+_draw_list:
+
+ push bp
+ mov bp, sp
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ mov dx, HEX (0204)
+ call _move_cursor
+
+ mov cx, word ptr [bp + 6]
+ mov si, word ptr [bp + 4]
+
+ mov di, word ptr [bp + 8]
+ dec di
+
+_draw_list.skip_loop:
+
+ and cx, cx
+ jz _draw_list.skip_loop_finished
+
+_draw_list.more_lodsb:
+
+ lodsb
+
+ cmp al, ','
+ jne _draw_list.more_lodsb
+
+ dec cx
+ jmp _draw_list.skip_loop
+
+_draw_list.skip_loop_finished:
+
+ xor bx, bx
+
+_draw_list.more:
+
+ lodsb
+
+ and al, al
+ jz _draw_list.done
+
+ cmp al, ','
+ je _draw_list.newline
+
+ call _writechr
+ jmp _draw_list.more
+
+_draw_list.newline:
+
+ mov dl, HEX (04)
+
+ inc dh
+ call _move_cursor
+
+ inc bx
+
+ cmp bx, di
+ jl _draw_list.more
+
+_draw_list.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ call _move_cursor
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _draw_menu
+;******************************************************************************
+_draw_menu:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 12
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ xor cx, cx
+ mov si, ax
+
+ mov word ptr [bp - 6], ax
+
+ xor ah, ah
+ mov al, cs:[_video_rows]
+
+ shr ax
+ mov word ptr [bp - 12], ax
+
+ xor ax, ax
+ mov word ptr [bp - 8], ax
+
+ call _hide_cursor
+
+_draw_menu.count_loop:
+
+ lodsb
+
+ and al, al
+ jz _draw_menu.done_count
+
+ cmp al, ','
+ jne _draw_menu.count_loop
+
+ inc cx
+ jmp _draw_menu.count_loop
+
+_draw_menu.done_count:
+
+ inc cx
+
+ mov word ptr [bp - 4], cx
+ mov word ptr [bp - 2], 0
+
+ xor ax, ax
+ mov word ptr [bp - 10], 0
+
+ mov dx, HEX (0204)
+ call _move_cursor
+
+ push ax
+ push bx
+ push cx
+
+ mov ax, cs:[_menu_default]
+
+ mov cx, word ptr [bp - 12]
+ sub cx, 2
+
+ cmp ax, cx
+ ja _draw_menu.calc_skip
+
+ add dh, al
+ jmp _draw_menu.got_default
+
+_draw_menu.calc_skip:
+
+ mov dh, cl
+ add dh, 2
+
+ sub ax, cx
+
+ mov word ptr [bp - 2], ax
+
+_draw_menu.got_default:
+
+ pop cx
+ pop bx
+ pop ax
+
+_draw_menu.more_select:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ax, word ptr [bp - 12]
+ mov dh, al
+
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ mov cx, HEX (0200)
+ mov dl, HEX (50)
+ int HEX (10)
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ call _draw_white_bar
+
+ push word ptr [bp - 12]
+ push word ptr [bp - 2]
+ push word ptr [bp - 6]
+
+ call _draw_list
+ add sp, 6
+
+_draw_menu.check:
+
+ cmp word ptr [bp - 8], 0
+ jne _draw_menu.get_key
+
+_draw_menu.timeout:
+
+ push bx
+ push cx
+ push dx
+
+ mov cx, word ptr [bp - 4]
+
+ mov bx, word ptr [bp - 12]
+ dec bx
+
+ cmp cx, bx
+ jb _draw_menu.adjust
+
+ mov cx, bx
+
+_draw_menu.adjust:
+
+ inc cx
+
+ mov dh, HEX (02)
+ add dh, cl
+
+ xor dl, dl
+ call _move_cursor
+
+ mov ax, dx
+ call _run_menu_timeout
+
+ pop dx
+ pop cx
+ pop bx
+ jnc _draw_menu.option_selected
+
+ mov word ptr [bp - 8], 1
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov dx, ax
+ call _move_cursor
+
+ mov ax, HEX (0920)
+ mov bx, HEX (0007)
+ mov cx, HEX (0050)
+ int HEX (10)
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ call _move_cursor
+
+_draw_menu.get_key:
+
+ xor ah, ah
+ int HEX (16)
+
+ cmp ah, HEX (48)
+ je _draw_menu.go_up
+
+ cmp ah, HEX (50)
+ je _draw_menu.go_down
+
+ cmp al, HEX (0D)
+ je _draw_menu.option_selected
+
+ jmp _draw_menu.get_key
+
+_draw_menu.go_up:
+
+ cmp dh, HEX (02)
+ jle _draw_menu.hit_top
+
+ call _draw_black_bar
+
+ mov dl, HEX (04)
+ call _move_cursor
+
+ dec dh
+ jmp _draw_menu.more_select
+
+_draw_menu.go_down:
+
+ mov ax, word ptr [bp - 12]
+
+ cmp dh, al
+ je _draw_menu.hit_bottom
+
+ xor ch, ch
+ mov cl, dh
+
+ sub cl, HEX (02)
+ inc cl
+ add cx, word ptr [bp - 2]
+
+ mov ax, word ptr [bp - 4]
+
+ cmp cx, ax
+ je _draw_menu.get_key
+
+ call _draw_black_bar
+
+ mov dl, HEX (04)
+ call _move_cursor
+
+ inc dh
+ jmp _draw_menu.more_select
+
+_draw_menu.hit_top:
+
+ mov cx, word ptr [bp - 2]
+
+ and cx, cx
+ jz _draw_menu.get_key
+
+ dec word ptr [bp - 2]
+ jmp _draw_menu.more_select
+
+_draw_menu.hit_bottom:
+
+ xor ch, ch
+ mov cl, dh
+
+ sub cl, HEX (02)
+ inc cl
+ add cx, word ptr [bp - 2]
+
+ mov ax, word ptr [bp - 4]
+
+ cmp cx, ax
+ je _draw_menu.get_key
+
+ inc word ptr [bp - 2]
+ jmp _draw_menu.more_select
+
+_draw_menu.option_selected:
+
+ sub dh, HEX (02)
+
+ xor ah, ah
+ mov al, dh
+
+ inc ax
+ add ax, word ptr [bp - 2]
+
+_draw_menu.done:
+
+ call _show_cursor
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 12
+ clc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _run_menu
+;******************************************************************************
+global _run_menu
+_run_menu:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 8
+
+ push bx
+ push cx
+ push es
+ push ds
+ push di
+
+ mov cx, cs:[_menu_timeout]
+
+ and cx, cx
+ jnz _run_menu.init
+
+ mov ax, cs:[_menu_default]
+ inc ax
+
+ jmp _run_menu.done
+
+_run_menu.init:
+
+ mov ax, cs:[_menu_default]
+ mov word ptr [bp - 6], ax
+
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 2], 0
+
+_run_menu.clear:
+
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ xor cx, cx
+ mov dh, cs:[_video_rows]
+ mov dl, cs:[_video_cols]
+ int HEX (10)
+
+_run_menu.reset:
+
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+_run_menu.display_title:
+
+ mov ax, HEX (0920)
+ mov bx, HEX (0070)
+
+ xor ch, ch
+
+ mov cl, cs:[_video_cols]
+ inc cl
+
+ int HEX (10)
+
+ mov ah, HEX (03)
+ xor bh, bh
+ int HEX (10)
+
+ mov ax, offset _menu_header
+ push ax
+
+ call _strlen
+ add sp, 2
+
+ push dx
+ xor dx, dx
+
+ mov cx, 2
+ div cx
+
+ mov bx, ax
+
+ xor ah, ah
+ mov al, cs:[_video_cols]
+
+ add ax, cx
+ xor dx, dx
+
+ mov cx, 2
+ div cx
+
+ pop dx
+
+ sub al, bl
+ add dl, al
+
+ mov ah, HEX (02)
+ xor bh, bh
+ int HEX (10)
+
+ mov bx, offset _menu_header
+ call _writestr
+
+ xor dl, dl
+
+ mov ah, HEX (02)
+ xor bh, bh
+ int HEX (10)
+
+_run_menu.init2:
+
+ mov bx, offset _menu_entries
+
+ mov ax, [bx + 0]
+ mov cx, [bx + 4]
+
+ mov es, ax
+ xor bx, bx
+
+_run_menu.convert:
+
+ mov ax, es:[bx]
+ push ax
+
+ call _convert_entry
+ add sp, 2
+
+ add word ptr [bp - 4], 1
+ add bx, 2
+
+ loop _run_menu.convert
+
+ mov ax, cs:[_menu_entry_list]
+ mov ds, ax
+
+ xor ax, ax
+ call _draw_menu
+
+_run_menu.done:
+
+ push ax
+
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ xor cx, cx
+ mov dh, cs:[_video_rows]
+ mov dl, cs:[_video_cols]
+ int HEX (10)
+
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+ pop ax
+
+ mov bx, cs:[_menu_entries]
+ mov es, bx
+ xor bx, bx
+
+ xor dx, dx
+ dec ax
+
+ mov cx, 2
+ mul cx
+
+ add bx, ax
+ mov ax, es:[bx]
+
+ pop di
+ pop ds
+ pop es
+ pop cx
+ pop bx
+
+ add sp, 8
+ clc
+
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_menu_entry_list: dw HEX (0000)
+_list_idx: dw HEX (0000)
+
+_menu_header: db "Freeldr Boot Manager", HEX (00)
+
+_menu_footer1: db " Automatically booting in ", HEX (00)
+_menu_footer2: db " seconds...", HEX (00)
+_menu_footer3: db " second...", HEX (00)
+
+global _menu_default
+_menu_default: dw HEX (0000)
+
+global _menu_timeout
+_menu_timeout: dw HEX (0000)
+
+global _menu_entries
+_menu_entries: db HEX (0006) dup (0)
--- /dev/null
+;******************************************************************************
+; @file screen.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _adjust_screen
+;******************************************************************************
+global _adjust_screen
+_adjust_screen:
+
+ push ax
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment wit zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try to get the amount of rows from the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [HEX (0484)]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Did the BIOS contain the rows?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Yep, so we're good.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _adjust_screen.vidrows_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so we'll assume 25.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, HEX (18)
+
+_adjust_screen.vidrows_ok:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the amount of rows the console has.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cs:[_video_rows], al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the video state.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0F)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ah register contains the amount of columns the console has. We
+ ;; need to subtract by one as indexing starts at zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec ah
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the amount of columns the console has.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cs:[_video_cols], ah
+
+_adjust_screen.done:
+
+ pop ds
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _video_rows
+_video_rows: db HEX (00)
+
+global _video_cols
+_video_cols: db HEX (00)
--- /dev/null
+;******************************************************************************
+; @file search.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _search_dos_dir
+;******************************************************************************
+global _search_dos_dir
+_search_dos_dir:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 34
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ 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 _search_dos_dir.not_root
+
+ mov ax, cs:[_root_start]
+ mov dx, cs:[_root_start + 2]
+
+_search_dos_dir.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 _search_dos_dir.read
+
+_search_dos_dir.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 _search_dos_dir.not_found
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ mov word ptr [bp - 34], bx
+
+_search_dos_dir.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
+
+_search_dos_dir.search:
+
+ push cx
+ mov cx, 11
+
+ cmp byte ptr es:[di], 0
+ je _search_dos_dir.advance
+
+ cmp byte ptr es:[di], HEX (E5)
+ je _search_dos_dir.advance
+
+ push si
+ push di
+ push ds
+
+ mov si, cs
+ mov ds, si
+
+ mov si, word ptr [bp - 32]
+ repe cmpsb
+
+ pop ds
+ pop di
+ pop si
+ je _search_dos_dir.found
+
+_search_dos_dir.advance:
+
+ pop cx
+
+ add di, 32
+ loop _search_dos_dir.search
+
+ cmp word ptr [bp - 30], 1
+ jne _search_dos_dir.check
+
+ mov ax, word ptr [bp - 22]
+
+ and ax, ax
+ jz _search_dos_dir.not_found
+
+ 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 _search_dos_dir.read
+
+_search_dos_dir.check:
+
+ mov ax, word ptr [bp - 34]
+
+ and ax, ax
+ jz _search_dos_dir.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 _search_dos_dir.read
+
+_search_dos_dir.next_clust:
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jmp _search_dos_dir.not_root
+
+_search_dos_dir.not_found:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 34
+ pop bp
+
+ mov ax, 3
+ stc
+
+ ret
+
+_search_dos_dir.found:
+
+ pop cx
+ mov si, di
+
+ mov ax, cs
+ mov ds, ax
+ mov bx, offset _file_info
+
+ mov ax, es:[di + 26]
+ mov [bx + 0], ax
+
+ mov ax, es:[di + 20]
+ mov [bx + 2], ax
+
+ mov ax, es:[di + 28]
+ mov [bx + 4], ax
+
+ mov ax, es:[di + 30]
+ mov [bx + 6], ax
+
+ mov al, es:[di + 11]
+ mov [bx + 8], al
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 34
+ pop bp
+
+ mov ax, offset _file_info
+ clc
+
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_file_info: db 9 dup (0)
--- /dev/null
+;******************************************************************************
+; @file vector.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _vec_adjust
+;******************************************************************************
+_vec_adjust:
+
+ push bp
+ mov bp, sp
+
+ push bx
+ push cx
+ push dx
+
+ mov bx, word ptr [bp + 4]
+
+_vec_adjust.check:
+
+ mov cx, [bx + 2]
+
+ cmp cx, word ptr [bp + 6]
+ ja _vec_adjust.done
+
+_vec_adjust.check2:
+
+ and cx, cx
+ jnz _vec_adjust.shift
+
+ mov cx, 16
+ jmp short _vec_adjust.set
+
+_vec_adjust.shift:
+
+ shl cx
+
+_vec_adjust.set:
+
+ mov [bx + 2], cx
+
+_vec_adjust.alloc:
+
+ mov ax, 2
+ xor dx, dx
+
+ mul cx
+
+ push ax
+ push dx
+
+ mov ax, [bx + 0]
+ push ax
+
+ call _xrealloc
+ add sp, 6
+
+ mov [bx + 0], ax
+
+_vec_adjust.done:
+
+ xor ax, ax
+
+ pop dx
+ pop cx
+ pop bx
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _vec_push
+;******************************************************************************
+global _vec_push
+_vec_push:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ mov bx, word ptr [bp + 4]
+
+_vec_push.alt:
+
+ mov ax, [bx + 4]
+ push ax
+
+ push word ptr [bp + 4]
+
+ call _vec_adjust
+ add sp, 4
+
+ mov word ptr [bp - 2], ax
+
+ and ax, ax
+ jnz _vec_push.done
+
+_vec_push.set:
+
+ mov ax, [bx + 0]
+ mov es, ax
+
+ mov ax, [bx + 4]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov di, ax
+
+ mov ax, [bp + 6]
+ mov es:[di], ax
+
+ mov cx, [bx + 4]
+ add cx, 1
+
+ mov [bx + 4], cx
+
+_vec_push.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file walk.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _walk_path
+;******************************************************************************
+global _walk_path
+_walk_path:
+
+ push bx
+
+ mov ax, cs:[_root_cluster]
+ mov dx, cs:[_root_cluster + 2]
+
+ xor cx, cx
+
+ cmp byte ptr [di], '/'
+ jne _walk_path.not_root
+
+ inc di
+
+_walk_path.not_root:
+
+ push ax
+ push dx
+
+ mov si, di
+
+_walk_path.find_end:
+
+ lodsb
+
+ cmp al, ' '
+ jbe _walk_path.end_path
+
+ cmp al, '/'
+ jne _walk_path.find_end
+
+_walk_path.end_path:
+
+ xchg si, di
+ pop dx
+ pop ax
+
+ mov bx, di
+ dec bx
+
+ cmp bx, si
+ je _walk_path.done
+
+ cmp byte ptr [di - 1], 0
+ je _walk_path.done
+
+ call _mangle_dos_name
+ jc _walk_path.not_found
+
+ call _search_dos_dir
+ jc _walk_path.not_found
+
+ push bx
+ push es
+
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ mov ax, es:[bx + 0]
+ mov dx, es:[bx + 2]
+
+ mov cl, es:[bx + 8]
+ pop es
+ pop bx
+
+ test cl, HEX (10)
+ jz _walk_path.not_found
+
+ cmp byte ptr [di - 1], '/'
+ jne _walk_path.done
+
+ jmp _walk_path.not_root
+
+_walk_path.not_found:
+
+ pop bx
+ stc
+
+ ret
+
+_walk_path.done:
+
+ pop bx
+ clc
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file writechr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function writechr
+;******************************************************************************
+global _writechr
+_writechr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push bp ; Some BIOSes destroy BP when the screen scrolls
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file writedec.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writedec
+;******************************************************************************
+global _writedec
+_writedec:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+ push bp
+
+ mov bx, 10
+ xor cx, cx
+
+_writedec.cloop:
+
+ div bx
+ inc cx
+
+ push dx
+ xor dx, dx
+
+ and ax, ax
+ jnz _writedec.cloop
+
+_writedec.dloop:
+
+ pop ax
+
+ mov ah, HEX (0E)
+ add al, '0'
+ int HEX (10)
+
+ loop _writedec.dloop
+
+_writedec.done:
+
+ pop bp
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file writehex.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+global _writehex
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, cs:[_writehex_num_digits]
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (0E)
+
+ push bp
+ push bx
+
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop bp
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _writehex_num_digits
+_writehex_num_digits: dw HEX (0004)
--- /dev/null
+;******************************************************************************
+; @file writestr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writestr
+;******************************************************************************
+global _writestr
+_writestr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push si
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize si with bx
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump over our printing code to get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _writestr.next
+
+_writestr.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_writestr.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _writestr.print
+
+_writestr.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop si
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file xmalloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _xmalloc
+;******************************************************************************
+global _xmalloc
+_xmalloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [bp + 6]
+ mov dx, [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call malloc.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push dx
+
+ call _malloc
+ add sp, 4
+
+ jc _xmalloc.error
+
+ push ax
+ push bx
+
+ dec ax
+ mov es, ax
+
+ xor bx, bx
+ mov cx, es:[bx + 3]
+
+ pop bx
+ pop ax
+
+ push ax
+ mov es, ax
+
+_xmalloc.loop:
+
+ xor di, di
+
+ push ax
+ push cx
+
+ xor al, al
+ mov cx, 16
+ rep stosb
+
+ pop cx
+ pop ax
+
+ inc ax
+ mov es, ax
+
+ loop _xmalloc.loop
+
+_xmalloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_xmalloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we fail to get memory in here then there's something wrong
+ ;; so just error out.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "Memory full (malloc)", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;******************************************************************************
+; @file xrealloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _xrealloc
+;******************************************************************************
+global _xrealloc
+_xrealloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [bp + 8]
+ mov dx, [bp + 6]
+ mov si, [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call realloc.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push dx
+ push si
+
+ call _realloc
+ add sp, 6
+
+ and ax, ax
+ jz _xrealloc.error
+
+_xrealloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_xrealloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we fail to get memory in here then there's something wrong
+ ;; so just error out.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "Memory full (realloc)", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+default chimaera
+#timeout 10
+timeout 0
+
+label chimaera
+ title Chimaera OS
+ kernel /kernel.sys
--- /dev/null
+/******************************************************************************
+ * @file genhash.c
+ *****************************************************************************/
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct hash {
+
+ char *keywd;
+ unsigned value;
+
+ struct hash *next;
+ struct hash **prev;
+
+};
+
+static char *trim_whitespace (char *str) {
+
+ char *end;
+
+ while (isspace ((int) *str)) {
+ str++;
+ }
+
+ if (*str == '\0') {
+ return str;
+ }
+
+ end = str + strlen (str) - 1;
+
+ while (end > str && isspace ((int) *end)) {
+ end--;
+ }
+
+ end[1] = '\0';
+ return str;
+
+}
+
+static void hash_push (struct hash **head, struct hash *item) {
+
+ item->prev = head;
+
+ if (*head) {
+ (*head)->prev = &item->next;
+ }
+
+ item->next = *head;
+ *head = item;
+
+}
+
+int main (int argc, char **argv) {
+
+ struct hash *curr_hash, *seen_hashes = 0;
+
+ char ch, keywd[256], *p;
+ unsigned hash;
+
+ while ((fgets (keywd, sizeof (keywd), stdin))) {
+
+ p = trim_whitespace (keywd);
+ hash = 0;
+
+ while ((ch = *p++)) {
+ hash = (((hash << 5) | (hash >> 11)) ^ (ch | 0x20)) & 0xffff;
+ }
+
+ for (curr_hash = seen_hashes; curr_hash; curr_hash = curr_hash->next) {
+
+ if (curr_hash->value == hash) {
+
+ fprintf (stderr, "hash collision (0x%04x) %s %s\n", hash, keywd, curr_hash->keywd);
+ return 1;
+
+ }
+
+ }
+
+ if (!(curr_hash = (struct hash *) malloc (sizeof (*curr_hash)))) {
+
+ fprintf (stderr, "Out of memory");
+ return 1;
+
+ }
+
+ curr_hash->keywd = keywd;
+ curr_hash->value = hash;
+
+ curr_hash->next = 0;
+ hash_push (&seen_hashes, curr_hash);
+
+ printf ("hash_%s: equ 0x%04x\n", keywd, hash);
+
+ }
+
+ return 0;
+
+}
--- /dev/null
+default
+kernel
+label
+root
+timeout
+title
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := stdio stdlib string
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: libc.a
+
+clean:
+ for f in `find . -name '*.o'`; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ for f in `find . -name '*.lst'`; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ if [ -f libc.a ]; then rm -rf libc.a; fi
+
+libc.a: stdio/fclose.o stdio/feof.o stdio/fopen.o stdio/fread.o stdlib/free.o stdlib/malloc.o stdlib/realloc.o string/memmove.o string/strlen.o
+ ../../../utils/binutils/sar r libc.a $^
+ ../../../utils/binutils/sar s libc.a
+
+stdio/%.o: stdio/%.asm
+ if [ ! -d "stdio" ]; then mkdir -p "stdio"; fi
+ ../../../utils/binutils/sasm -I$(SRCDIR)/include -l stdio/$*.lst -o $@ $<
+
+stdlib/%.o: stdlib/%.asm
+ if [ ! -d "stdlib" ]; then mkdir -p "stdlib"; fi
+ ../../../utils/binutils/sasm -l stdlib/$*.lst -o $@ $<
+
+string/%.o: string/%.asm
+ if [ ! -d "string" ]; then mkdir -p "string"; fi
+ ../../../utils/binutils/sasm -l string/$*.lst -o $@ $<
+
+%.o: %.asm
+ ../../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := stdio stdlib string
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: libc.a
+
+clean:
+ for /r %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ for /r %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
+ if exist libc.a ( del /q libc.a )
+
+libc.a: stdio/fclose.o stdio/feof.o stdio/fopen.o stdio/fread.o stdlib/free.o stdlib/malloc.o stdlib/realloc.o string/memmove.o string/strlen.o
+ ../../../utils/binutils/sar r libc.a $^
+ ../../../utils/binutils/sar s libc.a
+
+stdio/%.o: stdio/%.asm
+ if not exist "stdio" ( mkdir "stdio" )
+ ../../../utils/binutils/sasm -I$(SRCDIR)/include -l stdio/$*.lst -o $@ $<
+
+stdlib/%.o: stdlib/%.asm
+ if not exist "stdlib" ( mkdir "stdlib" )
+ ../../../utils/binutils/sasm -l stdlib/$*.lst -o $@ $<
+
+string/%.o: string/%.asm
+ if not exist "string" ( mkdir "string" )
+ ../../../utils/binutils/sasm -l string/$*.lst -o $@ $<
+
+%.o: %.asm
+ ../../../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file fclose.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fclose
+;******************************************************************************
+global _fclose
+_fclose:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actaully have some value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _fclose.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ xor si, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es:[si]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=3E to close the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (3E)
+ int HEX (21)
+ jc _fclose.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free our pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push word ptr [bp + 4]
+
+ call _free
+ add sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
+
+_fclose.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file feof.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _feof
+;******************************************************************************
+global _feof
+_feof:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actaully have some value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _feof.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ xor si, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the flags from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es:[si + 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached EOF?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, HEX (0100)
+ jz _feof.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return 1 to indicate that we reached EOF.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1
+
+_feof.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
+
+_feof.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file fopen.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fopen
+;******************************************************************************
+global _fopen
+_fopen:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=3D to open the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ax, HEX (3D00)
+ int HEX (21)
+ jc _fopen.error
+
+_fopen.success:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the file handle in ax.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate some memory for a pointer (i.e. FILE *).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 16
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _xmalloc
+ add sp, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the malloc didn't fail.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, ax
+ jz _fopen.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll use es:di to store the values.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We're not handling files (at least so far) so just push a null word.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We're not EOF yet.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in the extra segment into ax.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fopen.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file fread.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fread
+;******************************************************************************
+global _fread
+_fread:
+
+ 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 buffer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have actually buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;and si, si
+ ;jz _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 10]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ mov bx, es:[di + 0]
+ mov dx, es:[di + 2]
+
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the end of the file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test dx, HEX (0100)
+ jnz _fread.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]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read # no of bytes into the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (3F)
+ int HEX (21)
+ jc _fread.error
+
+ and ax, ax
+ jnz _fread.read_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add an EOF marker to the flags,
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ or word ptr es:[di + 2], HEX (0100)
+ pop di
+ pop es
+
+ jmp short _fread.zero
+
+_fread.read_ok:
+
+ cmp cx, ax
+ je _fread.size_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add an EOF marker to the flags,
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ or word ptr es:[di + 2], HEX (0100)
+ pop di
+ pop es
+
+_fread.size_ok:
+
+ cmp word ptr [bp + 6], 0
+ je _fread.zero
+
+ xor dx, dx
+
+ mov cx, word ptr [bp + 6]
+ div cx
+
+ mov word ptr [bp - 2], ax
+ jmp _fread.done
+
+_fread.zero:
+
+ mov word ptr [bp - 2], 0
+
+_fread.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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
+
+_fread.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
--- /dev/null
+;******************************************************************************
+; @file free.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _free
+;******************************************************************************
+global _free
+_free:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=49 to free the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, word ptr [bp + 4]
+
+ mov ah, HEX (49)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop ax
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file malloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _malloc
+;******************************************************************************
+global _malloc
+_malloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 6]
+ mov dx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the size to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _malloc.ok
+
+_malloc.inc:
+
+ inc ax
+ jz _malloc.error
+
+_malloc.ok:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=48 to allocate the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+
+ mov ah, HEX (48)
+ int HEX (21)
+ jc _malloc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_malloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file realloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _realloc
+;******************************************************************************
+global _realloc
+_realloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+ push di
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack as well as the pointer to
+ ;; re-allocate.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 8]
+ mov dx, word ptr [bp + 6]
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have valid memory as a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _realloc.calc
+
+ mov di, bx
+ dec di
+ mov es, di
+
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _realloc.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _realloc.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _realloc.error
+
+_realloc.calc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the size to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _realloc.ok
+
+_realloc.inc:
+
+ inc ax
+ jz _realloc.error
+
+_realloc.ok:
+
+ mov si, ax
+
+ and bx, bx
+ jz _realloc.alloc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First. lets try and resize the memory block.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ mov es, bx
+ mov bx, si
+
+ mov ah, HEX (4A)
+ int HEX (21)
+ pop es
+ pop bx
+ jnc _realloc.done
+
+_realloc.alloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=48 to allocate the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ mov bx, si
+
+ mov ah, HEX (48)
+ int HEX (21)
+ pop bx
+ jc _realloc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Only copy existing data if there was an original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, bx
+
+ and di, di
+ jz _realloc.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers that copy will clobber.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ds
+
+ mov di, bx
+ mov ds, di
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ mov cx, word ptr es:[di + 3]
+ mov es, ax
+
+ cmp cx, bx
+ jb _realloc.copy
+
+ mov cx, bx
+
+_realloc.copy:
+
+ xor si, si
+ xor di, di
+
+ push cx
+
+ mov cx, 16
+ rep movsb
+
+ pop cx
+
+ mov si, es
+ inc si
+ mov es, si
+
+ mov di, ds
+ inc di
+ mov ds, di
+
+ loop _realloc.copy
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers that copy clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop si
+
+_realloc.free:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we reached this point then free the original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+
+ mov ah, HEX (49)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_realloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop di
+ pop si
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_realloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop di
+ pop si
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file memmove.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _memmove
+;******************************************************************************
+global _memmove
+_memmove:
+
+ push bp
+ mov bp, sp
+
+ push si
+ push di
+ push bx
+ push cx
+
+ mov di, word ptr [bp + 4]
+ mov si, word ptr [bp + 6]
+ mov cx, word ptr [bp + 8]
+
+.L3:
+
+ cmp di, si
+ ja .L2
+
+.L4:
+
+ and cx, cx
+ jz .L1
+
+ movsb
+ dec cx
+
+ jmp .L4
+
+ jmp .L1
+
+.L2:
+
+ and cx, cx
+ jz .L1
+
+ dec cx
+
+.L6:
+
+ and cx, cx
+ jz .L5
+
+ mov bx, si
+ add bx, cx
+
+ mov al, [si]
+
+ mov bx, di
+ add bx, cx
+
+ mov es:[di], al
+
+ dec cx
+ jmp .L6
+
+.L5:
+
+ mov bx, si
+ add bx, cx
+
+ mov al, [si]
+
+ mov bx, di
+ add bx, cx
+
+ mov es:[di], al
+
+.L1:
+
+ pop cx
+ pop bx
+ pop di
+ pop si
+
+ mov ax, word ptr [bp + 4]
+ clc
+
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file strlen.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strlen
+;******************************************************************************
+global _strlen
+_strlen:
+
+ push bp
+ mov bp, sp
+
+ push cx
+ push si
+ push di
+
+ mov si, word ptr [bp + 4]
+ xor cx, cx
+
+_strlen.loop:
+
+ lodsb
+
+ or al, al
+ jz _strlen.done
+
+ inc cx
+ jmp short _strlen.loop
+
+_strlen.done:
+
+ mov ax, cx
+
+ pop di
+ pop si
+ pop cx
+ pop bp
+ ret
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: dosmbr.bin
+
+clean:
+ if [ -f dosmbr.bin ]; then rm -rf dosmbr.bin; fi
+ if [ -f dosmbr.lst ]; then rm -rf dosmbr.lst; fi
+
+%.bin: %.asm
+ ../../utils/binutils/sasm -f bin -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: dosmbr.bin
+
+clean:
+ if exist dosmbr.bin ( del /q dosmbr.bin )
+ if exist dosmbr.lst ( del /q dosmbr.lst )
+
+%.bin: %.asm
+ ../../utils/binutils/sasm -f bin -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file dosmbr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy ourselves down to memory address 0000:0600.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (07C0)
+ mov ds, ax
+
+ mov ax, HEX (0060)
+ mov es, ax
+
+ xor si, si
+ xor di, di
+
+ mov cx, 256
+ rep movsw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Now jump to the copy.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp HEX (0060) : _real_start
+
+;******************************************************************************
+; @function _real_start
+;******************************************************************************
+_real_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov ss, ax
+ mov sp, HEX (0600)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with the address of the first
+ ;; partition information.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (01BE)
+
+ .test_for_active:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Is the partition active?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test byte ptr [di], HEX (80)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Yes, so lets try boot from it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz .active_partition_found
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next partition entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, HEX (0010)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the end of the partition table?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp di, HEX (01FE)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so check this partition.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jb .test_for_active
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We haven't found an active partition.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call error
+ db "No active partition found", HEX (0D), HEX (0A), HEX (00)
+
+ .active_partition_found:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load the boot sector from the partition.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call read_boot_sector
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then the read was unsuccessful.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc .trouble_reading_drive
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Is the partition bootable?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[HEX (7DFE)], HEX (AA55)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so we'll just print out an error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jne .invalid_partition_code
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Finally, jump to the boot code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp HEX (0000) : HEX (7C00)
+
+ .trouble_reading_drive:
+
+ call error
+ db "Read error while reading drive", HEX (0D), HEX (0A), HEX (00)
+
+ .invalid_partition_code:
+
+ call error
+ db "Partition signature != 55AA", HEX (0D), HEX (0A), HEX (00)
+
+;******************************************************************************
+; @function error
+;******************************************************************************
+error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the address of the string from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump passed printing so that we get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short error.next
+
+error.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ah register with 'Teletype output'.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the bx register with the 'Page number' and 'Color'.
+ ;;
+ ;; Note: The color isn't used unless where in graphics mode
+ ;; but it may be best practice to set it anyway.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, HEX (0007)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (10)
+
+error.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz error.print
+
+error.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Wait for a keypress then warm reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ int HEX (16)
+ int HEX (19)
+
+;******************************************************************************
+; @function read_boot_sector
+;******************************************************************************
+read_boot_sector:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (41)
+ mov bx, HEX (55AA)
+ stc
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then disk extensions a unavailable.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc read_boot_sector.standard_bios
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Bit 1 in the cx register should be set if disk extensions
+ ;; are present.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ shr cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Test for carry (from shr) too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sbb bx, HEX (AA55) - 1
+ jne read_boot_sector.standard_bios
+
+read_boot_sector.lba_bios:
+
+ mov ax, [di + 8]
+ mov [read_boot_sector.bios_lba_low], ax
+
+ mov ax, [di + 10]
+ mov [read_boot_sector.bios_lba_high], ax
+
+ mov ax, HEX (4200)
+ mov si, offset read_boot_sector.bios_lba_address_packet
+
+ stc
+ int HEX (13)
+ ret
+
+read_boot_sector.standard_bios:
+
+ mov ax, HEX (0204)
+ mov bx, HEX (7C00)
+ mov cx, [di + 2]
+ mov dh, [di + 1]
+
+ stc
+ int HEX (13)
+ ret
+
+read_boot_sector.bios_lba_address_packet:
+
+ db HEX (10)
+ db HEX (00)
+ dw HEX (0004)
+ dw HEX (7C00)
+ dw HEX (0000)
+
+read_boot_sector.bios_lba_low:
+
+ dw HEX (0000)
+
+read_boot_sector.bios_lba_high:
+
+ dw HEX (0000)
+ dw HEX (0000), HEX (0000)
+
+;******************************************************************************
+; @function writehex
+;******************************************************************************
+writehex:
+
+ push ax
+ push bx
+ push cx
+ push di
+
+ mov cl, 4
+ mov di, 4
+
+writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae writehex.high
+
+writehex.low:
+
+ add al, HEX (30)
+ jmp short writehex.ischar
+
+writehex.high:
+
+ add al, HEX (37)
+
+writehex.ischar:
+
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop ax
+
+ dec di
+ jnz writehex.loop
+
+writehex.done:
+
+ pop di
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pad with zeros until 440 bytes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+db HEX (01B8) - (. - _start) dup (0)
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: kernel.sys
+
+clean:
+ for f in *.o; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ 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
+ ../utils/binutils/slink --oformat binary -o $@ $^
+
+%.o: %.asm
+ ../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+all: kernel.sys
+
+clean:
+ for %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ 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
+ ../utils/binutils/slink --oformat binary -o $@ $^
+
+%.o: %.asm
+ ../utils/binutils/sasm -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file bootstrap.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Memory layout.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Mem.Stack.Top: equ HEX (0840)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Define some offsets for the BPB.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _bytes_per_sector (bp - 64)
+%define _sectors_per_cluster (bp - 62)
+%define _reserved_sectors (bp - 61)
+%define _number_of_fats (bp - 59)
+%define _root_entries (bp - 58)
+%define _total_sectors16 (bp - 56)
+%define _media_descriptor (bp - 54)
+%define _sectors_per_fat (bp - 53)
+%define _sectors_per_track (bp - 51)
+%define _heads_per_cylinder (bp - 49)
+%define _hidden_sectors (bp - 47)
+%define _total_sectors32 (bp - 43)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; FAT32 EBPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _sectors_per_fat32 (bp - 39)
+%define _root_cluster (bp - 35)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Other offsets used within this file.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _edd_available (bp - 28)
+%define _drive_no (bp - 26)
+
+%define _fat_start (bp - 24)
+%define _data_start (bp - 20)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; FAT32 offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _fat_secmask (bp - 16)
+%define _fat_secshift (bp - 14)
+%define _fat_sector (bp - 12)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Offsets of FAT12 and FAT16 convert cluster and next cluster functions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _convert_cluster (bp - 8)
+%define _next_cluster (bp - 6)
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and cx register as well as the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push es
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the convertional memory (in KBs) ...
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; ... And convert it into 16-byte paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, 6
+ shl ax, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reserve memory for a stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, (Mem.Stack.Top >> 4)
+ sub ax, cx
+
+ mov di, ax
+
+ popf
+ pop es
+ pop cx
+ pop bx
+ pop ax
+
+ mov ss, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base and stack pointers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, Mem.Stack.Top
+ lea sp, [bp - 64]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no. passed to us.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax, bx, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push dx
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Transfer the drive no. into the dl register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dl, cl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure our edd_avaiable variable is zero by default.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [_edd_available], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Only check if we're booted from a hard disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test dl, HEX (70)
+ jnz _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (41)
+ mov bx, HEX (55AA)
+ stc
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then disk extensions a unavailable.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Bit 1 in the cx register should be set if disk extensions
+ ;; are present.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ shr cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Test for carry (from shr) too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sbb bx, HEX (AA55) - 1
+ jne _no_edd
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indicate that we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [_edd_available], 1
+
+_no_edd:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax, bx, cx and dx registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ popf
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the extra segment and si register as they
+ ;; get clobbered by movsb.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push si
+ pushf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB just above the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, ss
+ mov es, di
+
+ mov si, 11
+ lea di, [bp - 64]
+
+ mov cx, 25
+ rep movsb
+
+ cmp byte ptr [HEX (01)], HEX (58)
+ jne _not_fat32
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we get here then we're dealing with FAT32, so first
+ ;; preserve the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the number of sectors per FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [HEX (24)]
+ stosw
+
+ mov ax, [HEX (26)]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the root cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [HEX (2C)]
+ stosw
+
+ mov ax, [HEX (2E)]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+ push ax
+ push dx
+
+_calc_offsets:
+
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_fat_start], si
+ mov [_fat_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+
+ push ax
+
+ mul word ptr [_sectors_per_fat32 + 2]
+ add di, ax
+
+ pop ax
+ mul word ptr [_sectors_per_fat32]
+
+ add ax, si
+ adc dx, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_data_start], ax
+ mov [_data_start + 2], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+ pop di
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [_bytes_per_sector]
+ shr ax
+ shr ax
+ dec ax
+
+ mov [_fat_secmask], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+ xchg ax, cx
+
+_secshift:
+
+ inc ax
+ shr cx
+
+ cmp cx, 1
+ jne _secshift
+
+ mov [_fat_secshift], ax
+ dec cx
+
+ mov [_fat_sector], cx
+ mov [_fat_sector + 2], cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_after_copy:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ popf
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers (need as _next_cluster pops both).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L6
+
+.L4:
+
+ push dx
+ push ax
+ push bx
+
+ call _convert_cluster32
+ jc .L7
+
+ mov cx, bx
+ pop bx
+
+.L5:
+
+ call _read_sectors
+
+.L6:
+
+ pop ax
+ pop dx
+
+ call _nextcluster_fat32
+ jmp short .L4
+
+.L7:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the value in the bx register to a segment and add
+ ;; it to the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, 4
+ shr bx, cl
+
+ mov cx, es
+ add cx, bx
+ mov es, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Pass the drive no. in dl.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dh, dh
+ mov dl, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor bx, bx
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to the main code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _all_read
+
+;******************************************************************************
+; @function _not_fat32
+;******************************************************************************
+_not_fat32:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push ax
+ push dx
+
+ xor ax, ax
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [_hidden_sectors]
+ mov di, [_hidden_sectors + 2]
+
+ add si, [_reserved_sectors]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset ready for the fathelper at the start of
+ ;; freeldr.sys.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_fat_start], si
+ mov [_fat_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [_number_of_fats]
+ cbw
+ mul word ptr [_sectors_per_fat]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr [_root_entries]
+ div word ptr [_bytes_per_sector]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_data_start], si
+ mov [_data_start + 2], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop ax
+ pop di
+
+ popf
+ pop si
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Previded we've got a clean stack, the carry flag should be set from
+ ;; the boot sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc .L3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the address of the next cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _getfattype
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax and dx registers (need as _next_cluster pops both).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push dx
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the next sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L1
+
+.L2:
+
+ push dx
+ push ax
+ push bx
+
+ call [_convert_cluster]
+ jc .L3
+
+ mov cx, bx
+ pop bx
+
+.L8:
+
+ push bp
+ push ax
+ push bx
+
+ mov ax, HEX (0E2E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop ax
+ pop bp
+ call _read_sectors
+
+.L1:
+
+ pop ax
+ pop dx
+
+ call [_next_cluster]
+ jmp short .L2
+
+.L3:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the screen.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0600)
+ mov bh, HEX (07)
+ xor cx, cx
+ mov dx, HEX (184F)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the cursor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop ax
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the value in the bx register to a segment and add
+ ;; it to the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, 4
+ shr bx, cl
+
+ mov cx, es
+ add cx, bx
+ mov es, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Pass the drive no. in dl.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dh, dh
+ mov dl, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor bx, bx
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to the main code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _all_read
+
+;******************************************************************************
+; @function _convert_cluster12
+;******************************************************************************
+_convert_cluster12:
+
+ cmp ax, HEX (0FF8)
+ jb _convert_cluster12.c3
+
+ stc
+ ret
+
+_convert_cluster12.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [_data_start]
+ add dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster16
+;******************************************************************************
+_convert_cluster16:
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster16.c3
+
+ stc
+ ret
+
+_convert_cluster16.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, [_data_start]
+ add dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster32
+;******************************************************************************
+_convert_cluster32:
+
+ cmp dx, HEX (0FFF)
+ jne _convert_cluster32.c3
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster32.c3
+
+ stc
+ ret
+
+_convert_cluster32.c3:
+
+ mov cx, dx
+
+ sub ax, 2
+ sbb cx, 0
+
+ mov bl, [_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ xchg cx, ax
+ mul bx
+
+ xchg ax, cx
+ mul bx
+
+ add dx, cx
+
+ add ax, [_data_start]
+ add dx, [_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _getfattype
+;******************************************************************************
+_getfattype:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ xor ax, ax
+
+_getfattype.init:
+
+ mov al, [_sectors_per_cluster]
+ cbw
+ mov si, ax
+
+ mov di, [_bytes_per_sector]
+
+ xor dx, dx
+ xor cx, cx
+
+ mov ax, [_total_sectors16]
+ and ax, ax
+ jnz _getfattype.have_secs
+
+ mov ax, [_total_sectors32]
+ mov dx, [_total_sectors32 + 2]
+
+_getfattype.have_secs:
+
+ sub ax, [_reserved_sectors]
+ sbb dx, 0
+
+ mov cl, [_number_of_fats]
+
+_getfattype.sec_fat_loop:
+
+ sub ax, [_sectors_per_fat]
+ sbb dx, 0
+ loop _getfattype.sec_fat_loop
+
+ push ax
+ push dx
+
+ mov ax, [_root_entries]
+ mov bx, 32
+ mul bx
+
+ add ax, di
+ adc dx, 0
+
+ sub ax, 1
+ sbb dx, 0
+
+ div di
+ mov bx, ax
+
+ pop dx
+ pop ax
+
+ sub ax, bx
+ sbb dx, 0
+
+ div si
+
+ cmp ax, 4096
+ ja _getfattype.fat16
+
+_getfattype.fat12:
+
+ mov ax, offset _convert_cluster12
+ mov [_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat12
+ mov [_next_cluster], ax
+
+ jmp short _getfattype.done
+
+_getfattype.fat16:
+
+ mov ax, offset _convert_cluster16
+ mov [_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat16
+ mov [_next_cluster], ax
+
+_getfattype.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat12
+;******************************************************************************
+_nextcluster_fat12:
+
+ push cx
+ push si
+
+ mov si, ax
+
+_nextcluster_fat12.secoff:
+
+ mov ax, 3
+ mul si
+ shr ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat12.read_fat:
+
+ push es
+ push bx
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ mov ax, [_fat_start]
+ mov dx, [_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat12.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat12.cn_exit
+
+_nextcluster_fat12.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat12.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat12.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, ss
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _nextcluster_fat12.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_nextcluster_fat12.even_cluster:
+
+ and ax, HEX (0FFF)
+
+_nextcluster_fat12.compare:
+
+ cmp ax, HEX (0FF8)
+ cmc
+
+_nextcluster_fat12.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat16
+;******************************************************************************
+_nextcluster_fat16:
+
+ push cx
+ push si
+
+_nextcluster_fat16.secoff:
+
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, [_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat16.read_fat:
+
+ push es
+ push bx
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ mov ax, [_fat_start]
+ mov dx, [_fat_start + 2]
+
+ add ax, si
+ adc dx, 0
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat16.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat16.cn_exit
+
+_nextcluster_fat16.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat16.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat16.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, ss
+ jnc _nextcluster_fat16.first64
+
+ add ax, HEX (1000)
+
+_nextcluster_fat16.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+_nextcluster_fat16.compare:
+
+ cmp ax, HEX (FFF8)
+ cmc
+
+_nextcluster_fat16.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat32
+;******************************************************************************
+_nextcluster_fat32:
+
+ push es
+ push bx
+ push cx
+ push di
+
+ mov di, ax
+ and di, [_fat_secmask]
+
+ mov cx, [_fat_secshift]
+
+_nextcluster_fat32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _nextcluster_fat32.cn_loop
+
+ shl di
+ shl di
+
+ add ax, [_fat_start]
+ adc dx, [_fat_start + 2]
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ cmp ax, [_fat_sector]
+ jne _nextcluster_fat32.read
+
+ cmp dx, [_fat_sector + 2]
+ je _nextcluster_fat32.cn_exit
+
+_nextcluster_fat32.read:
+
+ mov [_fat_sector], ax
+ mov [_fat_sector + 2], dx
+
+ mov cx, 1
+ call _read_sectors
+
+_nextcluster_fat32.cn_exit:
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ cmp dx, HEX (0FFF)
+ jne _nextcluster_fat32.no_carry
+
+ cmp ax, HEX (FFF8)
+ jb _nextcluster_fat32.no_carry
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ stc
+ ret
+
+_nextcluster_fat32.no_carry:
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ clc
+ ret
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push di
+
+_read_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_read_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 [_edd_available], 1
+ jb _read_sectors.chs
+
+_read_sectors.lba:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll create the LBA read 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, [_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need to set si to sp as the LBA read 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
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (42)
+ 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 read the sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _read_sectors.success
+
+_read_sectors.chs:
+
+ div word ptr [_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 [_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.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, [_drive_no]
+ stc
+ int HEX (13)
+ jnc _read_sectors.success
+
+_read_sectors.failure:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ah, ah
+ mov dl, [_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 _read_sectors.retry
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ add bx, [_bytes_per_sector]
+ jnc _read_sectors.no_incr
+
+ mov cx, es
+ add ch, HEX (10)
+ mov es, cx
+
+_read_sectors.no_incr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 _read_sectors.next
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, 4
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (0E)
+
+ push bp
+ push bx
+
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop bp
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Make sure we fit inside 2048 bytes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+db HEX (0800) - (. - _start) dup (0)
--- /dev/null
+;******************************************************************************
+; @file crlf.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _crlf
+;******************************************************************************
+global _crlf
+_crlf:
+
+ push ax
+ push bx
+ push dx
+ push bp
+
+ mov ah, HEX (0E)
+ mov al, HEX (0D)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ mov ah, HEX (0E)
+ mov al, HEX (0A)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bp
+ pop dx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file disk.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _read_boot_sector
+;******************************************************************************
+_read_boot_sector:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have disk extensions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (41)
+ mov bx, HEX (55AA)
+ stc
+ int HEX (13)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then disk extensions a unavailable.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _read_boot_sector.standard_bios
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Bit 1 in the cx register should be set if disk extensions
+ ;; are present.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ shr cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Test for carry (from shr) too.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sbb bx, HEX (AA55) - 1
+ jne _read_boot_sector.standard_bios
+
+_read_boot_sector.lba_bios:
+
+ mov cs:[_read_boot_sector.bios_lba_address_packet + 6], es
+
+ mov ax, es:[si + 8]
+ mov cs:[_read_boot_sector.bios_lba_low], ax
+
+ mov ax, es:[si + 10]
+ mov cs:[_read_boot_sector.bios_lba_high], ax
+
+ mov ax, cs
+ mov ds, ax
+
+ mov ax, HEX (4200)
+ mov si, offset _read_boot_sector.bios_lba_address_packet
+
+ stc
+ int HEX (13)
+
+ jmp _read_boot_sector.check
+
+_read_boot_sector.standard_bios:
+
+ mov ax, HEX (0201)
+ xor bx, bx
+
+ mov cx, es:[si + 2]
+ mov dh, es:[si + 1]
+
+ stc
+ int HEX (13)
+
+_read_boot_sector.check:
+
+ cmp byte ptr es:[bx], HEX (EB)
+ je _read_boot_sector.check2
+
+ stc
+ jmp _read_boot_sector.done
+
+_read_boot_sector.check2:
+
+ cmp byte ptr es:[bx + 2], HEX (90)
+ je _read_boot_sector.done
+
+ stc
+
+_read_boot_sector.done:
+
+ pop ds
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+_read_boot_sector.bios_lba_address_packet:
+
+ db HEX (10)
+ db HEX (00)
+ db HEX (01)
+ db HEX (00)
+ dw HEX (0000)
+ dw HEX (0000)
+
+_read_boot_sector.bios_lba_low:
+
+ dw HEX (0000)
+
+_read_boot_sector.bios_lba_high:
+
+ dw HEX (0000)
+ dw HEX (0000), HEX (0000)
+
+;******************************************************************************
+; @function _get_partition_info
+;******************************************************************************
+global _get_partition_info
+_get_partition_info:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the base pointer to the stack pointer and reserve some space.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 24
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push ds
+ push bx
+ push si
+ push di
+ push dx
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the stack space.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 2], 0
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 6], 0
+ mov word ptr [bp - 8], 0
+ mov word ptr [bp - 10], 0
+ mov word ptr [bp - 12], 0
+ mov word ptr [bp - 14], 0
+ mov word ptr [bp - 16], 0
+ mov word ptr [bp - 18], 0
+ mov word ptr [bp - 20], 0
+ mov word ptr [bp - 22], 0
+ mov word ptr [bp - 24], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; MBR partitions start at offset 0x01BE and are 16 bytes in length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 6]
+ xor dx, dx
+
+ mov cx, 16
+ mul cx
+
+ mov si, ax
+ add si, HEX (01BE)
+
+.L8:
+
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (10)
+ stc
+ int HEX (13)
+ jc .L21
+
+.L9:
+
+ push cx
+ push dx
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ mov ax, HEX (0201)
+ mov cx, HEX (0001)
+ xor dh, dh
+ stc
+ int HEX (13)
+
+ pop dx
+ pop cx
+ jc .L21
+
+.L10:
+
+ cmp byte ptr es:[bx + 0], HEX (EB)
+ jne .L11
+
+ cmp byte ptr es:[bx + 2], HEX (90)
+ jne .L11
+
+ jmp .L12
+
+.L11:
+
+ cmp byte ptr es:[si], 128
+ je .L13
+
+ cmp byte ptr es:[si], 0
+ jne .L21
+
+.L13:
+
+ xor ch, ch
+ mov cl, cs:[_drive_no]
+
+ cmp word ptr [bp + 4], cx
+ jne .L23
+
+ cmp byte ptr es:[si], 128
+ jne .L23
+
+ mov word ptr [bp - 2], 1
+
+.L23:
+
+ mov bx, ss
+ mov es, bx
+ xor bx, bx
+
+ call _read_boot_sector
+ jc .L21
+
+.L14:
+
+ cmp byte ptr es:[bx + 0], HEX (EB)
+ jne .L21
+
+ cmp byte ptr es:[bx + 2], HEX (90)
+ jne .L21
+
+ cmp byte ptr es:[bx + 1], HEX (58)
+ jne .L12
+
+ mov ax, es:[bx + 44]
+ mov dx, es:[bx + 46]
+
+ mov word ptr [bp - 4], ax
+ mov word ptr [bp - 6], dx
+
+ xor ax, ax
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, es:[bx + 28]
+ mov di, es:[bx + 30]
+
+ add si, es:[bx + 14]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 22], si
+ mov word ptr [bp - 24], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, es:[bx + 16]
+ cbw
+
+ push ax
+
+ mul word ptr es:[bx + 38]
+ add di, ax
+
+ pop ax
+ mul word ptr es:[bx + 36]
+
+ add ax, si
+ adc dx, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 8], ax
+ mov word ptr [bp - 10], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector mask.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx + 11]
+ shr ax
+ shr ax
+ dec ax
+
+ mov word ptr [bp - 12], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the sector shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+
+ xchg ax, cx
+ inc cx
+
+.L26:
+
+ inc ax
+ shr cx
+
+ cmp cx, 1
+ jne .L26
+
+ mov word ptr [bp - 14], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump passed the oldfat calculations.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp .L25
+
+.L12:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, es:[bx + 28]
+ mov di, es:[bx + 30]
+
+ add si, es:[bx + 14]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 22], si
+ mov word ptr [bp - 24], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, es:[bx + 16]
+ cbw
+ mul word ptr es:[bx + 22]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 16], si
+ mov word ptr [bp - 18], di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr es:[bx + 17]
+ div word ptr es:[bx + 11]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 8], si
+ mov word ptr [bp - 10], di
+
+.L25:
+
+ xor di, di
+
+ mov ax, HEX (80)
+ xor dx, dx
+
+ call _kmalloc
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First, thing we need is a place to store the current directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 65
+ xor dx, dx
+
+ call _kmalloc
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Start in the root of the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp - 4]
+ stosw
+
+ mov ax, word ptr [bp - 6]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need a scratch buffer for the disk so allocate one.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss:[bx + 11]
+ xor dx, dx
+
+ xor ch, ch
+ mov cl, ss:[bx + 13]
+
+ mul cx
+ mov word ptr [bp - 20], ax
+
+.L24:
+
+ call _kmalloc
+ stosw
+
+ mov ax, ss
+ mov ds, ax
+
+ mov si, bx
+ add si, 11
+
+ mov cx, 25
+ rep movsb
+
+ mov ax, word ptr [bp + 4]
+ stosb
+
+ mov ax, word ptr [bp - 4]
+ stosw
+
+ mov ax, word ptr [bp - 6]
+ stosw
+
+ mov ax, word ptr [bp - 22]
+ stosw
+
+ mov ax, word ptr [bp - 24]
+ stosw
+
+ mov ax, word ptr [bp - 16]
+ stosw
+
+ mov ax, word ptr [bp - 18]
+ stosw
+
+ mov ax, word ptr [bp - 8]
+ stosw
+
+ mov ax, word ptr [bp - 10]
+ stosw
+
+ mov ax, word ptr [bp - 12]
+ stosw
+
+ mov ax, word ptr [bp - 14]
+ stosw
+
+ mov ax, word ptr [bp - 20]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get drive parameters.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (08) ; clobbers AX, BL, CX, DX, ES:DI
+ int HEX (13)
+ jc .L7
+
+ and cx, HEX (3F)
+ mov es:[HEX (0015)], cx
+
+ mov cl, dh
+ inc cx
+ mov es:[HEX (0017)], cx
+
+.L7:
+
+ inc byte ptr cs:[_last_drive]
+
+ mov ax, es
+ jmp .L19
+
+.L21:
+
+ xor ax, ax
+
+.L19:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop cx
+ pop dx
+ pop di
+ pop si
+ pop bx
+ pop ds
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if the partiton is active.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr [bp - 2], 1
+ je .L22
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 24
+ clc
+
+ jmp .L20
+
+.L22:
+
+ add sp, 24
+ stc
+
+.L20:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _get_hard_disk_partitions
+;******************************************************************************
+global _get_hard_disk_partitions
+_get_hard_disk_partitions:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer and make some room
+ ;; for variables within this function.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 10
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov ax, ss
+ mov es, ax
+
+ lea di, [bp - 10]
+ xor al, al
+
+ mov cx, 10
+ rep stosb
+
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up our loop variables.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov word ptr [bp - 4], ax
+
+.L3:
+
+ cmp word ptr [bp - 4], 4
+ jae .L2
+
+ mov dx, word ptr [bp - 4]
+ add dx, HEX (80)
+
+ xor ax, ax
+ mov word ptr [bp - 2], ax
+
+.L5:
+
+ cmp word ptr [bp - 2], 4
+ jae .L6
+
+ mov ax, word ptr [bp - 2]
+ push ax
+
+ mov ax, dx
+ push ax
+
+ call _get_partition_info
+ add sp, 4
+
+ and ax, ax
+ jz .L15
+
+ jnc .L16
+
+ mov es, ax
+ xor bx, bx
+
+ cmp es:[bx + 29], dl
+ jne .L16
+
+.L17:
+
+ push ax
+
+ mov ax, offset _vec_parts
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+ jmp .L15
+
+.L16:
+
+ push ds
+
+ mov cx, ss
+ mov ds, cx
+
+ push ax
+
+ lea ax, word ptr [bp - 10]
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+ pop ds
+
+.L15:
+
+ add word ptr [bp - 2], 1
+ jmp .L5
+
+.L6:
+
+ add word ptr [bp - 4], 1
+ jmp .L3
+
+.L2:
+
+ mov cx, word ptr [bp - 6]
+ xor bx, bx
+
+.L4:
+
+ and cx, cx
+ jz .L18
+
+ mov ax, word ptr [bp - 10]
+ mov es, ax
+
+ mov ax, es:[bx]
+ push ax
+
+ mov ax, offset _vec_parts
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+ add bx, 2
+ dec cx
+
+ jmp short .L4
+
+.L18:
+
+ mov ax, word ptr [bp - 10]
+
+ mov es, ax
+ call _free_mem
+
+.L1:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 10
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Pop the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _read_sectors
+;******************************************************************************
+global _read_sectors
+_read_sectors:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+ push di
+ push es
+
+_read_sectors.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The di regsiter will be our retry counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, HEX (0005)
+
+_read_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 _read_sectors.chs
+
+_read_sectors.lba:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll create the LBA read 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 read 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
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (42)
+ 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 read the sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnc _read_sectors.success
+
+_read_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.
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read the sector into es:bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0201)
+ mov dl, cs:[_drive_no]
+ stc
+ int HEX (13)
+ jnc _read_sectors.success
+
+_read_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 _read_sectors.retry
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Invoke the BIOS.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (18)
+
+_read_sectors.success:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the bytes per sector to bx to get the next offset to read 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 _read_sectors.next
+
+_read_sectors.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _drive_no
+_drive_no: db HEX (00)
+
+global _last_drive
+_last_drive: db HEX (00)
+
+global _selected_disk
+_selected_disk: dw HEX (0000)
+
+global _disk_scratch
+_disk_scratch: dw HEX (0000)
+
+global _edd_available
+_edd_available: dw HEX (0000)
+
+global _clustsize
+_clustsize: dw HEX (0000)
+
+global _vec_parts
+_vec_parts: db 6 dup (0)
+
+global _disk_transfer_addr
+_disk_transfer_addr:
+
+ dw HEX (0000)
+ dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file divide.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _divide_handler
+;******************************************************************************
+global _divide_handler
+_divide_handler:
+
+ push sp
+ push bp
+
+ mov bp, sp
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're within the kernel then we'll blue screen.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_curr_psp], 0
+ jne _divide_handler.no_clear
+
+_divide_handler.clear:
+
+ mov ax, HEX (0600)
+ mov bh, HEX (1F)
+ xor cx, cx
+ mov dx, HEX (1850)
+ int HEX (10)
+
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+ jmp _divide_handler.init
+
+_divide_handler.no_clear:
+
+ call _crlf
+
+_divide_handler.init:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the data segment is the dame as the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print our first message.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, offset _divide_handler.msg
+ call _writestr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the segment of the error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print a colon.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ':'
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the offset of the error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 2]
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print a newline.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _crlf
+ call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ds
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the stack segmennt segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the stack and base pointers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 2]
+ add ax, 3 * 2 ; return address, offset, segment.
+ call _writehex
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ mov ax, word ptr [bp]
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print a newline.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the general purpose registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ call _writehex
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ mov ax, di
+ call _writehex
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ pop ax
+ call _writehex
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ pop ax
+ call _writehex
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value of bx off the stack and print it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Indent with 4 spaces.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Finally, get the value of ax off the stack and print it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ call _writehex
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print a newline.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _crlf
+ call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're within the kernel we don't want to try quiting
+ ;; the program.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_curr_psp], 0
+ je _divide_handler.reboot
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Let's try and exit the current process.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (4C7F)
+ int HEX (21)
+
+_divide_handler.reboot:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call error with our ending message.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "Press any key to reboot...", HEX (00)
+
+_divide_handler.msg:
+
+ db "Trap to vector 0: Divide overflow at ", HEX (00)
--- /dev/null
+;******************************************************************************
+; @file _error.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _error
+;******************************************************************************
+global _error
+_error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the address of the string from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump passed printing so that we get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _error.next
+
+_error.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_error.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _error.print
+
+_error.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Wait for a keypress.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ int HEX (16)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Stop floppy motor.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, HEX (03F2)
+ xor al, al
+ out dx, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset console.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0003)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Cold reboot.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov bx, HEX (0472)
+ mov word ptr es:[bx], 0
+
+ jmp HEX (F000) : HEX (FFF0)
--- /dev/null
+;******************************************************************************
+; @file fat.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _convert_cluster12
+;******************************************************************************
+global _convert_cluster12
+_convert_cluster12:
+
+ cmp ax, HEX (0FF8)
+ jb _convert_cluster12.c3
+
+ stc
+ ret
+
+_convert_cluster12.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster16
+;******************************************************************************
+global _convert_cluster16
+_convert_cluster16:
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster16.c3
+
+ stc
+ ret
+
+_convert_cluster16.c3:
+
+ xor dx, dx
+
+ sub ax, 2
+ sbb dx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ mul bx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _convert_cluster32
+;******************************************************************************
+global _convert_cluster32
+_convert_cluster32:
+
+ cmp dx, HEX (0FFF)
+ jne _convert_cluster32.c3
+
+ cmp ax, HEX (FFF8)
+ jb _convert_cluster32.c3
+
+ stc
+ ret
+
+_convert_cluster32.c3:
+
+ mov cx, dx
+
+ sub ax, 2
+ sbb cx, 0
+
+ mov bl, cs:[_sectors_per_cluster]
+ dec bx
+
+ sub bh, bh
+ inc bx
+
+ xchg cx, ax
+ mul bx
+
+ xchg ax, cx
+ mul bx
+
+ add dx, cx
+
+ add ax, cs:[_data_start]
+ adc dx, cs:[_data_start + 2]
+
+ ret
+
+;******************************************************************************
+; @function _getfattype
+;******************************************************************************
+global _getfattype
+_getfattype:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ xor ax, ax
+ xor dx, dx
+
+_getfattype.init:
+
+ mov al, cs:[_sectors_per_cluster]
+ cbw
+ mov si, ax
+
+ mov di, cs:[_bytes_per_sector]
+
+ xor dx, dx
+ xor cx, cx
+
+ mov ax, cs:[_total_sectors16]
+ and ax, ax
+ jnz _getfattype.have_secs
+
+ mov ax, cs:[_total_sectors32]
+ mov dx, cs:[_total_sectors32 + 2]
+
+_getfattype.have_secs:
+
+ sub ax, cs:[_reserved_sectors]
+ sbb dx, 0
+
+ mov cl, cs:[_number_of_fats]
+
+_getfattype.sec_fat_loop:
+
+ sub ax, cs:[_sectors_per_fat]
+ sbb dx, 0
+ loop _getfattype.sec_fat_loop
+
+ push ax
+ push dx
+
+ mov ax, cs:[_root_entries]
+
+ mov bx, 32
+ mul bx
+
+ add ax, di
+ adc dx, 0
+
+ sub ax, 1
+ sbb dx, 0
+
+ div di
+ mov bx, ax
+
+ pop dx
+ pop ax
+
+ sub ax, bx
+ sbb dx, 0
+
+ div si
+
+ cmp ax, 4096
+ ja _getfattype.fat16
+
+_getfattype.fat12:
+
+ mov ax, offset _convert_cluster12
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat12
+ mov cs:[_next_cluster], ax
+
+ jmp short _getfattype.done
+
+_getfattype.fat16:
+
+ mov ax, offset _convert_cluster16
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat16
+ mov cs:[_next_cluster], ax
+
+_getfattype.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat12
+;******************************************************************************
+global _nextcluster_fat12
+_nextcluster_fat12:
+
+ push cx
+ push si
+
+ mov si, ax
+
+_nextcluster_fat12.secoff:
+
+ 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
+
+_nextcluster_fat12.read_fat:
+
+ push es
+ push bx
+
+ 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
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat12.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat12.cn_exit
+
+_nextcluster_fat12.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat12.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat12.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ push ds
+ mov ax, cs:[_fat_seg]
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+ jnc _nextcluster_fat12.even_cluster
+
+ mov cl, 4
+ shr ax, cl
+
+_nextcluster_fat12.even_cluster:
+
+ and ax, HEX (0FFF)
+
+_nextcluster_fat12.compare:
+
+ cmp ax, HEX (0FF8)
+ cmc
+
+_nextcluster_fat12.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat16
+;******************************************************************************
+global _nextcluster_fat16
+_nextcluster_fat16:
+
+ push cx
+ push si
+
+_nextcluster_fat16.secoff:
+
+ shl ax
+
+ push cx
+ pushf
+
+ mov cx, cs:[_bytes_per_sector]
+ shl cx
+
+ xor dx, dx
+ div cx
+
+ push dx
+ xchg si, ax
+
+_nextcluster_fat16.read_fat:
+
+ push es
+ push bx
+
+ 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
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat16.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat16.cn_exit
+
+_nextcluster_fat16.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat16.cn_exit:
+
+ pop bx
+ pop es
+
+_nextcluster_fat16.get_clust:
+
+ pop si
+ popf
+ pop cx
+
+ mov ax, cs:[_fat_seg]
+ jnc _nextcluster_fat16.first64
+
+ add ax, HEX (1000)
+
+_nextcluster_fat16.first64:
+
+ push ds
+ mov ds, ax
+ mov ax, [si]
+ pop ds
+
+_nextcluster_fat16.compare:
+
+ cmp ax, HEX (FFF8)
+ cmc
+
+_nextcluster_fat16.done:
+
+ xor dx, dx
+
+ pop si
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _nextcluster_fat32
+;******************************************************************************
+global _nextcluster_fat32
+_nextcluster_fat32:
+
+ push es
+ push bx
+ push cx
+ push di
+
+ mov di, ax
+ and di, cs:[_fat_secmask]
+
+ mov cx, cs:[_fat_secshift]
+
+_nextcluster_fat32.cn_loop:
+
+ shr dx
+ rcr ax
+ loop _nextcluster_fat32.cn_loop
+
+ shl di
+ shl di
+
+ add ax, cs:[_fat_start]
+ adc dx, cs:[_fat_start + 2]
+
+ mov bx, cs:[_fat_seg]
+ mov es, bx
+ xor bx, bx
+
+ cmp ax, cs:[_fat_sector]
+ jne _nextcluster_fat32.read
+
+ cmp dx, cs:[_fat_sector + 2]
+ je _nextcluster_fat32.cn_exit
+
+_nextcluster_fat32.read:
+
+ mov cs:[_fat_sector], ax
+ mov cs:[_fat_sector + 2], dx
+
+ mov cx, 2
+ call _read_sectors
+
+_nextcluster_fat32.cn_exit:
+
+ mov ax, es:[di]
+ mov dx, es:[di + 2]
+
+ cmp dx, HEX (0FFF)
+ jne _nextcluster_fat32.no_carry
+
+ cmp ax, HEX (FFF8)
+ jb _nextcluster_fat32.no_carry
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ stc
+ ret
+
+_nextcluster_fat32.no_carry:
+
+ pop di
+ pop cx
+ pop bx
+ pop es
+
+ clc
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _fat_bpb
+_fat_bpb: db 25 dup (0)
+
+global _convert_cluster
+_convert_cluster: dw HEX (0000)
+
+global _next_cluster
+_next_cluster: dw HEX (0000)
+
+global _fat_seg
+_fat_seg: dw HEX (0000)
+
+global _fat_secmask
+_fat_secmask: dw HEX (0000)
+
+global _fat_secshift
+_fat_secshift: dw HEX (0000)
+
+global _curr_cluster
+_curr_cluster:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _fat_sector
+_fat_sector:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _root_cluster
+_root_cluster:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _fat_start
+_fat_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _root_start
+_root_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _data_start
+_data_start:
+
+ dw HEX (0000)
+ dw HEX (0000)
--- /dev/null
+%ifndef _FAT_INC
+%define _FAT_INC
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Offsets into the BPB.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define _bytes_per_sector (_fat_bpb + 0)
+%define _sectors_per_cluster (_fat_bpb + 2)
+%define _reserved_sectors (_fat_bpb + 3)
+%define _number_of_fats (_fat_bpb + 5)
+%define _root_entries (_fat_bpb + 6)
+%define _total_sectors16 (_fat_bpb + 8)
+%define _media_descriptor (_fat_bpb + 10)
+%define _sectors_per_fat (_fat_bpb + 11)
+%define _sectors_per_track (_fat_bpb + 13)
+%define _heads_per_cylinder (_fat_bpb + 15)
+%define _hidden_sectors (_fat_bpb + 17)
+%define _total_sectors32 (_fat_bpb + 21)
+
+%endif ; _FAT_INC
--- /dev/null
+;******************************************************************************
+; @file file.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _read_cluster
+;******************************************************************************
+_read_cluster:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer to the stack pointer and reserve
+ ;; some space.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 36
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ push si
+ push di
+
+_read_cluster.walk:
+
+ and ax, ax
+ jz _read_cluster.check
+
+ push ax
+ push dx
+
+ mov ax, bx
+ mov dx, cx
+
+ call cs:[_next_cluster]
+ jnc _read_cluster.found
+
+ pop dx
+ pop ax
+
+ jmp _read_cluster.done
+
+_read_cluster.found:
+
+ mov bx, ax
+ mov cx, dx
+
+ pop dx
+ pop ax
+
+ dec ax
+ jnz _read_cluster.walk
+
+_read_cluster.check:
+
+ mov ax, bx
+ mov dx, cx
+
+ call cs:[_convert_cluster]
+ jnc _read_cluster.read
+
+_read_cluster.read:
+
+ xor ch, ch
+ mov cl, es:[si + 6]
+
+ mov bx, es:[si + 68]
+ mov es, bx
+ xor bx, bx
+
+ call _read_sectors
+
+_read_cluster.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 36
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _getc
+;******************************************************************************
+_getc:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push si
+
+ mov word ptr [bp - 2], 0
+
+_getc.is_eof:
+
+ mov ax, es:[si + 64]
+ mov dx, es:[si + 66]
+
+ mov cx, ax
+
+ or cx, dx
+ jz _getc.done
+
+_getc.check:
+
+ cmp dx, es:[si + 62]
+ ja _getc.check2
+
+ cmp dx, es:[si + 62]
+ jne _getc.done
+
+ cmp ax, es:[si + 60]
+ jbe _getc.done
+
+_getc.check2:
+
+ mov ax, es:[si + 60]
+ mov dx, es:[si + 62]
+
+ mov cx, es:[si + 50]
+ div cx
+
+ cmp word ptr es:[si + 52], 0
+ je _getc.check_offset
+
+ mov word ptr es:[si + 52], 0
+ jmp short _getc.read
+
+_getc.check_offset:
+
+ and dx, dx
+ jnz _getc.loaded
+
+_getc.read:
+
+ mov bx, es:[si + 56]
+ mov cx, es:[si + 58]
+ call _read_cluster
+
+_getc.loaded:
+
+ push es
+
+ mov bx, es:[si + 68]
+ mov es, bx
+ mov bx, dx
+ mov al, es:[bx]
+
+ mov bx, ds
+ mov es, bx
+ stosb
+
+ mov bx, es
+ mov ds, bx
+
+ pop es
+ inc word ptr [bp - 2]
+
+ add word ptr es:[si + 60], 1
+ adc word ptr es:[si + 62], 0
+
+_getc.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ clc
+
+ pop bp
+ ret
+
+_getc.error:
+
+ xor ax, ax
+
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ stc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _get_file_handle
+;******************************************************************************
+_get_file_handle:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push es
+
+ mov word ptr [bp - 2], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Intialize the es register with address of our vector entries
+ ;; and zero out bx for the counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs:[_vec_files + 0]
+ mov es, bx
+ xor bx, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check to see if our vector is empty.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs:[_vec_files + 2]
+
+ and cx, cx
+ jz _get_file_handle.done
+
+_get_file_handle.search:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the vector entry is zero then we have a free entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[bx], 0
+ je _get_file_handle.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance to the next entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add bx, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Increase our counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc word ptr [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ loop _get_file_handle.search
+
+_get_file_handle.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set ax to the index of the file plus 3.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp - 2]
+ add ax, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and clear the carry flag to indicate success.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 2
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and eturn to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+
+;******************************************************************************
+; @function _close_file
+;******************************************************************************
+global _close_file
+_close_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push di
+ push si
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _close_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _close_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the correct file offset by subtracting 3.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub bx, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset into our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 we have a free entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[bx], 0
+ jne _close_file.ok
+
+_close_file.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop si
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 6
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_close_file.ok:
+
+ push es
+
+ mov ax, es:[bx]
+ mov es, ax
+
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Our file handle info contains a pointer to a buffer at offset
+ ;; 52 so we need to free it.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[di + 68]
+ push es
+
+ mov es, ax
+ call _free_mem
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free our entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ call _free_mem
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the entry to zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es:[bx], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract 1 from the length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec word ptr cs:[_vec_files + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop si
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Not sure what ax should be so just clear it for now and clear the
+ ;; carray flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _open_file
+;******************************************************************************
+global _open_file
+_open_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Walk the path until we hit the last '\'.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _walk_path
+ jnc _open_file.found_dir
+
+_open_file.not_found:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 3
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.found_dir:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _open_file.name_error
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then we couldn't find the specified file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _open_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax register should contain information about the file so
+ ;; copy it into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment as the code segment and copy the value
+ ;; in the ax register into the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The info passed back to us from _search_dos_dir should contain the
+ ;; entry type at offset 8 so move that into the cl register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, es:[bx + 8]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Was the entry a file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test cl, HEX (18)
+ jz _open_file.got_file
+
+_open_file.name_error:
+
+ pop bx
+ pop di
+
+_open_file.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 2
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.got_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get an available file info entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _get_file_handle
+ jnc _open_file.got_handle
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag and error number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 4
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_open_file.got_handle:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the ax register
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate memory for the file info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 128
+ xor dx, dx
+ call _kmalloc
+
+ mov es, ax
+ xor di, di
+
+ mov ax, cs:[_curr_cluster]
+ stosw
+
+ mov ax, cs:[_curr_cluster + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value in the code segment into the data segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, cs
+ mov ds, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the si register with the address of our BPB.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _fat_bpb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the BPB to the file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store other disk info.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, cs:[_drive_no]
+ stosb
+
+ mov ax, cs:[_root_cluster]
+ stosw
+
+ mov ax, cs:[_root_cluster + 2]
+ stosw
+
+ mov ax, cs:[_fat_start]
+ stosw
+
+ mov ax, cs:[_fat_start + 2]
+ stosw
+
+ mov ax, cs:[_root_start]
+ stosw
+
+ mov ax, cs:[_root_start + 2]
+ stosw
+
+ mov ax, cs:[_data_start]
+ stosw
+
+ mov ax, cs:[_data_start + 2]
+ stosw
+
+ mov ax, cs:[_fat_secmask]
+ stosw
+
+ mov ax, cs:[_fat_secshift]
+ stosw
+
+ mov ax, cs:[_clustsize]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value 1 as the first word to indicate that we need
+ ;; to be read
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the starting cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 0]
+ stosw
+
+ mov ax, cs:[si + 2]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; File pointer starts at zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the file size.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 4]
+ stosw
+
+ mov ax, cs:[si + 6]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate memory for a buffer that will be used to keep track of
+ ;; the current data read.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+
+ mov ax, es:[si + 50]
+ xor dx, dx
+ call _kmalloc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the current Program Segment Prefix.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_curr_psp]
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore ax and re-push it to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ push ax
+
+_open_file.check:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the capacity of our "vector array"?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp ax, cs:[_vec_files + 2]
+ jb _open_file.no_push
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so add the file info to our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ push es
+
+ mov bx, offset _vec_files
+ push bx
+
+ call _vec_push
+ add sp, 4
+
+ jmp short _open_file.done
+
+_open_file.no_push:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value that in the extra segment into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the address of our vector array.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs:[_vec_files + 0]
+ mov es, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract 3 from ax to get the real index into our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sub ax, 3
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the dx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiply by two to get the offset into the vector array.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the offset into bx and set it to the value that we copied into
+ ;; the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+ mov es:[bx], si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add one to our vector length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc word ptr cs:[_vec_files + 4]
+
+_open_file.done:
+
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+;******************************************************************************
+; @function _read_file
+;******************************************************************************
+global _read_file
+_read_file:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the base pointer to the stack pointer and make some room to store
+ ;; some values within this function.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+ sub sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push es
+ push ds
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure our total bytes read is zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr [bp - 2], 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we're not write-only.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr es:[si + 54], 1
+ je _read_file.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the buffer offset (dx) into the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, dx
+
+_read_file.loop:
+
+ call _getc
+ jc _read_file.error
+
+ and ax, ax
+ jz _read_file.done
+
+ inc word ptr [bp - 2]
+ loop _read_file.loop
+
+_read_file.done:
+
+ mov ax, [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ 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
+
+_read_file.error:
+
+ mov ax, 6
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop ds
+ pop es
+ 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
+
+;******************************************************************************
+; @function _seek_file
+;******************************************************************************
+global _seek_file
+_seek_file:
+
+ push bx
+
+ cmp bx, 3
+ jb _seek_file.error
+
+ sub bx, 3
+ jmp _seek_file.calc
+
+_seek_file.error:
+
+ pop bx
+
+ mov ax, 6
+ stc
+
+ ret
+
+_seek_file.calc:
+
+ push es
+ push si
+ push di
+ push ax
+ push dx
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset into our vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+ pop cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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
+ jne _seek_file.check
+
+ pop dx
+ pop ax
+ pop di
+ pop si
+ pop es
+ pop bx
+
+ mov ax, 6
+ stc
+
+ ret
+
+_seek_file.check:
+
+ mov ax, es:[bx]
+ mov es, ax
+ xor si, si
+
+ pop dx
+ pop ax
+
+ cmp al, 0
+ je _seek_file.beginning
+
+ cmp al, 1
+ je _seek_file.offset
+
+ cmp al, 2
+ je _seek_file.end
+
+ pop di
+ pop si
+ pop es
+ pop bx
+
+ mov ax, 1
+ stc
+
+ ret
+
+_seek_file.beginning:
+
+ xor ax, ax
+
+ mov es:[si + 60], ax
+ mov es:[si + 62], 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
+
+_seek_file.offset:
+
+ mov ax, es:[si + 60]
+ add ax, cx
+
+ mov di, es:[si + 62]
+ adc di, dx
+
+ cmp di, 0
+ jge _seek_file.ptr_ok
+
+ xor ax, ax
+ xor di, di
+
+_seek_file.ptr_ok:
+
+ mov es:[si + 60], ax
+ mov es:[si + 62], di
+
+_seek_file.done:
+
+ mov word ptr es:[si + 52], 1
+
+ mov ax, es:[si + 60]
+ mov dx, es:[si + 62]
+ clc
+
+ pop di
+ pop si
+ pop es
+ pop bx
+
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _vec_files
+_vec_files: db 6 dup (0)
--- /dev/null
+;******************************************************************************
+; @file find.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _compress_filename
+;******************************************************************************
+_compress_filename:
+
+ push si
+ push di
+
+ push si
+ mov cl, 8
+
+_compress_filename.name:
+
+ lodsb
+
+ cmp al, ' '
+ je _compress_filename.check
+
+ stosb
+
+ dec cl
+ jnz _compress_filename.name
+
+_compress_filename.check:
+
+ test bl, HEX (20)
+ jnz _compress_filename.check2
+
+ pop si
+
+ xor al, al
+ stosb
+
+ pop di
+ pop si
+ ret
+
+_compress_filename.check2:
+
+ pop si
+ add si, 8
+
+ cmp byte ptr [si], ' '
+ jne _compress_filename.need_ext
+
+ xor al, al
+ stosb
+
+ pop di
+ pop si
+ ret
+
+_compress_filename.need_ext:
+
+ mov al, '.'
+ stosb
+
+ mov cl, 3
+
+_compress_filename.ext:
+
+ lodsb
+
+ cmp al, ' '
+ je _compress_filename.ext_done
+
+ stosb
+ loop _compress_filename.ext
+
+_compress_filename.ext_done:
+
+ xor al, al
+ stosb
+
+ pop di
+ pop si
+ ret
+
+;******************************************************************************
+; @function _find_next_file
+;******************************************************************************
+_find_next_file:
+
+ push si
+ mov dx, si
+
+_find_next_file.dir_loop:
+
+ push cx
+ push di
+
+ mov al, es:[bx]
+
+ and al, al
+ jz _find_next_file.advance
+
+ cmp al, HEX (E5)
+ je _find_next_file.advance
+
+ mov di, bx
+ mov si, dx
+ mov cx, 11
+
+_find_next_file.compare:
+
+ lodsb
+
+ cmp al, '?'
+ je _find_next_file.wild
+
+ cmp al, es:[di]
+ jne _find_next_file.advance
+
+_find_next_file.wild:
+
+ inc di
+ loop _find_next_file.compare
+
+ jmp short _find_next_file.done
+
+_find_next_file.advance:
+
+ pop di
+ pop cx
+
+ add bx, 32
+ add di, 32
+
+ loop _find_next_file.dir_loop
+
+_find_next_file.not_found:
+
+ mov bx, HEX (FFFF)
+
+ pop si
+ ret
+
+_find_next_file.done:
+
+ pop di
+ pop cx
+
+ pop si
+ ret
+
+;******************************************************************************
+; @function _find_file
+;******************************************************************************
+global _find_file
+_find_file:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 42
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ cmp word ptr es:[bx + 13], HEX (FFFF)
+ je _find_file.error
+
+ mov ax, es:[bx + 13]
+ mov word ptr [bp - 36], ax
+
+ mov word ptr [bp - 42], es
+ mov word ptr [bp - 32], bx
+
+ mov word ptr [bp - 20], 0
+ mov word ptr [bp - 16], 0
+
+ mov ax, es:[bx + 13]
+ xor dx, dx
+
+ mov cx, cs:[_bytes_per_sector]
+ div cx
+
+ mov word ptr [bp - 40], ax
+ mov word ptr [bp - 38], dx
+
+ mov ax, es:[bx + 15]
+ mov dx, es:[bx + 19]
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _find_file.not_root
+
+ mov ax, cs:[_root_start]
+ mov dx, cs:[_root_start + 2]
+
+_find_file.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 _find_file.read
+
+_find_file.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 _find_file.not_found
+
+ 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]
+
+_find_file.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
+
+ mov ax, word ptr [bp - 38]
+ xor dx, dx
+
+ mov bx, 32
+ div bx
+
+ sub cx, ax
+
+_find_file.search:
+
+ mov di, word ptr [bp - 36]
+
+ mov ax, word ptr [bp - 42]
+ mov ds, ax
+
+ mov si, word ptr [bp - 32]
+ inc si
+
+ mov bx, cs:[_disk_scratch]
+ mov es, bx
+
+ mov bx, word ptr [bp - 38]
+ call _find_next_file
+
+ mov si, es
+ mov ds, si
+ mov si, bx
+
+ mov bx, word ptr [bp - 42]
+ mov es, bx
+ mov bx, word ptr [bp - 32]
+
+ mov es:[bx + 13], di
+
+ mov word ptr [bp - 38], si
+ mov word ptr [bp - 36], di
+
+ cmp si, HEX (FFFF)
+ je _find_file.check2
+
+ mov al, [si + 11]
+
+ and al, es:[bx + 12]
+ jz _find_file.found
+
+ add word ptr [bp - 38], 32
+ add word ptr [bp - 36], 32
+
+ loop _find_file.search
+
+_find_file.check2:
+
+ cmp word ptr [bp - 30], 1
+ jne _find_file.check
+
+ mov ax, word ptr [bp - 22]
+
+ and ax, ax
+ jz _find_file.not_found
+
+ 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
+
+ mov cx, word ptr [bp - 24]
+ mov word ptr [bp - 38], 0
+
+ jmp _find_file.read
+
+_find_file.check:
+
+ mov ax, word ptr [bp - 34]
+
+ and ax, ax
+ jz _find_file.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
+
+ mov cx, word ptr [bp - 24]
+ mov word ptr [bp - 38], 0
+
+ jmp _find_file.read
+
+_find_file.next_clust:
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jc _find_file.not_found
+
+ mov bx, word ptr [bp - 36]
+ mov es, bx
+ mov bx, word ptr [bp - 32]
+
+ mov word ptr es:[bx + 13], 0
+ mov es:[bx + 15], ax
+ mov es:[bx + 19], dx
+
+ mov word ptr [bp - 38], 0
+ jmp _find_file.not_root
+
+_find_file.not_found:
+
+ mov word ptr es:[bx + 13], HEX (FFFF)
+
+_find_file.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 42
+ pop bp
+
+ mov ax, 3
+ stc
+
+ ret
+
+_find_file.found:
+
+ cmp word ptr es:[bx + 13], HEX (FFFF)
+ je _find_file.check_end
+
+ add word ptr es:[bx + 13], 32
+
+_find_file.check_end:
+
+ cmp word ptr [bp - 30], 1
+ je _find_file.root_end
+
+ mov ax, cs:[_bytes_per_sector]
+ xor dx, dx
+
+ xor ch, ch
+ mov cl, cs:[_sectors_per_cluster]
+
+ mul cx
+
+ cmp es:[bx + 13], ax
+ jb _find_file.fill
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jc _find_file.end
+
+ mov word ptr es:[bx + 13], 0
+ mov es:[bx + 15], ax
+ mov es:[bx + 19], dx
+
+ jmp _find_file.fill
+
+_find_file.end:
+
+ mov word ptr es:[bx + 13], HEX (FFFF)
+ jmp _find_file.fill
+
+_find_file.root_end:
+
+ cmp word ptr [bp - 22], 0
+ ja _find_file.fill
+
+ mov word ptr es:[bx + 13], HEX (FFFF)
+
+_find_file.fill:
+
+ mov ax, [si + 22]
+ mov es:[bx + 22], ax
+
+ mov ax, [si + 24]
+ mov es:[bx + 24], ax
+
+ mov ax, [si + 28]
+ mov es:[bx + 26], ax
+
+ mov ax, [si + 30]
+ mov es:[bx + 28], ax
+
+ push bx
+
+ mov di, word ptr [bp - 42]
+ mov es, di
+
+ mov di, word ptr [bp - 32]
+ add di, 30
+
+ mov bl, [si + 11]
+ call _compress_filename
+
+ pop bx
+
+_find_file.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 42
+ pop bp
+
+ xor ax, ax
+ clc
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file int21.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _bcd2int
+;******************************************************************************
+_bcd2int:
+
+ push bx
+ push cx
+ push dx
+
+ mov bx, ax
+
+ and ax, HEX (0F)
+ xchg cx, ax
+
+ shr bx
+ shr bx
+ shr bx
+ shr bx
+
+ and bx, HEX (0F)
+
+ mov ax, 10
+ mul bx
+
+ add cx, ax
+ xchg ax, cx
+
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+;******************************************************************************
+; @function _expand_file_spec
+;******************************************************************************
+_expand_file_spec:
+
+ push ax
+ push bx
+ push si
+ push di
+
+ mov si, dx
+ add bx, 1 ; search template
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 1. Start with 11 spaces and the cursor at position 1.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, bx
+ mov cx, 11
+ mov al, ' '
+ rep stosb
+
+ mov di, bx ; cursor at position 1
+
+_expand_file_spec.read_char:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 2. Read a character from input and stop if at end.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ and al, al
+ jz _expand_file_spec.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 3. If the next character is a dot then set extension to ' '
+ ; move the cursor to position 9 and go to step 2.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp al, '.'
+ jne _expand_file_spec.check_asterisk
+
+ mov byte ptr es:[bx + 8], ' '
+ mov byte ptr es:[bx + 9], ' '
+ mov byte ptr es:[bx + 10], ' '
+
+ mov di, bx
+ add di, 8
+
+ jmp _expand_file_spec.read_char
+
+_expand_file_spec.check_asterisk:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 4. If the next character is an asterisk, then fill the rest of the
+ ;; pattern with question marks and move the cursor past the end
+ ;; and go to step 2.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp al, '*'
+ jne _expand_file_spec.not_asterisk
+
+ mov cx, bx
+ sub cx, di
+ add cx, 11
+ mov al, '?'
+ rep stosb
+
+ mov di, bx
+ add di, 11
+
+ jmp _expand_file_spec.read_char
+
+_expand_file_spec.not_asterisk:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 5. If not past the end, copy the character, and go to step 2.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, di
+ sub cx, bx
+
+ cmp cx, 11
+ jae _expand_file_spec.read_char
+
+ cmp al, 'a'
+ jb _expand_file_spec.store
+
+ cmp al, 'z'
+ ja _expand_file_spec.store
+
+ and al, HEX (DF)
+
+_expand_file_spec.store:
+
+ stosb
+ jmp _expand_file_spec.read_char
+
+_expand_file_spec.done:
+
+ pop di
+ pop si
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _get_disk_info
+;******************************************************************************
+_get_disk_info:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+ push ds
+
+ mov ax, cs:[_selected_disk]
+ mov word ptr [bp - 2], ax
+
+_get_disk_info.check:
+
+ push si
+
+ call _strlen
+ add sp, 2
+
+ cmp ax, 2
+ jb _get_disk_info.got_disk
+
+ cmp byte ptr [si + 1], ':'
+ jne _get_disk_info.got_disk
+
+ xor ah, ah
+ mov al, [si]
+
+ push ax
+
+ call _isalpha
+ mov cx, ax
+
+ pop ax
+
+ and cx, cx
+ jz _get_disk_info.got_disk
+
+ add si, 2
+ push ax
+
+ call _toupper
+ add sp, 2
+
+ sub al, HEX (41)
+
+ cmp ax, cs:[_selected_disk]
+ je _get_disk_info.got_disk
+
+ mov word ptr [bp - 2], ax
+ inc ax
+
+ cmp cs:[_vec_parts + 4], ax
+ jb _get_disk_info.error
+
+ dec ax
+
+ cmp ax, 2
+ jae _get_disk_info.got_disk
+
+ call _probe_disk
+ jc _get_disk_info.error
+
+_get_disk_info.got_disk:
+
+ mov ax, word ptr [bp - 2]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_parts]
+ mov es, ax
+
+ mov ax, es:[bx]
+
+_get_disk_info.copy:
+
+ push si
+
+ mov ds, ax
+ xor si, si
+
+ lodsw
+ ;mov cs:[_curr_path], ax
+
+ lodsw
+ mov cs:[_curr_cluster], ax
+
+ lodsw
+ mov cs:[_curr_cluster + 2], ax
+
+ lodsw
+ mov cs:[_disk_scratch], 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
+
+ pop si
+
+ mov bx, cs:[_root_cluster]
+ mov cx, cs:[_root_cluster + 2]
+
+ or bx, cx
+
+ and bx, bx
+ jnz _get_disk_info.fat32
+
+ call _getfattype
+ jmp _get_disk_info.done
+
+_get_disk_info.fat32:
+
+ mov ax, offset _convert_cluster32
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat32
+ mov cs:[_next_cluster], ax
+
+_get_disk_info.done:
+
+ mov word ptr cs:[_fat_sector], ax
+ mov word ptr cs:[_fat_sector + 2], ax
+
+ pop ds
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 2
+ clc
+
+ pop bp
+ ret
+
+_get_disk_info.error:
+
+ xor ax, ax
+
+ pop ds
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 2
+ stc
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _probe_disk
+;******************************************************************************
+_probe_disk:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov dx, ax
+
+_probe_disk.read:
+
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Okay, we are booted from a floppy so we need to figure out which
+ ;; address it is within our _Vec_parts "structure".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_parts]
+ mov es, ax
+
+ mov ax, es:[bx]
+ mov es, ax
+
+ pop dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try and read the drive.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+
+ mov ax, es:[HEX (0006)]
+ mov es, ax
+ xor bx, bx
+
+ mov ax, HEX (0201)
+ mov cx, HEX (0001)
+ stc
+ int HEX (13)
+ pop es
+ jc _probe_disk.error
+
+ mov ax, es:[HEX (0006)]
+ mov ds, ax
+
+_probe_disk.check:
+
+ cmp byte ptr [HEX (0000)], HEX (EB)
+ jne _probe_disk.error
+
+ cmp byte ptr [HEX (0002)], HEX (90)
+ jne _probe_disk.error
+
+_probe_disk.calc:
+
+ mov di, 8
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Next we'll copy the BPB to our "structure".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, bx
+ add si, 11
+
+ mov cx, 25
+ rep movsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the drive number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, dl
+ stosb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Floppies should be FAT12 so pad with zeros.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ xor dx, dx
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, [HEX (001C)]
+ mov di, [HEX (001E)]
+
+ add si, [HEX (000E)]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, di
+ pop di
+
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, cx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Repush di and reset the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+ push di
+ mov di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, [HEX (0010)]
+ cbw
+ mul word ptr [HEX (0016)]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, di
+ pop di
+
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, cx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Repush di and reset the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+ push di
+ mov di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr [HEX (0011)]
+ div word ptr [HEX (000B)]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, di
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, dx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Floppies shouldn't have a sector mask or shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Figure out how big a cluster is.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [HEX (000B)]
+ xor dx, dx
+
+ xor ch, ch
+ mov cl, [HEX (000D)]
+
+ mul cx
+ stosw
+
+ clc
+ jmp _probe_disk.done
+
+_probe_disk.error:
+
+ stc
+
+_probe_disk.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _int21_dispatch
+;******************************************************************************
+global _int21_dispatch
+_int21_dispatch:
+
+ mov cs:[_user_sssp + 2], ss
+ mov cs:[_user_sssp], sp
+
+ mov cs:[_user_ax], ax
+ mov cs:[_user_bp], bp
+
+ cmp ah, HEX (01)
+ jb _int21_dispatch.no_key
+
+ cmp ah, HEX (05)
+ jbe _int21_dispatch.check
+
+ cmp ah, HEX (08)
+ jb _int21_dispatch.no_key
+
+ cmp ah, HEX (0B)
+ ja _int21_dispatch.no_key
+
+_int21_dispatch.check:
+
+ push ax
+ mov ah, HEX (01)
+ int HEX (16)
+ pop ax
+ jz _int21_dispatch.no_key
+
+ push ax
+ xor ah, ah
+ int HEX (16)
+ cmp ax, HEX (2E03)
+ pop ax
+ jne _int21_dispatch.no_key
+
+ mov al, '^'
+ call _writechr
+
+ mov al, 'C'
+ call _writechr
+
+ jmp _spawn_int23
+
+_int21_dispatch.no_key:
+
+ cld ; Make sure direction flag is always clean
+ push bx
+ push bp
+
+ ;mov bp, sp
+ ;mov word ptr [bp + 2], bx
+
+ mov bp, offset _int21_dispatch.list
+ mov bx, offset _int21_dispatch.list_end
+
+_int21_dispatch.L:
+
+ cmp bp, bx
+ jae _int21_dispatch.unimpl
+
+ cmp ah, cs:[bp]
+ jne _int21_dispatch.next
+
+ mov bx, cs:[bp + 1]
+
+ mov bp, sp
+ xchg word ptr [bp + 2], bx
+
+ pop bp
+ ret
+
+_int21_dispatch.next:
+
+ add bp, 3
+
+ cmp bp, bx
+ jb _int21_dispatch.L
+
+_int21_dispatch.unimpl:
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ and dl, dl
+ jz _int21_dispatch.col_ok
+
+ mov al, HEX (0D)
+ call _writechr
+
+ mov al, HEX (0A)
+ call _writechr
+
+_int21_dispatch.col_ok:
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Unimplemented syscall.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push ds
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _int21_dispatch.err
+ call _writestr
+
+ pop ds
+ pop ax
+ push di
+
+ mov word ptr cs:[_writehex_num_digits], 2
+ call _writehex
+ mov word ptr cs:[_writehex_num_digits], 4
+
+ pop di
+ call _crlf
+
+ pop bp
+ pop bx
+ iret
+
+_int21_dispatch.halt:
+
+ hlt
+ jmp short _int21_dispatch.halt
+
+_int21_dispatch.err:
+
+ db "Not implemented: INT 21h/AH=", 0x00
+
+_int21_dispatch.list:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Program Terminate.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (00)
+ dw _int21_00
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Display Output.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (02)
+ dw _int21_02
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Direct Console Input Without Echo.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (07)
+ dw _int21_07
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Console Input Without Echo.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (08)
+ dw _int21_08
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print String.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (09)
+ dw _int21_09
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Buffered Keyboard Input.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (0A)
+ dw _int21_0A
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Select Disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (0E)
+ dw _int21_0E
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get Current Default Drive.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (19)
+ dw _int21_19
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set Disk Transfer Address (DTA).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (1A)
+ dw _int21_1A
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set Interrupt Vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (25)
+ dw _int21_25
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get Date.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (2A)
+ dw _int21_2A
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get Time.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (2C)
+ dw _int21_2C
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get DOS Version Number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (30)
+ dw _int21_30
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set Current Directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3B)
+ dw _int21_3B
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Create File Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;db HEX (3C)
+ ;dw _int21_3C
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Open File Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3D)
+ dw _int21_3D
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Close File Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3E)
+ dw _int21_3E
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read From File or Device Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3F)
+ dw _int21_3F
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Delete/Unlink File.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;db HEX (41)
+ ;dw _int21_41
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move File Pointer Using Handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (42)
+ dw _int21_42
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get Current Directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (47)
+ dw _int21_47
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (48)
+ dw _int21_48
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free Allocated Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (49)
+ dw _int21_49
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Modify Allocated Memory Blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4A)
+ dw _int21_4A
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Exec Program.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4B)
+ dw _int21_4B
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Terminate Process With Return Code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4C)
+ dw _int21_4C
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Find First Matching File.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4E)
+ dw _int21_4E
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Find Next Matching File.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (4F)
+ dw _int21_4F
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Create File.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;db HEX (5B)
+ ;dw _int21_5B
+
+_int21_dispatch.list_end:
+
+;******************************************************************************
+; @function iretc
+;******************************************************************************
+iretc:
+
+ push bp
+
+ mov bp, sp
+ jc iretc.c
+
+ and byte ptr [bp + 6], HEX (FE) ; clear carry
+ jmp short iretc.ret
+
+iretc.c:
+
+ or byte ptr [bp + 6], 1 ; set carry
+
+iretc.ret:
+
+ pop bp
+ iret
+
+
+;******************************************************************************
+; @function _int21_00
+; @brief Program Terminate
+;******************************************************************************
+_int21_00:
+
+ xor al, al
+ jmp _int21_4C
+
+;******************************************************************************
+; @function _int21_02
+; @brief Display Ouput
+;
+; @in DL -> Character to output.
+;******************************************************************************
+_int21_02:
+
+ push ax
+
+ mov al, dl
+ call _writechr
+
+ pop ax
+ iret
+
+;******************************************************************************
+; @function _int21_07
+; @brief Direct Console Input Without Echo
+;******************************************************************************
+_int21_07:
+
+ mov al, cs:[_int21_07.got_extend]
+
+ and al, al
+ jz _int21_07.wait
+
+ mov byte ptr cs:[_int21_07.got_extend], 0
+ jmp _int21_07.done
+
+_int21_07.wait:
+
+ xor ah, ah
+ int HEX (16)
+
+ and al, al
+ jnz _int21_07.done
+
+ mov cs:[_int21_07.got_extend], ah
+
+_int21_07.done:
+
+ mov ah, HEX (07)
+ iret
+
+_int21_07.got_extend: db HEX (00)
+
+;******************************************************************************
+; @function _int21_08
+; @brief Console Input Without Echo
+;******************************************************************************
+_int21_08:
+
+ mov al, cs:[_int21_08.scan]
+
+ and al, al
+ jz _int21_08.wait
+
+ mov byte ptr cs:[_int21_08.scan], 0
+ jmp _int21_08.done
+
+_int21_08.wait:
+
+ xor ah, ah
+ int HEX (16)
+
+ cmp ax, HEX (2E03)
+ jne _int21_08.char_ok
+
+ mov al, '^'
+ call _writechr
+
+ mov al, 'C'
+ call _writechr
+
+ mov al, HEX (0D)
+ call _writechr
+
+ mov al, HEX (0A)
+ call _writechr
+
+ jmp _spawn_int23
+
+_int21_08.char_ok:
+
+ mov cs:[_int21_08.scan], ah
+
+ and al, al
+ jz _int21_08.done
+
+ mov byte ptr cs:[_int21_08.scan], 0
+
+_int21_08.done:
+
+ mov ah, HEX (08)
+ iret
+
+_int21_08.scan: db HEX (00)
+
+;******************************************************************************
+; @function _int21_09
+; @brief Print String
+;
+; @in DS:DX -> Pointer to string ending in '$'.
+;******************************************************************************
+_int21_09:
+
+ push ax
+ push si
+
+ mov si, dx
+
+_int21_09.loop:
+
+ lodsb
+
+ cmp al, '$'
+ je _int21_09.done
+
+ call _writechr
+ jmp short _int21_09.loop
+
+_int21_09.done:
+
+ pop si
+ pop ax
+ iret
+
+;******************************************************************************
+; @function _int21_0A
+; @brief Buffered Keyboard Input
+;
+; @in DS:DX -> Pointer to input buffer of the format:
+; | max | count | BUFFER (N bytes)
+; | | `------- input buffer
+; | `------------ number of characters returned (byte)
+; `-------------- maximum number of characters to read (byte)
+;******************************************************************************
+_int21_0A:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 4
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ mov [bp - 2], dh
+ mov [bp - 1], dl
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ mov di, dx
+
+ mov cx, [di]
+ add di, 2
+
+ and cl, cl
+ jz _int21_0A.ret
+
+ dec cl
+
+ cmp ch, cl
+ jae _int21_0A.ret
+
+ xor bh, bh
+ mov bl, ch
+ add di, bx
+
+_int21_0A.get_chars:
+
+ xor ax, ax
+ int HEX (16)
+
+ cmp ax, HEX (2E03)
+ jne _int21_0A.check_key
+
+ mov al, HEX (0D)
+ stosb
+
+ mov di, dx
+ mov byte ptr [di + 1], 0
+
+ mov al, '^'
+ call _writechr
+
+ mov al, 'C'
+ call _writechr
+
+ mov al, HEX (0D)
+ call _writechr
+
+ mov al, HEX (0A)
+ call _writechr
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 4
+ pop bp
+
+ jmp _spawn_int23
+
+_int21_0A.check_key:
+
+ cmp ax, HEX (0E7F)
+ je _int21_0A.handle_bs
+
+ cmp ah, HEX (4B)
+ je _int21_0A.handle_bs
+
+ cmp al, HEX (0D)
+ je _int21_0A.done
+
+ cmp al, HEX (08)
+ jne _int21_0A.not_bs
+
+_int21_0A.handle_bs:
+
+ and ch, ch
+ jz _int21_0A.get_chars
+
+ xor ah, ah
+ mov al, [bp - 1]
+
+ push cx
+ push dx
+ xor dx, dx
+
+ mov cl, ch
+ xor ch, ch
+ add ax, cx
+
+ mov cx, HEX (50)
+ div cx
+
+ xchg ax, dx
+ pop dx
+ pop cx
+
+ and ax, ax
+ jnz _int21_0A.handle_bs2
+
+ push ax
+ push bx
+ push dx
+ push cx
+
+ mov ax, HEX (0300)
+ xor bx, bx
+ int HEX (10)
+
+ pop cx
+ dec dh
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (50)
+ int HEX (10)
+
+ call _int21_0A.erase_char
+
+ mov ax, HEX (0200)
+ xor bx, bx
+ mov dl, HEX (4F)
+ int HEX (10)
+
+ pop dx
+ pop bx
+ pop ax
+
+ dec ch
+ dec di
+ mov byte ptr es:[di], 0
+
+ jmp _int21_0A.get_chars
+
+_int21_0A.handle_bs2:
+
+ call _int21_0A.erase_char
+
+ dec ch
+ dec di
+ mov byte ptr es:[di], 0
+
+ jmp _int21_0A.get_chars
+
+_int21_0A.not_bs:
+
+ cmp ch, cl
+ jae _int21_0A.get_chars
+
+ cmp al, HEX (20)
+ jb _int21_0A.get_chars
+
+ cmp al, HEX (7F)
+ ja _int21_0A.get_chars
+
+ call _writechr
+ stosb
+
+ inc ch
+ jmp _int21_0A.get_chars
+
+_int21_0A.done:
+
+ mov al, HEX (0D)
+ stosb
+
+ mov di, dx
+ mov [di + 1], ch
+
+_int21_0A.ret:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 4
+ pop bp
+
+ iret
+
+_int21_0A.erase_char:
+
+ mov al, HEX (08)
+ call _writechr
+
+ mov al, HEX (20)
+ call _writechr
+
+ mov al, HEX (08)
+ jmp _writechr
+
+;******************************************************************************
+; @function _int21_OE
+; @brief Select Disk
+;******************************************************************************
+_int21_0E:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+_int21_0E.check:
+
+ xor dh, dh
+
+ cmp dx, cs:[_selected_disk]
+ je _int21_0E.done
+
+ inc dx
+
+ cmp cs:[_vec_parts + 4], dx
+ jb _int21_0E.done
+
+ dec dx
+
+ cmp dx, 2
+ jae _int21_0E.set
+
+ mov ax, dx
+
+ call _probe_disk
+ jc _int21_0E.done
+
+_int21_0E.set:
+
+ mov cs:[_selected_disk], dx
+
+_int21_0E.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ mov al, cs:[_last_drive]
+
+ cmp al, 5
+ jae _int21_0E.ret
+
+ mov al, 5
+
+_int21_0E.ret:
+
+ iret
+
+;******************************************************************************
+; @function _int21_19
+; @brief Get Current Default Drive
+;
+; @out AL -> Current default drive.
+;******************************************************************************
+_int21_19:
+
+ mov al, cs:[_selected_disk]
+ iret
+
+;******************************************************************************
+; @function _int21_1A
+; @brief Set Disk Transfer Address (DTA)
+;
+; @in DS:DX -> Pointer to disk transfer address.
+;******************************************************************************
+_int21_1A:
+
+ mov cs:[_disk_transfer_addr], dx
+ mov cs:[_disk_transfer_addr + 2], ds
+
+ iret
+
+;******************************************************************************
+; @function _int21_25
+; @brief Set Interrupt Vector
+;
+; @in AL -> Interrupt number.
+; @in DS:DX = -> Pointer to interrupt handler.
+;******************************************************************************
+_int21_25:
+
+ push es
+ push bx
+
+ xor bx, bx
+ mov es, bx
+
+ mov bl, al
+ shl bx
+ shl bx
+
+ mov word ptr es:[bx], dx
+ mov word ptr es:[bx + 2], ds
+
+ pop bx
+ pop es
+ iret
+
+;******************************************************************************
+; @function _int21_2A
+; @brief Get Date
+;
+; @out AL -> Day of the week (0 = Sunday).
+; @out CX -> Year (1980 - 2009).
+; @out DH -> Month (1 - 12).
+; @out DL -> Day (1 - 31)
+;******************************************************************************
+_int21_2A:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 8
+
+ push ax
+ push bx
+ push si
+ push di
+
+ xor cx, cx
+ xor dx, dx
+
+ mov ah, HEX (04)
+ clc
+ int HEX (1A)
+ jnc _int21_2A.ok
+
+ mov word ptr [bp - 8], 1980
+ mov byte ptr [bp - 4], 1
+ mov byte ptr [bp - 2], 1
+
+ jmp _int21_2A.done
+
+_int21_2A.ok:
+
+ mov bx, dx
+ xor dx, dx
+
+ xor ah, ah
+ mov al, ch
+ call _bcd2int
+
+ mov di, 100
+ mul di
+ xchg di, ax
+
+ xor ah, ah
+ mov al, cl
+ call _bcd2int
+
+ add di, ax
+
+ cmp di, 1980
+ jae _int21_2A.got_year
+
+ mov ax, 1980
+ add di, ax
+
+_int21_2A.got_year:
+
+ mov word ptr [bp - 8], di
+
+ xor ah, ah
+ mov al, bh
+ call _bcd2int
+
+ or al, al
+ jnz _int21_2A.got_month
+
+ mov al, 1
+
+_int21_2A.got_month:
+
+ mov byte ptr [bp - 4], al
+
+ xor ah, ah
+ mov al, bl
+ call _bcd2int
+
+ or al, al
+ jnz _int21_2A.got_day
+
+ mov al, 1
+
+_int21_2A.got_day:
+
+ mov byte ptr [bp - 2], al
+
+_int21_2A.done:
+
+ pop di
+ pop si
+ pop bx
+ pop ax
+
+ mov cx, word ptr [bp - 8]
+ mov dh, byte ptr [bp - 4]
+ mov dl, byte ptr [bp - 2]
+
+ add sp, 8
+ pop bp
+
+ iret
+
+;******************************************************************************
+; @function _int21_2C
+; @brief Get Time
+;
+; @out CH -> Hour (0 - 23).
+; @out CL -> Minutes (0 - 59).
+; @out DH -> Seconds (0 - 59).
+; @out DL -> Hundreths (0 - 99)
+;******************************************************************************
+_int21_2C:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 6
+
+ push ax
+ push bx
+ push si
+ push di
+
+ xor cx, cx
+ xor dx, dx
+
+ xor ah, ah
+ int HEX (1A)
+
+ mov ax, dx ; low 16 bits
+ mov dx, cx ; high 16 bits
+
+ push ax
+ push dx
+
+ xor di, di
+ push di
+
+ mov di, 1
+ push di
+
+ mov di, 7
+ push di
+
+ push dx
+ push ax
+
+ call _udivmodsi4
+ add sp, 10
+
+ mov byte ptr [bp - 6], al
+
+ pop dx
+ pop ax
+
+ mov di, 1
+ push di
+
+ mov di, 1
+ push di
+
+ mov di, 7
+ push di
+
+ push dx
+ push ax
+
+ call _udivmodsi4
+ add sp, 10
+
+ mov cx, 1092
+ div cx
+
+ mov byte ptr [bp - 4], al
+
+ mov ax, 100
+ mul dx
+
+ mov cx, 1821
+ div cx
+
+ mov byte ptr [bp - 2], al
+
+_int21_2C.done:
+
+ pop di
+ pop si
+ pop bx
+ pop ax
+
+ mov ch, byte ptr [bp - 6]
+ mov cl, byte ptr [bp - 4]
+ mov dh, byte ptr [bp - 2]
+ xor dl, dl
+
+ add sp, 6
+ pop bp
+
+ iret
+
+;******************************************************************************
+; @function _int21_30
+; @brief Get DOS Version Number
+;******************************************************************************
+_int21_30:
+
+ ;mov ax, HEX (0030)
+ xor ax, ax
+
+ xor bx, bx
+ xor cx, cx
+
+ iret
+
+;******************************************************************************
+; @function _int21_3B
+; @brief Set Current Directory
+;
+; @in DS:DX -> ASCIIZ path name (max 64 bytes).
+;******************************************************************************
+_int21_3B:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov ax, cs:[_selected_disk]
+ mov word ptr [bp - 2], ax
+
+ mov si, dx
+
+_int21_3B.check3:
+
+ push si
+
+ call _strlen
+ add sp, 2
+
+ cmp ax, 2
+ jb _int21_3B.got_disk
+
+ cmp byte ptr [si + 1], ':'
+ jne _int21_3B.got_disk
+
+ xor ah, ah
+ mov al, [si]
+
+ push ax
+
+ call _isalpha
+ mov cx, ax
+
+ pop ax
+
+ and cx, cx
+ jz _int21_3B.got_disk
+
+ add si, 2
+ push ax
+
+ call _toupper
+ add sp, 2
+
+ sub al, HEX (41)
+
+ cmp ax, cs:[_selected_disk]
+ je _int21_3B.got_disk
+
+ mov word ptr [bp - 2], ax
+ inc ax
+
+ cmp cs:[_vec_parts + 4], cx
+ jb _int21_3B.error
+
+ dec ax
+
+ cmp ax, 2
+ jae _int21_3B.got_disk
+
+ call _probe_disk
+ jc _int21_3B.error
+
+_int21_3B.got_disk:
+
+ mov ax, word ptr [bp - 2]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_parts]
+ mov es, ax
+
+ mov ax, es:[bx]
+ mov es, ax
+
+_int21_3B.copy:
+
+ push es
+ push si
+ push ds
+
+ xor si, si
+ mov ds, ax
+
+ lodsw
+ ;mov cs:[_curr_path], ax
+
+ lodsw
+ mov cs:[_curr_cluster], ax
+
+ lodsw
+ mov cs:[_curr_cluster + 2], ax
+
+ lodsw
+ mov cs:[_disk_scratch], 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
+
+ pop ds
+ pop si
+ pop es
+
+ mov bx, cs:[_root_cluster]
+ mov cx, cs:[_root_cluster + 2]
+
+ or bx, cx
+
+ and bx, bx
+ jnz _int21_3B.fat32
+
+ call _getfattype
+ jmp _int21_3B.get_path
+
+_int21_3B.fat32:
+
+ mov ax, offset _convert_cluster32
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat32
+ mov cs:[_next_cluster], ax
+
+_int21_3B.get_path:
+
+ mov di, si
+
+ push es
+ push di
+
+ xor bx, bx
+ mov bx, es:[bx]
+
+ mov di, offset _int21_3B.path
+
+ mov ax, cs
+ mov es, ax
+
+ cmp byte ptr [si], '\\'
+ je _int21_3B.setup
+
+ mov al, '\\'
+ stosb
+
+ push si
+ push ds
+
+ mov ds, bx
+ xor si, si
+
+ push si
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ rep movsb
+
+ pop ds
+ pop si
+
+_int21_3B.setup:
+
+ mov ax, offset _int21_3B.path
+
+ mov cx, di
+ sub cx, ax
+
+ cmp cx, 1
+ je _int21_3B.no_slash
+
+ mov al, '\\'
+ stosb
+
+_int21_3B.no_slash:
+
+ mov bx, si
+
+_int21_3B.loop:
+
+ mov ax, si
+ sub ax, bx
+
+ cmp ax, 65
+ ja _int21_3B.check
+
+ lodsb
+
+ or al, al
+ jz _int21_3B.check
+
+ cmp al, '.'
+ je _int21_3B.check_curr
+
+ cmp al, '\\'
+ jne _int21_3B.convert_alpha
+
+ cmp si, bx
+ je _int21_3B.loop
+
+ cmp byte ptr es:[di - 1], '\\'
+ je _int21_3B.loop
+
+_int21_3B.convert_alpha:
+
+ xor ah, ah
+ push ax
+
+ call _isalpha
+
+ and ax, ax
+ jz _int21_3B.no_alpha
+
+ call _toupper
+ add sp, 2
+
+ jmp _int21_3B.char_ok
+
+_int21_3B.no_alpha:
+
+ pop ax
+ jmp _int21_3B.char_ok
+
+_int21_3B.check_curr:
+
+ cmp byte ptr [si], 0
+ je _int21_3B.loop
+
+ cmp byte ptr [si], '\\'
+ je _int21_3B.loop
+
+ cmp byte ptr [si], '.'
+ je _int21_3B.check_prev
+
+ jmp _int21_3B.char_ok
+
+_int21_3B.check_prev:
+
+ cmp byte ptr [si + 1], 0
+ je _int21_3B.get_prev
+
+ cmp byte ptr [si + 1], '\\'
+ jne _int21_3B.char_ok
+
+_int21_3B.get_prev:
+
+ mov byte ptr es:[di - 1], 0
+
+ push si
+ push ds
+
+ mov ax, es
+ mov ds, ax
+
+ mov ax, '\\'
+ push ax
+
+ mov ax, offset _int21_3B.path
+ push ax
+
+ call _strrchr
+ add sp, 4
+
+ pop ds
+ pop si
+
+ mov di, ax
+ inc di
+ mov byte ptr es:[di], 0
+
+ jmp _int21_3B.loop
+
+_int21_3B.char_ok:
+
+ stosb
+ jmp _int21_3B.loop
+
+_int21_3B.check:
+
+ cmp byte ptr es:[di - 1], '\\'
+ jne _int21_3B.check2
+
+ dec di
+
+_int21_3B.check2:
+
+ xor al, al
+ stosb
+
+ pop di
+ pop es
+
+ cmp byte ptr [si], 0
+ jne _int21_3B.error
+
+_int21_3B.search:
+
+ mov ax, cs
+ mov ds, ax
+
+ mov di, offset _int21_3B.path
+
+ cmp byte ptr [di], 0
+ jne _int21_3B.walk
+
+ mov ax, cs:[_root_cluster]
+ mov dx, cs:[_root_cluster + 2]
+
+ mov es:[HEX (0002)], ax
+ mov es:[HEX (0004)], dx
+
+ xor di, di
+
+ mov ax, es:[di]
+ mov es, ax
+
+ xor al, al
+
+ mov cx, 65
+ rep stosb
+
+ jmp _int21_3B.done
+
+_int21_3B.walk:
+
+ call _walk_path
+ jc _int21_3B.error
+
+ call _mangle_dos_name
+ jc _int21_3B.error
+
+ call _search_dos_dir
+ jc _int21_3B.error
+
+ push bx
+ push es
+
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ mov ax, es:[bx + 0]
+ mov dx, es:[bx + 2]
+
+ mov cl, es:[bx + 8]
+
+ pop es
+ pop bx
+
+ test cl, HEX (10)
+ jz _int21_3B.error
+
+ mov es:[HEX (0002)], ax
+ mov es:[HEX (0004)], dx
+
+_int21_3B.copy2:
+
+ mov ax, cs
+ mov ds, ax
+
+ mov si, offset _int21_3B.path
+ inc si
+
+ xor di, di
+
+ mov ax, es:[di]
+ mov es, ax
+
+ push si
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ rep movsb
+
+ xor ax, ax
+ stosb
+
+ jmp _int21_3B.done
+
+_int21_3B.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ mov ax, 3
+ stc
+
+ jmp iretc
+
+_int21_3B.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ xor ax, ax
+ clc
+
+ jmp iretc
+
+_int21_3B.path: db 66 dup (0)
+
+;******************************************************************************
+; @function _int21_3D
+; @brief Open File Using Handle
+;
+; @in AL -> Open access mode.
+; @in DS:DX -> Pointer to an ASCIIZ file name.
+;
+; @out AX -> File handle. Error code if CF is set.
+;******************************************************************************
+_int21_3D:
+
+ push bp
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ xor bh, bh
+ mov bl, al
+
+ mov si, dx
+
+ call _get_disk_info
+ jc _int21_3D.error
+
+ mov di, si
+
+_int21_3D.open:
+
+ call _open_file
+ jmp _int21_3D.done
+
+_int21_3D.error:
+
+ mov ax, 3
+ stc
+
+_int21_3D.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_3E
+; @brief Close File Using Handle
+;
+; @in BX -> File handle to close..
+; @out AX -> Clear. Error code if CF is set.
+;******************************************************************************
+_int21_3E:
+
+ call _close_file
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_3F
+; @brief Read From File or Device Using Handle
+;
+; @in BX -> File handle..
+; @in CX -> Number of bytes to read.
+; @in DS:DX -> Pointer to read buffer.
+;
+; @out AX -> Number of bytes read. Error code if CF is set.
+;******************************************************************************
+_int21_3F:
+
+ push bp
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _int21_3F.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _int21_3F.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_3F.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-initialize the extra segment but this time with the address
+ ;; of the vector entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+_int21_3F.copy:
+
+ push si
+ push ds
+ push ax
+
+ 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
+
+ mov bx, cs:[_root_cluster]
+ mov cx, cs:[_root_cluster + 2]
+
+ or bx, cx
+
+ and bx, bx
+ jnz _int21_3F.fat32
+
+ call _getfattype
+ jmp _int21_3F.read
+
+_int21_3F.fat32:
+
+ mov ax, offset _convert_cluster32
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat32
+ mov cs:[_next_cluster], ax
+
+_int21_3F.read:
+
+ pop ax
+ pop ds
+ pop si
+ mov es, ax
+
+ xor si, si
+ call _read_file
+
+ jmp _int21_3F.done
+
+_int21_3F.error:
+
+ mov ax, 6
+ stc
+
+_int21_3F.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_42
+; @brief Move File Pointer Using Handle
+;
+; @in AL -> Origin of move:
+; 00 = Beginning of file plus offset (SEEK_SET)
+; 01 = Current location plus offset (SEEK_CUR)
+; 02 = End of file plus offset (SEEK_END)
+; @in BX -> File handle.
+; @in CX -> High order word of number of bytes to move.
+; @in DX -> Low order word of number of bytes to move.
+;
+; @out AX -> Error code if CF is set.
+; @out DX:AX -> New pointer location if CF not set.
+;******************************************************************************
+_int21_42:
+
+ call _seek_file
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_47
+; @brief Get Current Directory
+;
+; @in DL -> Drive number.
+; @in DS:SI -> Pointer to a 64 byte user buffer.
+;
+; @out AX -> Error code if CF is set.
+;******************************************************************************
+_int21_47:
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ xor dh, dh
+ mov ax, dx
+
+ and ax, ax
+ jnz _int21_47.check
+
+ mov ax, cs:[_selected_disk]
+ jmp _int21_47.got_disk
+
+_int21_47.check:
+
+ mov cx, cs:[_vec_parts + 4]
+ inc ax
+
+ cmp ax, cx
+ ja _int21_47.error
+
+ dec ax
+
+_int21_47.got_disk:
+
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov di, ax
+
+ mov ax, cs:[_vec_parts + 0]
+ mov es, ax
+
+ mov di, es:[di]
+ mov es, di
+
+ mov bx, es:[HEX (0000)]
+
+ mov ax, ds
+ mov es, ax
+
+ mov ds, bx
+
+ mov di, si
+ xor si, si
+
+ mov cx, 64
+ rep movsb
+
+ xor al, al
+ stosb
+
+ mov ax, HEX (0100)
+ clc
+
+ jmp short _int21_47.done
+
+_int21_47.error:
+
+ mov ax, 15
+ stc
+
+_int21_47.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_48
+; @brief Allocate Memory Blocks
+;
+; @in BX -> Number of memory paragraphs requested.
+;
+; @out AX -> Segment address of allocated memory block
+; (MCB + lpara). Error code if CF is set.
+; @out BX -> Size in paras of the largets block of memory
+; available if CF is set and AX = 08 (Not enough mem).
+;******************************************************************************
+_int21_48:
+
+ call _alloc_mem
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_49
+; @brief Free Allocated Memeory Blocks
+;
+; @in ES -> Segment of the block to be returned (MCB + lpara).
+; @out AX -> Clear.
+;******************************************************************************
+_int21_49:
+
+ call _free_mem
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_4A
+; @brief Resize Allocated Memory Blocks
+;
+; @in BX -> New requested block size in paragraphs.
+; @in ES -> Segment of block to resize.
+;
+; @out AX -> Segment address of memory block (MCB + lpara).
+; Error code if CF is set.
+; @out BX -> Set to maximum block size possible if the request
+; block size is greater than what available.
+;******************************************************************************
+_int21_4A:
+
+ call _resize_mem
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_4B
+; @brief Exec Program
+;
+; @in DS:DX -> Pointer to an ASCIIZ filename.
+; @in ES:BX -> Pointer to a parameter block.
+;******************************************************************************
+_int21_4B:
+
+ and al, al
+ jz _int21_4B.arg_ok
+
+ mov ax, 1
+ stc
+
+ jmp iretc
+
+_int21_4B.arg_ok:
+
+ push bp
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ push ax
+ push bx
+ push es
+
+ mov si, dx
+
+ call _get_disk_info
+ jc _int21_4B.disk_error
+
+ mov di, si
+
+ mov ax, es:[bx + 2]
+ push ax
+
+ mov ax, es:[bx + 4]
+ push ax
+
+_int21_4B.load:
+
+ call _load_program
+ pop ds
+ pop si
+ jc _int21_4B.load_error
+
+ and ax, ax
+ jnz _int21_4B.load_ok
+
+_int21_4B.load_error:
+
+ pop es
+ pop bx
+ pop si
+
+ jmp _int21_4B.error
+
+_int21_4B.disk_error:
+
+ pop es
+ pop bx
+ pop si
+
+ mov ax, 3
+
+_int21_4B.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ stc
+ jmp iretc
+
+_int21_4B.load_ok:
+
+ mov es, ax
+
+ mov di, HEX (80)
+ mov cl, [si]
+ mov ch, HEX (7E)
+
+ cmp cl, ch
+ jbe _int21_4B.copy_cmd_line
+
+ mov cl, ch
+
+_int21_4B.copy_cmd_line:
+
+ xor ch, ch
+ inc cl
+ rep movsb
+
+ mov byte ptr es:[di], HEX (0D)
+ pop es
+ pop di
+ pop bx
+
+ and bl, bl
+ jz _int21_4B.start
+
+ mov ax, cs
+ mov ds, ax
+
+ add di, 14
+
+ mov ax, cs:[_child_sssp]
+ stosw
+
+ mov ax, cs:[_child_sssp + 2]
+ stosw
+
+ mov ax, cs:[_child_csip]
+ stosw
+
+ mov ax, cs:[_child_csip + 2]
+ stosw
+
+ jmp short _int21_4B.ret_ok
+
+_int21_4B.start:
+
+ call _start_program
+
+ mov al, cs:[_last_ret_val]
+
+_int21_4B.ret_ok:
+
+ clc
+
+_int21_4B.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ jmp iretc
+
+;******************************************************************************
+; @function _int21_4C
+; @brief Terminate Process With Return Code
+;******************************************************************************
+_int21_4C:
+
+ xor ah, ah
+
+ mov cs:[_last_ret_val], ax
+ mov dx, cs:[_curr_psp]
+
+ mov bx, cs:[_vec_files]
+ mov es, bx
+ xor bx, bx
+
+ mov cx, cs:[_vec_files + 2]
+ push ds
+ push ax
+
+_int21_4C.check_file:
+
+ and cx, cx
+ jz _int21_4C.free_mem
+
+ cmp word ptr es:[bx], 0
+ je _int21_4C.next_file
+
+ mov di, es:[bx]
+ mov ds, di
+ xor di, di
+
+ mov ax, [di + 70]
+
+ cmp ax, dx
+ jne _int21_4C.next_file
+
+ mov ax, [di + 68]
+ push es
+
+ mov es, ax
+ call _free_mem
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free our entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ds
+ mov es, ax
+
+ call _free_mem
+ pop es
+
+ xor ax, ax
+ mov es:[bx], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Subtract 1 from the length.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec word ptr cs:[_vec_files + 4]
+
+_int21_4C.next_file:
+
+ add bx, 2
+ dec cx
+
+ jmp _int21_4C.check_file
+
+_int21_4C.free_mem:
+
+ mov bx, cs:[_free_seg]
+
+_int21_4C.mem_check:
+
+ mov es, bx
+ xor di, di
+
+ cmp bx, cs:[_max_seg]
+ jae _int21_4C.done
+
+ cmp byte ptr es:[di + 0], 'M'
+ jne _int21_4C.next_mem
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _int21_4C.next_mem
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _int21_4C.next_mem
+
+ mov cx, es:[di + 3]
+ mov ax, es:[di + 5]
+
+ cmp ax, dx
+ jne _int21_4C.no_free
+
+ mov di, es
+ inc di
+
+ mov es, di
+ call _free_mem
+
+_int21_4C.no_free:
+
+ add bx, cx
+
+_int21_4C.next_mem:
+
+ inc bx
+ jmp _int21_4C.mem_check
+
+_int21_4C.done:
+
+ mov ds, dx
+
+ xor ax, ax
+ mov es, ax
+
+ mov ax, [HEX (0A)]
+ mov es:[HEX (22) * 4], ax
+
+ mov ax, [HEX (0C)]
+ mov es:[(HEX (22) * 4) + 2], ax
+
+ mov ax, [HEX (0E)]
+ mov es:[HEX (23) * 4], ax
+
+ mov ax, [HEX (10)]
+ mov es:[(HEX (23) * 4) + 2], ax
+
+ pop ax
+ pop ds
+ mov es, dx
+
+ mov sp, es:[HEX (42)]
+ mov ss, es:[HEX (44)]
+
+ mov bx, es:[HEX (16)]
+ mov cs:[_curr_psp], bx
+
+ call _free_mem
+
+ xor bx, bx
+ mov es, bx
+
+ mov bx, HEX (22) * 4
+ jmp far ptr es:[bx]
+
+;******************************************************************************
+; @function _int21_4E
+; @brief Find First Matching File
+;
+; @in CX -> Attribute used during search.
+; @in DS:DX -> Pointer to ASCIIZ filespace, including wildcards.
+;******************************************************************************
+_int21_4E:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 10
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov ax, cs:[_selected_disk]
+ mov word ptr [bp - 10], ax
+
+ mov si, dx
+ push si
+
+ call _strlen
+ add sp, 2
+
+ cmp ax, 2
+ jb _int21_4E.got_disk
+
+ cmp byte ptr [si + 1], ':'
+ jne _int21_4E.got_disk
+
+ xor ah, ah
+ mov al, [si]
+
+ push ax
+
+ call _isalpha
+ mov bx, ax
+
+ pop ax
+
+ and bx, bx
+ jz _int21_4E.got_disk
+
+ push ax
+
+ call _toupper
+ add sp, 2
+
+ sub al, HEX (41)
+ mov word ptr [bp - 10], ax
+
+_int21_4E.got_disk:
+
+ call _get_disk_info
+ jc _int21_4E.no_path
+
+ mov di, si
+
+ call _walk_path
+ jc _int21_4E.no_path
+
+_int21_4E.got_path:
+
+ mov word ptr [bp - 6], si
+ mov word ptr [bp - 4], ax
+ mov word ptr [bp - 2], dx
+
+ cmp byte ptr [si], 0
+ je _int21_4E.get_wild
+
+ mov bx, si
+
+_int21_4E.loop:
+
+ mov al, [bx]
+
+ and al, al
+ jz _int21_4E.search
+
+ cmp al, '*'
+ je _int21_4E.ok
+
+ inc bx
+ jmp _int21_4E.loop
+
+_int21_4E.search:
+
+ mov ax, word ptr [bp - 4]
+ mov dx, word ptr [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push di
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _int21_4E.name_error
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bx
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag is set then we couldn't find the specified file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _int21_4E.no_file
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax register should contain information about the file so
+ ;; copy it into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment as the code segment and copy the value
+ ;; in the ax register into the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The info passed back to us from _search_dos_dir should contain the
+ ;; entry type at offset 8 so move that into the cl register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, es:[bx + 8]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the cluster as well.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx + 0]
+ mov dx, es:[bx + 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Was the entry a file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test cl, HEX (10)
+ jz _int21_4E.search_file
+
+ mov word ptr [bp - 4], ax
+ mov word ptr [bp - 2], dx
+
+_int21_4E.get_wild:
+
+ mov si, cs
+ mov ds, si
+
+ mov si, offset _int21_4E.wild
+ jmp _int21_4E.ok
+
+_int21_4E.search_file:
+
+ mov si, word ptr [bp - 6]
+
+_int21_4E.ok:
+
+ mov bx, cs:[_disk_transfer_addr + 2]
+ mov es, bx
+ mov bx, cs:[_disk_transfer_addr]
+
+ mov ax, word ptr [bp - 10]
+ mov es:[bx], al
+
+ mov cx, word ptr [bp - 8]
+ mov ax, word ptr [bp - 4]
+ mov dx, word ptr [bp - 2]
+
+ or cl, HEX (31) ; bit 0 and 5 (R/O and archive) are ignored
+ not cl
+ mov es:[bx + 12], cl ; Search attribute mask
+
+ push ax
+ push dx
+
+ mov dx, si
+ call _expand_file_spec
+
+ pop dx
+ pop ax
+
+ mov word ptr es:[bx + 13], 0
+ mov es:[bx + 15], ax
+ mov es:[bx + 19], dx
+
+ call _find_file
+ jc _int21_4E.no_file
+
+_int21_4E.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 10
+ pop bp
+
+ xor ax, ax
+ clc
+
+ jmp iretc
+
+_int21_4E.no_path:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 10
+ pop bp
+
+ mov ax, 3
+ stc
+
+ jmp iretc
+
+_int21_4E.name_error:
+
+ pop bx
+ pop di
+
+_int21_4E.no_file:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 10
+ pop bp
+
+ mov ax, 2
+ stc
+
+ jmp iretc
+
+_int21_4E.wild: db "*.*", HEX (00)
+
+;******************************************************************************
+; @function _int21_4F
+; @brief Find Next Matching File
+;
+; @in DS:DX -> Unchanged from previous function 4E.
+; @out AX -> Error code if CF is set.
+;******************************************************************************
+_int21_4F:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 8
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov bx, cs:[_disk_transfer_addr + 2]
+ mov es, bx
+ mov bx, cs:[_disk_transfer_addr]
+
+ xor ah, ah
+ mov al, es:[bx]
+
+ mov word ptr [bp - 2], ax
+
+_int21_4F.got_disk:
+
+ inc ax
+
+ cmp cs:[_vec_parts + 4], ax
+ jb _int21_4F.error
+
+ dec ax
+
+ push bx
+ push es
+ push dx
+
+ mov ax, word ptr [bp - 2]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_parts]
+ mov es, ax
+
+ mov ax, es:[bx]
+
+ pop dx
+ pop es
+ pop bx
+
+_int21_4F.copy:
+
+ push cx
+ push bx
+ push es
+ push ds
+ push si
+ push di
+
+ mov ds, ax
+ xor si, si
+
+ lodsw
+ ;mov cs:[_curr_path], ax
+
+ lodsw
+ mov cs:[_curr_cluster], ax
+
+ lodsw
+ mov cs:[_curr_cluster + 2], ax
+
+ lodsw
+ mov cs:[_disk_scratch], 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
+
+ pop di
+ pop si
+ pop ds
+ pop es
+
+ mov bx, cs:[_root_cluster]
+ mov cx, cs:[_root_cluster + 2]
+
+ or bx, cx
+
+ and bx, bx
+ jnz _int21_4F.fat32
+
+ call _getfattype
+ jmp _int21_4F.find
+
+_int21_4F.fat32:
+
+ mov ax, offset _convert_cluster32
+ mov cs:[_convert_cluster], ax
+
+ mov ax, offset _nextcluster_fat32
+ mov cs:[_next_cluster], ax
+
+_int21_4F.find:
+
+ pop bx
+ pop cx
+
+ mov ax, es:[bx + 15]
+ mov dx, es:[bx + 19]
+ mov cx, es:[bx + 12]
+
+ call _find_file
+ jc _int21_4F.error
+
+_int21_4F.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 8
+ pop bp
+
+ xor ax, ax
+ clc
+
+ jmp iretc
+
+_int21_4F.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 8
+ pop bp
+
+ mov ax, 18
+ stc
+
+ jmp iretc
--- /dev/null
+;******************************************************************************
+; @file int23.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _regain_control_int23
+;******************************************************************************
+_regain_control_int23:
+
+ push bp
+ mov bp, sp
+
+ mov bp, word ptr [bp + 2]
+ mov word ptr [bp - 3], ax
+
+ pop ax
+
+ mov word ptr [bp - 1], ax
+ mov ax, bp
+
+ dec ax
+ dec ax
+ dec ax
+ xchg ax, sp
+
+ pushf
+ add ax, (4 + 7)
+ sub ax, bp
+ pop ax
+ jz _int23_ign_carry
+
+ push ax
+ popf
+
+_int23_ign_carry:
+
+ pop ax
+ jnc _int23_respawn
+
+ xor ah, ah
+
+_int23_respawn:
+
+ pop bp
+ jmp _int21_dispatch
+
+;******************************************************************************
+; @function _int23_handler
+;******************************************************************************
+global _int23_handler
+_int23_handler:
+
+ stc
+ retf 0
+
+;******************************************************************************
+; @function _spawn_int23
+;******************************************************************************
+global _spawn_int23
+_spawn_int23:
+
+ mov bp, cs:[_user_sssp]
+ cli
+
+ mov ss, cs:[_user_sssp + 2]
+ mov sp, bp
+
+ sti
+ sub sp, 8
+
+ mov ax, cs:[_user_ax]
+ mov bp, cs:[_user_bp]
+
+ push ss
+ push bp
+
+ mov bp, sp
+ add bp, 4
+
+ mov word ptr [bp], HEX (23CD)
+ mov byte ptr [bp + 2], HEX (9A)
+ mov word ptr [bp + 3], offset _regain_control_int23
+ mov word ptr [bp + 5], cs
+
+ xchg word ptr [bp - 4], bp
+ clc
+
+ retf
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _user_sssp
+_user_sssp:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _user_ax
+_user_ax: dw HEX (0000)
+
+global _user_bp
+_user_bp: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file invalid.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _invalid_handler
+;******************************************************************************
+global _invalid_handler
+_invalid_handler:
+
+ push bp
+ mov bp, sp
+
+ push ax
+ push bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're within the kernel then we'll blue screen.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_curr_psp], 0
+ jne _invalid_handler.no_clear
+
+_invalid_handler.clear:
+
+ mov ax, HEX (0600)
+ mov bh, HEX (1F)
+ xor cx, cx
+ mov dx, HEX (1850)
+ int HEX (10)
+
+ mov ah, HEX (02)
+ xor bh, bh
+ xor dx, dx
+ int HEX (10)
+
+ jmp _invalid_handler.init
+
+_invalid_handler.no_clear:
+
+ call _crlf
+
+_invalid_handler.init:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the data segment is the dame as the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print our first message.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, offset _invalid_handler.msg
+ call _writestr
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print a newline.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+
+_invalid_handler.loop:
+
+ cmp si, 12 * 2
+ jae _invalid_handler.done
+
+ mov ax, si
+ xor dx, dx
+
+ mov cx, 12
+ div cx
+
+ and dx, dx
+ jnz _invalid_handler.print
+
+ call _crlf
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+_invalid_handler.print:
+
+ mov ax, word ptr [bp + si]
+ call _writehex
+
+ inc si
+ inc si
+
+ mov ax, si
+ xor dx, dx
+
+ mov cx, 12
+ div cx
+
+ and dx, dx
+ jz _invalid_handler.loop
+
+ mov al, ' '
+ call _writechr
+ call _writechr
+ call _writechr
+ call _writechr
+
+ jmp _invalid_handler.loop
+
+_invalid_handler.done:
+
+ call _crlf
+ call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we're within the kernel we don't want to try quiting
+ ;; the program.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_curr_psp], 0
+ je _invalid_handler.reboot
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Let's try and exit the current process.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (4C7F)
+ int HEX (21)
+
+_invalid_handler.reboot:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call error with our ending message.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "Press any key to reboot...", HEX (00)
+
+_invalid_handler.msg:
+
+ db "Trap to vector 6: Invalid opcode", HEX (00)
--- /dev/null
+;******************************************************************************
+; @file kernel.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Interrupt vectors.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define DIVIDE_VECTOR 0x00 ; Divide Interrupt Vector.
+%define INVALID_VECTOR 0x06 ; Invalid Opcode Interrupt Vector.
+%define REBOOT_VECTOR 0x19 ; Warm Reboot Interrupt Vector.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; DOS Interrupt Vectors.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%define INT20_VECTOR 0x20 ; Current Process Terminate Vector.
+%define INT21_VECTOR 0x21 ; DOS API Vector.
+%define INT22_VECTOR 0x22 ; Program Terminate Interrupt Vector.
+%define INT23_VECTOR 0x23 ; CTRL-C Interrupt Vector.
+
+;******************************************************************************
+; @function _all_read
+;******************************************************************************
+global _all_read
+_all_read:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the value that's in the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data segment with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the drive no.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [_drive_no], dl
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the stack segment with the value stored in bx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ss, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We should only need a little room for the stack so set the
+ ;; stack pointer to 2048.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov sp, HEX (0800)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to out main code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _real_start
+
+;******************************************************************************
+; @function _clear_kbd
+;******************************************************************************
+;_clear_kbd:
+;
+; push ax
+;
+;_clear_kbd.loop:
+;
+; mov ah, HEX (01)
+; int HEX (16)
+; jz _clear_kbd.done
+;
+; xor ah, ah
+; int HEX (16)
+;
+; jmp short _clear_kbd.loop
+;
+;_clear_kbd.done:
+;
+; pop ax
+; ret
+
+;******************************************************************************
+; @function _int20_handler
+;******************************************************************************
+_int20_handler:
+
+ mov ax, HEX (4C00)
+ jmp _int21_dispatch
+
+;******************************************************************************
+; @function _int22_handler
+;******************************************************************************
+_int22_handler:
+
+ ret
+
+;******************************************************************************
+; @function _reboot_handler
+;******************************************************************************
+_reboot_handler:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Disable interrupts and clear the direction flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cli
+ cld
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push ds
+ push si
+ push di
+ push ax
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the data and extra segments with the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Setup si and bx to point to our list and list end.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _interrupts_list
+ mov bx, offset _interrupts_list_end
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+_reboot_handler.loop:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we're not at the end of our interrupts list.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp si, bx
+ je _reboot_handler.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a byte from DS:SI to the al register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value into the DI register and multiple by 4 to get the
+ ;; correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, ax
+ shl di
+ shl di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value of DS:SI to ES:DI twice.
+ ;;
+ ;; Note: This will increment both the SI and DI registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ movsw
+ movsw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop back for the next entry (if there is one).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _reboot_handler.loop
+
+_reboot_handler.done:
+
+ pop cx
+ pop ax
+ pop di
+ pop si
+ pop ds
+ pop es
+
+ int HEX (19)
+
+;******************************************************************************
+; @function _real_start
+;******************************************************************************
+_real_start:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the data segment is initialized to the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;mov ax, cs
+ ;mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First we'll move the value in the stack pointer into the ax register
+ ;; and clear the dx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, sp
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Do we have any left over bytes (size % 16).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so we got the right segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jz .L8
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Yep, we have linguring bytes so increase the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the zero flag is set then we have overflowed
+ ;; (greater than 65535 bytes)
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz .L8
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Just for good measure set the data segment to the code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print an error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _error
+ db "segment overflow", HEX (0D), HEX (0A), HEX (00)
+
+.L8:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Now that we have the amount of segments that the stack pointer takes
+ ;; up we need to add the stack segment to get the first available segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ss
+ add ax, bx
+
+ mov [_free_seg], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the total memory (in KBs) and convert it to paragrahps for the
+ ;; maximum segment value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ mov cl, 6
+ shl ax, cl
+
+ mov [_max_seg], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the di register with our free segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, [_free_seg]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register ready for stosw.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+
+_clear_memory:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we've reached out max segment then we've cleared all our
+ ;; free memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp di, [_max_seg]
+ je _check_disks
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve some registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push cx
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment with the value in the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll be clearing 128 words (i.e 128 * 2) at a time.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 128
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the value in the ax register into es:di unitl cx is zero.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ rep stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore our registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add 16 to get the next segment.
+ ;;
+ ;; E.g. (0050:00ff -> 0x05ff) + 1 = 0060:0000 -> 0x0600.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add di, 16
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop back to the clear the segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _clear_memory
+
+_check_disks:
+
+ mov cx, 2
+
+.L10:
+
+ and cx, cx
+ jz .L13
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The very first thing we do is allocate at least 1 disk for use
+ ;; with floppies.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (80)
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try to allocate memory, this should never return if it fails.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _kmalloc
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Push the address to the vector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ mov ax, offset _vec_parts
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll start adding info to the segment starting at 0.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First, thing we need is a place to store the current directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 65
+ xor dx, dx
+
+ call _kmalloc
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Start in the root of the disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We need a scratch buffer for the disk so allocate one.
+ ;;
+ ;; Floppies are typically 512 bytes per sector and there's
+ ;; usually no more than 2 sectors per cluster so
+ ;; allocating 1024 (2 sectors) should be fine.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1024
+ xor dx, dx
+
+ call _kmalloc
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Decrement cx and loop back for next drive.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ dec cx
+ jmp .L10
+
+.L13:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out ah and put the drive number in al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ah, ah
+ mov al, cs:[_drive_no]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Are we booted from a floppy or hard disk?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test al, HEX (80)
+ jnz .L9
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the selected disk as the drive number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cs:[_selected_disk], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Okay, we are booted from a floppy so we need to figure out which
+ ;; address it is within our _Vec_parts "structure".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+
+ mov ax, cs:[_vec_parts]
+ mov es, ax
+
+ mov ax, es:[bx]
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try and read the drive.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+
+ mov ax, ss
+ mov es, ax
+ xor bx, bx
+
+ mov ax, HEX (0201)
+ mov cx, HEX (0001)
+ xor dh, dh
+ mov dl, cs:[_drive_no]
+ stc
+ int HEX (13)
+ pop es
+ jnc .L11
+
+ call _error
+ db "panic: failed to read boot drive", HEX (0D), HEX (0A), HEX (00)
+
+.L11:
+
+ cmp byte ptr ss:[bx + 0], HEX (EB)
+ jne .L10
+
+ cmp byte ptr ss:[bx + 2], HEX (90)
+ jne .L10
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Next we'll copy the BPB to our "structure".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ds
+
+ mov ax, ss
+ mov ds, ax
+
+ mov si, bx
+ add si, 11
+
+ mov cx, 25
+ rep movsb
+
+ pop ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the drive number.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, cs:[_drive_no]
+ stosb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Floppies should be FAT12 so pad with zeros.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ xor dx, dx
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate the offset of the first FAT.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ss:[bx + 28]
+ mov di, ss:[bx + 30]
+
+ add si, ss:[bx + 14]
+ adc di, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, di
+ pop di
+
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, cx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Repush di and reset the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+ push di
+ mov di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors both FATs require.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov al, ss:[bx + 16]
+ cbw
+ mul word ptr ss:[bx + 22]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the FAT offset to get the root directory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, di
+ pop di
+
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, cx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Repush di and reset the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+ push di
+ mov di, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Calculate how many sectors the root directory requires.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (0020)
+ mul word ptr ss:[bx + 17]
+ div word ptr ss:[bx + 11]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Adjust the root offset to get the data offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, ax
+ adc di, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in di to dx and restore di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, di
+ pop di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the offset for later use.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ mov ax, dx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Floppies shouldn't have a sector mask or shift.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Figure out how big a cluster is.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, ss:[bx + 11]
+ xor dx, dx
+
+ xor ch, ch
+ mov cl, ss:[bx + 13]
+
+ mul cx
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We don't want to set the selected drive so jump to getting the
+ ;; hard disk paritions.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp .L12
+
+.L9:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; For hard disks we always start at disk 2 (C:).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 2
+ mov cs:[_selected_disk], ax
+
+.L12:
+
+ call _get_hard_disk_partitions
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Debugging!!!
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;mov ax, cs:[_clust_size]
+ ;call _writehex
+ ;call _crlf
+ ;
+ ;mov ax, cs:[_selected_disk]
+ ;xor dx, dx
+ ;
+ ;mov cx, 2
+ ;mul cx
+ ;
+ ;mov bx, ax
+ ;
+ ;mov ax, cs:[_vec_parts]
+ ;mov es, ax
+ ;
+ ;mov ax, es:[bx]
+ ;mov es, ax
+ ;
+ ;mov ax, es:[HEX (0000)]
+ ;call _writehex
+ ;call _crlf
+ ;
+ ;mov ax, es:[HEX (0002)]
+ ;call _writehex
+ ;call _crlf
+ ;
+ ;mov ax, es:[HEX (0004)]
+ ;call _writehex
+ ;call _crlf
+ ;
+ ;xor ah, ah
+ ;mov al, es:[HEX (0006)]
+ ;call _writehex
+ ;call _crlf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reserve 1024 bytes for a fat segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1024
+ xor dx, dx
+
+ call _kmalloc
+ mov cs:[_fat_seg], ax
+
+_setup_interrupts:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Setup si and bx to point to our list and list end.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, offset _interrupts_list
+ mov bx, offset _interrupts_list_end
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the extra segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+.L4:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we're not at the end of our interrupts list.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp si, bx
+ je .L5
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a byte from DS:SI to the al register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value into the DI register and multiple by 4 to get the
+ ;; correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, ax
+ shl di
+ shl di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the address at the memory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, es:[di]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value of DS:SI to ES:DI.
+ ;;
+ ;; Note: This will increment both the SI and DI registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ movsw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the address we previously got.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [si - 2], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the segment at the memory offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, es:[di]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The segment of the new interrupt will be our code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es:[di], cs
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save the segment we previously got.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [si], dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to the SI register to account for the saved segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add si, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Loop back for the next entry (if there is one).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short .L4
+
+.L5:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-enable interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ sti
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Figure out how much memory we should allocate per program. If we
+ ;; have less than 256KB of memory then we'll divide by 4.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ int HEX (12)
+
+ mov cl, 2
+ shl ax, cl
+
+ cmp ax, HEX (0400)
+ jae .L17
+
+ mov cs:[_max_prog_alloc], ax
+
+.L17:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the data segment is actually initialized to the
+ ;; code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We also want to make sure the extra segment is initialized to the
+ ;; code segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out all other registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+ xor di, di
+ xor ax, ax
+ xor bx, bx
+ xor cx, cx
+ xor dx, dx
+
+.L14:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Execute command.com.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, offset _app_name
+ mov bx, offset _param_blk
+
+ mov ax, HEX (4B00)
+ int HEX (21)
+ jc .L7
+
+ jmp .L16
+
+.L7:
+
+ mov bx, offset _app_errmsg
+
+ call _writestr
+ call _crlf
+
+.L16:
+
+ cli
+ hlt
+
+ jmp .L16
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Start up file (tranditionally command.com).
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_app_errmsg: db "Bad or missing Command Interpreter", HEX (00)
+
+_app_name: db "\\command.com", HEX (00)
+_param_blk: db 16 dup (0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+align 4
+_interrupts_list:
+
+ db DIVIDE_VECTOR
+ dw _divide_handler, HEX (0000)
+
+ db INVALID_VECTOR
+ dw _invalid_handler, HEX (0000)
+
+ db REBOOT_VECTOR
+ dw _reboot_handler, HEX (0000)
+
+ db INT20_VECTOR
+ dw _int20_handler, HEX (0000)
+
+ db INT21_VECTOR
+ dw _int21_dispatch, HEX (0000)
+
+ db INT22_VECTOR
+ dw _int22_handler, HEX (0000)
+
+ db INT23_VECTOR
+ dw _int23_handler, HEX (0000)
+
+_interrupts_list_end:
--- /dev/null
+;******************************************************************************
+; @file kmalloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _kmalloc
+;******************************************************************************
+global _kmalloc
+_kmalloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax and dx registers should be setup with the size we want
+ ;; to allocate so convert it to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _kmalloc.ok
+
+_kmalloc.inc:
+
+ inc ax
+ jz _kmalloc.error
+
+_kmalloc.ok:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try and allocate the memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+
+ call _alloc_mem
+ jc _kmalloc.error
+
+ push ax
+ push bx
+
+ dec ax
+ mov es, ax
+
+ xor bx, bx
+ mov cx, es:[bx + 3]
+
+ pop bx
+ pop ax
+
+ push ax
+ mov es, ax
+
+_kmalloc.loop:
+
+ xor di, di
+
+ push ax
+ push cx
+
+ xor al, al
+ mov cx, 16
+ rep stosb
+
+ pop cx
+ pop ax
+
+ inc ax
+ mov es, ax
+
+ loop _kmalloc.loop
+
+_kmalloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_kmalloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we fail to get memory in here then there's something wrong
+ ;; so just error out.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ call _error
+ db "panic: failed to alloc memory in kmalloc", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;******************************************************************************
+; @file xrealloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _krealloc
+;******************************************************************************
+global _krealloc
+_krealloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have valid memory as a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _krealloc.calc
+
+ mov di, bx
+ dec di
+ mov es, di
+
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _krealloc.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _krealloc.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _krealloc.error
+
+_krealloc.calc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The ax and dx registers should be setup with the size we want
+ ;; to allocate so convert it to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _krealloc.ok
+
+_krealloc.inc:
+
+ inc ax
+ jz _krealloc.error
+
+_krealloc.ok:
+
+ mov si, ax
+
+ and bx, bx
+ jz _krealloc.alloc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First. lets try and resize the memory block.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ mov es, bx
+ mov bx, si
+ call _resize_mem
+
+ pop es
+ pop bx
+ jnc _krealloc.done
+
+_krealloc.alloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Try and allocate the memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+
+ mov bx, si
+ call _alloc_mem
+
+ pop bx
+ jc _krealloc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Only copy existing data if there was an original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, bx
+
+ and di, di
+ jz _krealloc.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers that copy will clobber.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ds
+
+ mov di, bx
+ mov ds, di
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ mov cx, word ptr es:[di + 3]
+ mov es, ax
+
+ cmp cx, bx
+ jb _krealloc.copy
+
+ mov cx, bx
+
+_krealloc.copy:
+
+ xor si, si
+ xor di, di
+
+ push cx
+
+ mov cx, 16
+ rep movsb
+
+ pop cx
+
+ mov si, es
+ inc si
+ mov es, si
+
+ mov di, ds
+ inc di
+ mov ds, di
+
+ loop _krealloc.copy
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers that copy clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop si
+
+_krealloc.free:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we reached this point then free the original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ call _free_mem
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_krealloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_krealloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we fail to get memory in here then there's something wrong
+ ;; so just error out.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs
+ mov ds, ax
+
+ call _error
+ db "panic: failed to alloc memory in krealloc", HEX (0D), HEX (0A), HEX (00)
--- /dev/null
+;******************************************************************************
+; @file mangle.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _mangle_dos_name
+;******************************************************************************
+global _mangle_dos_name
+_mangle_dos_name:
+
+ push ax
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov cx, cs
+ mov es, cx
+
+ mov di, offset _mangled_name
+ mov cx, 11
+
+_mangle_dos_name.loop:
+
+ lodsb
+
+ cmp al, ' '
+ jna _mangle_dos_name.end
+
+ cmp al, '\\'
+ je _mangle_dos_name.end
+
+ cmp al, '.'
+ je _mangle_dos_name.is_period
+
+ cmp al, HEX (61)
+ jb _mangle_dos_name.no_conv
+
+ cmp al, HEX (7A)
+ ja _mangle_dos_name.no_conv
+
+ mov dl, HEX (20)
+ not dl
+
+ and al, dl
+
+_mangle_dos_name.no_conv:
+
+ mov bx, offset _invalid_chars
+ mov ah, cl
+
+ cmp ax, HEX (0BE5)
+ jne _mangle_dos_name.check
+
+ mov al, HEX (05)
+
+_mangle_dos_name.check:
+
+ cmp byte ptr cs:[bx], 0
+ je _mangle_dos_name.store
+
+ cmp byte ptr cs:[bx], al
+ je _mangle_dos_name.error
+
+ inc bx
+ jmp short _mangle_dos_name.check
+
+_mangle_dos_name.store:
+
+ stosb
+ loop _mangle_dos_name.loop
+
+_mangle_dos_name.find_end:
+
+ lodsb
+
+ cmp al, ' '
+ jna _mangle_dos_name.end
+
+ cmp al, '\\'
+ jne _mangle_dos_name.find_end
+
+_mangle_dos_name.end:
+
+ mov al, ' '
+ rep stosb
+
+_mangle_dos_name.done:
+
+ mov bx, offset _mangled_name
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop ax
+
+ clc
+ ret
+
+_mangle_dos_name.is_period:
+
+ cmp cx, 11
+ jb _mangle_dir.period_check
+
+ mov al, '.'
+ stosb
+
+ dec cx
+ jmp _mangle_dos_name.loop
+
+_mangle_dir.period_check:
+
+ cmp di, offset _mangled_name
+ je _mangle_dir.add_period
+
+ cmp byte ptr es:[di - 1], '.'
+ jne _mangle_dir.need_padding
+
+_mangle_dir.add_period:
+
+ mov al, '.'
+ stosb
+
+ dec cx
+ jmp _mangle_dos_name.loop
+
+_mangle_dir.need_padding:
+
+ mov al, ' '
+
+_mangle_dos_name.period_loop:
+
+ cmp cx, 3
+ jbe _mangle_dos_name.loop
+
+ stosb
+ loop _mangle_dos_name.period_loop
+
+_mangle_dos_name.error:
+
+ mov di, offset _mangled_name
+ xor al, al
+
+ mov cx, 11
+ rep stosb
+
+ mov bx, offset _mangled_name
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop ax
+
+ stc
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_invalid_chars: db "\"*+,/:;<=>?[]|", HEX (00)
+_mangled_name: db 12 dup (0)
--- /dev/null
+;******************************************************************************
+; @file mem.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _alloc_mem
+;******************************************************************************
+global _alloc_mem
+_alloc_mem:
+
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov ax, cs:[_free_seg]
+ mov es, ax
+
+ push es
+
+ mov ax, bx
+ xor di, di
+
+_alloc_mem.search:
+
+ mov cx, es
+
+ cmp cx, cs:[_free_seg]
+ jb _alloc_mem.error
+
+ cmp cx, cs:[_max_seg]
+ jae _alloc_mem.error
+
+ cmp byte ptr es:[di], 'M'
+ je _alloc_mem.check
+
+ jmp short _alloc_mem.next
+
+_alloc_mem.check:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _alloc_mem.check2
+
+ jmp short _alloc_mem.next
+
+_alloc_mem.check2:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _alloc_mem.retry
+
+_alloc_mem.next:
+
+ mov si, es
+ inc si
+ mov es, si
+
+ dec ax
+ jnz _alloc_mem.search
+
+ cmp byte ptr es:[di], 'M'
+ je _alloc_mem.check3
+
+ cmp si, cs:[_free_seg]
+ jb _alloc_mem.error
+
+ cmp si, cs:[_max_seg]
+ jae _alloc_mem.error
+
+ jmp short _alloc_mem.success
+
+_alloc_mem.check3:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _alloc_mem.check4
+
+ jmp short _alloc_mem.success
+
+_alloc_mem.check4:
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _alloc_mem.success
+
+_alloc_mem.retry:
+
+ mov cx, es:[di + 3]
+ inc cx
+
+ mov si, es
+ add si, cx
+ mov es, si
+
+ pop si
+ push es
+
+ mov ax, bx
+ jmp _alloc_mem.search
+
+_alloc_mem.success:
+
+ xor di, di
+ pop es
+
+ mov byte ptr es:[di], 'M'
+ mov byte ptr es:[di + 1], 'C'
+ mov byte ptr es:[di + 2], 'B'
+
+ mov word ptr es:[di + 3], bx
+ mov ax, cs:[_curr_psp]
+ mov word ptr es:[di + 5], ax
+
+ mov ax, es
+ inc ax
+
+ clc
+ jmp short _alloc_mem.done
+
+_alloc_mem.error:
+
+ mov bx, es
+ pop ax
+ sub bx, ax
+
+ mov ax, 8
+ stc
+
+_alloc_mem.done:
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+;******************************************************************************
+; @function _free_mem
+;******************************************************************************
+global _free_mem
+_free_mem:
+
+ push bx
+ push cx
+ push di
+ push es
+
+ mov di, es
+
+ and di, di
+ jz _free_mem.error
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _free_mem.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _free_mem.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _free_mem.error
+
+ xor al, al
+ mov cx, 16
+ rep movsb
+
+ xor ax, ax
+ clc
+
+ jmp short _free_mem.done
+
+_free_mem.error:
+
+ mov ax, 9
+ stc
+
+_free_mem.done:
+
+ pop es
+ pop di
+ pop cx
+ pop bx
+ ret
+
+;******************************************************************************
+; @function _resize_mem
+;******************************************************************************
+global _resize_mem
+_resize_mem:
+
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov di, es
+
+ and di, di
+ jz _resize_mem.error
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _resize_mem.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _resize_mem.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _resize_mem.error
+
+ mov cx, word ptr es:[di + 3]
+
+ cmp cx, bx
+ jae _resize_mem.success
+
+ mov di, es
+ add di, cx
+ mov es, di
+
+ mov ax, bx
+ sub ax, cx
+
+ xor di, di
+
+_resize_mem.search:
+
+ mov cx, es
+
+ cmp cx, cs:[_max_seg]
+ jae _resize_mem.ins
+
+ cmp byte ptr es:[di], 'M'
+ je _resize_mem.check
+
+ jmp short _resize_mem.next
+
+_resize_mem.check:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _resize_mem.check2
+
+ jmp short _resize_mem.next
+
+_resize_mem.check2:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _resize_mem.ins
+
+_resize_mem.next:
+
+ mov si, es
+ inc si
+ mov es, si
+
+ dec ax
+ jnz _resize_mem.search
+
+ cmp si, cs:[_max_seg]
+ jae _resize_mem.max
+
+ cmp byte ptr es:[di], 'M'
+ je _resize_mem.check3
+
+ jmp short _resize_mem.success
+
+_resize_mem.check3:
+
+ cmp byte ptr es:[di + 1], 'C'
+ je _resize_mem.check4
+
+ jmp short _resize_mem.success
+
+_resize_mem.check4:
+
+ cmp byte ptr es:[di + 2], 'B'
+ je _resize_mem.ins
+
+_resize_mem.success:
+
+ pop es
+
+ mov di, es
+ dec di
+ mov es, di
+
+ xor di, di
+ mov word ptr es:[di + 3], bx
+
+ mov di, es
+ inc di
+ mov es, di
+
+ mov ax, es
+ clc
+
+ jmp short _resize_mem.done
+
+_resize_mem.max:
+
+ mov bx, cs:[_max_seg]
+ jmp short _resize_mem.got_seg
+
+_resize_mem.ins:
+
+ mov bx, es
+
+_resize_mem.got_seg:
+
+ pop es
+
+ mov ax, es
+ sub bx, ax
+
+ push es
+
+ mov di, es
+ dec di
+ mov es, di
+
+ xor di, di
+ mov word ptr es:[di + 3], bx
+
+ mov ax, 8
+ stc
+
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+_resize_mem.error:
+
+ mov ax, 9
+ stc
+
+ pop es
+
+_resize_mem.done:
+
+ pop di
+ pop si
+ pop dx
+ pop cx
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _free_seg
+_free_seg: dw HEX (0000)
+
+global _max_seg
+_max_seg: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file prog.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _alloc_prog_mem
+;******************************************************************************
+_alloc_prog_mem:
+
+ push bx
+ push cx
+
+ cmp ax, dx
+ jb _alloc_prog_mem.error
+
+ mov cl, 4
+
+ mov bx, ax
+ shl bx, cl
+
+ sub bx, 4
+
+ mov cs:[_child_sssp], bx
+ mov bx, ax
+
+ call _alloc_mem
+ jnc _alloc_prog_mem.done
+
+_alloc_prog_mem.error:
+
+ pop cx
+ pop bx
+
+ mov ax, 8
+ stc
+
+ ret
+
+_alloc_prog_mem.done:
+
+ pop cx
+ pop bx
+
+ clc
+ ret
+
+
+;******************************************************************************
+; @function _load_program
+;******************************************************************************
+global _load_program
+_load_program:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ call _open_file
+ jnc _load_program.got_file
+
+ add sp, 2
+ stc
+
+ pop bp
+ ret
+
+_load_program.got_file:
+
+ mov word ptr [bp - 2], ax
+
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+ push ds
+
+ mov ax, HEX (4202)
+ mov bx, word ptr [bp - 2]
+ xor cx, cx
+ xor dx, dx
+
+ call _seek_file
+ jc _load_program.error
+
+ add ax, HEX (0200) ; Minimum of 8KB for the stack.
+ adc dx, 0
+
+ mov cx, 16
+ div cx
+
+ and dx, dx
+ jz _load_program.got_size
+
+ inc ax
+ jnz _load_program.got_size
+
+ mov ax, 8
+ jmp _load_program.error
+
+_load_program.got_size:
+
+ push ax
+
+ mov ax, HEX (4200)
+ mov bx, word ptr [bp - 2]
+ xor cx, cx
+ xor dx, dx
+
+ call _seek_file
+ pop dx
+ jc _load_program.error
+
+ mov ax, cs:[_max_prog_alloc]
+
+ call _alloc_prog_mem
+ jnc _load_program.mem_ok
+
+_load_program.no_mem:
+
+ push ax
+
+ mov ax, cs
+ mov ds, ax
+
+ mov bx, offset _load_program.errmsg
+ call _writestr
+
+ pop ax
+ jmp _load_program.error
+
+_load_program.mem_ok:
+
+ mov cs:[_child_sssp + 2], ax
+
+ mov cs:[_child_csip + 2], ax
+ mov word ptr cs:[_child_csip], HEX (0100)
+
+ mov es, ax
+ mov word ptr es:[HEX (00)], HEX (20CD)
+
+ mov es:[HEX (02)], ax
+ mov word ptr es:[HEX (80)], 0
+
+ mov ax, cs:[_curr_psp]
+ mov es:[HEX (16)], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Ensure there's a 0 at the bottom of the stack so a local return call
+ ;; will execute the INT 20h instruction at [cs:0] and the initial value
+ ;; of ax.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, cs:[_child_sssp]
+
+ xor ax, ax
+ stosw
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Point DTA at PSP:80h.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov word ptr cs:[_disk_transfer_addr], HEX (80)
+ mov word ptr cs:[_disk_transfer_addr + 2], es
+
+ mov cs:[_curr_psp], es
+ mov bx, word ptr [bp - 2]
+
+ mov ax, es
+ mov ds, ax
+
+ push es
+ push ds
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have any open files.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp word ptr cs:[_vec_files + 2], 0
+ je _load_program.read_error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have a valid file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bx, 3
+ jb _load_program.read_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 _load_program.read_error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Re-initialize the extra segment but this time with the address
+ ;; of the vector entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor si, si
+
+ mov ax, es:[bx]
+ mov es, ax
+
+ mov cx, HEX (0200)
+ mov dx, HEX (0100)
+
+ mov bx, word ptr [bp - 2]
+
+_load_program.read:
+
+ call _read_file
+ jc _load_program.read_error
+
+ and ax, ax
+ jz _load_program.all_read
+
+ shr ax
+ shr ax
+ shr ax
+ shr ax
+
+ mov di, ds
+ add di, ax
+ mov ds, di
+
+ jmp short _load_program.read
+
+_load_program.all_read:
+
+ pop ds
+ pop es
+
+ mov bx, word ptr [bp - 2]
+ call _close_file
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Save some interrupts.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ mov es, ax
+
+ mov ax, es:[HEX (22) * 4]
+ mov [HEX (0A)], ax
+
+ mov ax, es:[(HEX (22) * 4) + 2]
+ mov [HEX (0C)], ax
+
+ mov ax, es:[HEX (23) * 4]
+ mov [HEX (0E)], ax
+
+ mov ax, es:[(HEX (23) * 4) + 2]
+ mov [HEX (10)], ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize "int 23h" with our default handler in case the
+ ;; user/program doesn't set the interrupt itself.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, offset _int23_handler
+ mov es:[HEX (23) * 4], bx
+
+ mov es:[(HEX (23) * 4) + 2], cs
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the current psp address.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_curr_psp]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ 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
+
+_load_program.read_error:
+
+ pop ds
+ pop es
+
+ call _free_mem
+
+_load_program.error:
+
+ mov bx, word ptr [bp - 2]
+ call _close_file
+
+ pop ds
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ stc
+
+ pop bp
+ ret
+
+_load_program.errmsg: db "Not enough memory to run program", HEX (0D), HEX (0A), HEX (00)
+
+;******************************************************************************
+; @file _start_program
+;******************************************************************************
+global _start_program
+_start_program:
+
+ cli
+
+ mov ds, ax
+
+ mov [HEX (42)], sp
+ mov [HEX (44)], ss
+
+ mov es, ax
+
+ mov ss, cs:[_child_sssp + 2]
+ mov sp, cs:[_child_sssp]
+
+ mov dx, cs:[_child_csip + 2]
+ mov si, cs:[_child_csip]
+
+ mov bp, HEX (0900)
+ pop bx
+
+ mov ax, HEX (0202)
+ push ax
+
+ xor ax, ax
+ xchg ax, bx
+
+ push dx
+ push si
+
+ iret
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _curr_psp
+_curr_psp: dw HEX (0000)
+
+global _last_ret_val
+_last_ret_val: dw HEX (0000)
+
+global _child_sssp
+_child_sssp:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _child_csip
+_child_csip:
+
+ dw HEX (0000)
+ dw HEX (0000)
+
+global _max_prog_alloc
+_max_prog_alloc: dw HEX (1000)
--- /dev/null
+;******************************************************************************
+; @file query.asm
+;******************************************************************************
+.386
+
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _query_cpu
+;******************************************************************************
+global _query_cpu
+_query_cpu:
+
+ push bx
+ push cx
+ pushf
+
+ xor bx, bx
+
+ push bx
+ popf
+
+ pushf
+ pop ax
+
+ and ax, HEX (F000)
+
+ cmp ax, HEX (F000)
+ jnz _query_cpu.is_286
+
+ mov ax, sp
+ xor cx, cx
+
+ push cx
+ inc cx
+
+ db HEX (8F), HEX (C1)
+ mov sp, ax
+
+ or cx, cx
+ jz _query_cpu.is_808x
+
+ mov bx, cx
+ jmp short _query_cpu.done
+
+_query_cpu.is_808x:
+
+ mov ax, 1
+ mov cl, 64
+ shr ax, cl
+
+ or ax, ax
+ jz _query_cpu.is_86
+
+ mov bx, 1
+
+_query_cpu.is_86:
+
+ jmp short _query_cpu.done
+
+_query_cpu.is_286:
+
+ mov bx, 2
+ mov ax, HEX (F000)
+
+ push ax
+ popf
+
+ pushf
+ pop ax
+
+ test ax, HEX (F000)
+ jz _query_cpu.done
+
+ mov bx, 3
+
+_query_cpu.done:
+
+ mov ax, bx
+ popf
+ pop cx
+ pop bx
+ ret
--- /dev/null
+;******************************************************************************
+; @file search.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _search_dos_dir
+;******************************************************************************
+global _search_dos_dir
+_search_dos_dir:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 34
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ 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 _search_dos_dir.not_root
+
+ mov ax, cs:[_root_start]
+ mov dx, cs:[_root_start + 2]
+
+_search_dos_dir.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 _search_dos_dir.read
+
+_search_dos_dir.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 _search_dos_dir.not_found
+
+ 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]
+
+_search_dos_dir.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
+
+_search_dos_dir.search:
+
+ push cx
+ mov cx, 11
+
+ cmp byte ptr es:[di], 0
+ je _search_dos_dir.advance
+
+ cmp byte ptr es:[di], HEX (E5)
+ je _search_dos_dir.advance
+
+ push si
+ push di
+ push ds
+
+ mov si, cs
+ mov ds, si
+
+ mov si, word ptr [bp - 32]
+ repe cmpsb
+
+ pop ds
+ pop di
+ pop si
+ je _search_dos_dir.found
+
+_search_dos_dir.advance:
+
+ pop cx
+
+ add di, 32
+ loop _search_dos_dir.search
+
+ cmp word ptr [bp - 30], 1
+ jne _search_dos_dir.check
+
+ mov ax, word ptr [bp - 22]
+
+ and ax, ax
+ jz _search_dos_dir.not_found
+
+ 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 _search_dos_dir.read
+
+_search_dos_dir.check:
+
+ mov ax, word ptr [bp - 34]
+
+ and ax, ax
+ jz _search_dos_dir.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 _search_dos_dir.read
+
+_search_dos_dir.next_clust:
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jmp _search_dos_dir.not_root
+
+_search_dos_dir.not_found:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 34
+ pop bp
+
+ mov ax, 3
+ stc
+
+ ret
+
+_search_dos_dir.found:
+
+ pop cx
+ mov si, di
+
+ mov ax, cs
+ mov ds, ax
+ mov bx, offset _file_info
+
+ mov ax, es:[di + 26]
+ mov [bx + 0], ax
+
+ mov ax, es:[di + 20]
+ mov [bx + 2], ax
+
+ mov ax, es:[di + 28]
+ mov [bx + 4], ax
+
+ mov ax, es:[di + 30]
+ mov [bx + 6], ax
+
+ mov al, es:[di + 11]
+ mov [bx + 8], al
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 34
+ pop bp
+
+ mov ax, offset _file_info
+ clc
+
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_file_info: db 9 dup (0)
--- /dev/null
+;******************************************************************************
+; @file vector.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _vec_adjust
+;******************************************************************************
+_vec_adjust:
+
+ push bp
+ mov bp, sp
+
+ push bx
+ push cx
+ push dx
+
+ mov bx, word ptr [bp + 4]
+
+_vec_adjust.check:
+
+ mov cx, [bx + 2]
+
+ cmp cx, word ptr [bp + 6]
+ ja _vec_adjust.done
+
+_vec_adjust.check2:
+
+ and cx, cx
+ jnz _vec_adjust.shift
+
+ mov cx, 16
+ jmp short _vec_adjust.set
+
+_vec_adjust.shift:
+
+ shl cx
+
+_vec_adjust.set:
+
+ mov [bx + 2], cx
+
+_vec_adjust.alloc:
+
+ mov ax, 2
+ xor dx, dx
+
+ mul cx
+ push bx
+
+ mov bx, [bx + 0]
+ call _krealloc
+
+ pop bx
+ mov [bx + 0], ax
+
+_vec_adjust.done:
+
+ xor ax, ax
+
+ pop dx
+ pop cx
+ pop bx
+
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _vec_push
+;******************************************************************************
+global _vec_push
+_vec_push:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push bx
+ push cx
+ push dx
+ push di
+ push es
+
+ mov bx, word ptr [bp + 4]
+
+_vec_push.alt:
+
+ mov ax, [bx + 4]
+ push ax
+
+ push word ptr [bp + 4]
+
+ call _vec_adjust
+ add sp, 4
+
+ mov word ptr [bp - 2], ax
+
+ and ax, ax
+ jnz _vec_push.done
+
+_vec_push.set:
+
+ mov ax, [bx + 0]
+ mov es, ax
+
+ mov ax, [bx + 4]
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov di, ax
+
+ mov ax, [bp + 6]
+ mov es:[di], ax
+
+ mov cx, [bx + 4]
+ add cx, 1
+
+ mov [bx + 4], cx
+
+_vec_push.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop es
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ add sp, 2
+ pop bp
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file walk.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _walk_path
+;******************************************************************************
+global _walk_path
+_walk_path:
+
+ push bx
+
+ mov ax, cs:[_curr_cluster]
+ mov dx, cs:[_curr_cluster + 2]
+
+ cmp byte ptr [di], '\\'
+ jne _walk_path.not_root
+
+ mov ax, cs:[_root_cluster]
+ mov dx, cs:[_root_cluster + 2]
+
+ xor cx, cx
+ inc di
+
+_walk_path.not_root:
+
+ push ax
+ push dx
+
+ mov si, di
+
+_walk_path.skip:
+
+ lodsb
+
+ cmp al, '\\'
+ je _walk_path.skip
+
+ dec si
+ mov di, si
+
+_walk_path.find_end:
+
+ lodsb
+
+ cmp al, ' '
+ jbe _walk_path.end_path
+
+ cmp al, '\\'
+ jne _walk_path.find_end
+
+_walk_path.end_path:
+
+ xchg si, di
+ pop dx
+ pop ax
+
+ mov bx, di
+ dec bx
+
+ cmp bx, si
+ je _walk_path.done
+
+ cmp byte ptr [di - 1], 0
+ je _walk_path.done
+
+ call _mangle_dos_name
+ jc _walk_path.not_found
+
+ call _search_dos_dir
+ jc _walk_path.not_found
+
+ push bx
+ push es
+
+ mov bx, cs
+ mov es, bx
+ mov bx, ax
+
+ mov ax, es:[bx + 0]
+ mov dx, es:[bx + 2]
+
+ mov cl, es:[bx + 8]
+ pop es
+ pop bx
+
+ test cl, HEX (10)
+ jz _walk_path.not_found
+
+ cmp byte ptr [di - 1], '\\'
+ jne _walk_path.done
+
+ jmp _walk_path.not_root
+
+_walk_path.not_found:
+
+ pop bx
+ stc
+
+ ret
+
+_walk_path.done:
+
+ pop bx
+ clc
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file writechr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function writechr
+;******************************************************************************
+global _writechr
+_writechr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push bp ; Some BIOSes destroy BP when the screen scrolls
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file writedec.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writedec
+;******************************************************************************
+global _writedec
+_writedec:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+ push bp
+
+ mov bx, 10
+ xor cx, cx
+
+_writedec.cloop:
+
+ div bx
+ inc cx
+
+ push dx
+ xor dx, dx
+
+ and ax, ax
+ jnz _writedec.cloop
+
+_writedec.dloop:
+
+ pop ax
+
+ mov ah, HEX (0E)
+ add al, '0'
+ int HEX (10)
+
+ loop _writedec.dloop
+
+_writedec.done:
+
+ pop bp
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
--- /dev/null
+;******************************************************************************
+; @file writehex.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writehex
+;******************************************************************************
+global _writehex
+_writehex:
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push di
+
+ mov di, cs:[_writehex_num_digits]
+ mov cl, 4
+
+_writehex.loop:
+
+ rol ax, cl
+ push ax
+ and al, 0b00001111
+ cmp al, 10
+ jae _writehex.high
+
+_writehex.low:
+
+ add al, HEX (30)
+ jmp short _writehex.ischar
+
+_writehex.high:
+
+ add al, HEX (37)
+
+_writehex.ischar:
+
+ mov ah, HEX (0E)
+
+ push bp
+ push bx
+
+ mov bx, HEX (0007)
+ int HEX (10)
+
+ pop bx
+ pop bp
+ pop ax
+
+ dec di
+ jnz _writehex.loop
+
+_writehex.done:
+
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global _writehex_num_digits
+_writehex_num_digits: dw HEX (0004)
--- /dev/null
+;******************************************************************************
+; @file writestr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _writestr
+;******************************************************************************
+global _writestr
+_writestr:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push bx
+ push si
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize si with bx
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump over our printing code to get the first character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _writestr.next
+
+_writestr.print:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Print the character to the screen.
+ ;;
+ ;; AH = 0Eh - Teletype output
+ ;; AL - Character to print
+ ;; BX - Page number and color
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (0E)
+ mov bx, HEX (0007)
+ int HEX (10)
+
+_writestr.next:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Load a character from si to al.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ lodsb
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached a NULL byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or al, al
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Nope, so print the character.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jnz _writestr.print
+
+_writestr.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ pop si
+ pop bx
+ pop ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := crt
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for d in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$d" ]; then mkdir -p "$(OBJDIR)/$$d"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" all; \
+ done
+
+clean:
+ for d in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$d" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" clean; \
+ fi; \
+ done
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := crt
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%d in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%d" ( mkdir "$(OBJDIR)/%%d" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" all \
+ )
+
+clean:
+ for %%d in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%d" ( \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" clean \
+ ) \
+ )
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+ASMSRC := $(shell find "$(SRCDIR)" -type f -name '*.asm' ! -name 'crt0*')
+ASMOBJ := $(patsubst $(SRCDIR)/%, %, $(ASMSRC:.asm=.o))
+
+all: crt0.o libc.a
+
+clean:
+ for f in `find . -name '*.o'`; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ for f in `find . -name '*.lst'`; do if [ -f $$f ]; then rm -rf $$f; fi; done
+ if [ -f libc.a ]; then rm -rf libc.a; fi
+
+libc.a: $(ASMOBJ)
+ ../../utils/binutils/sar r $@ $^
+ ../../utils/binutils/sar s $@
+
+%.o: %.asm
+ if [ ! -d $(patsubst %/, %, $(dir $@)) ]; then mkdir -p $(patsubst %/, %, $(dir $@)); fi
+ ../../utils/binutils/sasm -I$(SRCDIR)/include -l $*.lst -o $@ $<
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+VPATH := $(SRCDIR)
+
+ASMSRC := $(subst \,/,$(shell dir /s /b "$(SRCDIR)\\*.asm" | find "crt0.asm" /v))
+ASMOBJ := $(patsubst $(SRCDIR)/%, %, $(ASMSRC:.asm=.o))
+
+all: crt0.o libc.a
+
+clean:
+ for /r %%f in (*.o) do ( if exist %%f ( del /q %%f ) )
+ for /r %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
+ if exist libc.a ( del /q libc.a )
+
+libc.a: $(ASMOBJ)
+ ../../utils/binutils/sar r $@ $^
+ ../../utils/binutils/sar s $@
+
+%.o: %.asm
+ if not exist $(patsubst %/, %, $(dir $@)) ( mkdir $(patsubst %/, %, $(dir $@)) )
+ ../../utils/binutils/sasm -I$(SRCDIR)/include -l $*.lst -o $@ $<
--- /dev/null
+;******************************************************************************
+; @file crt0.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _start
+;******************************************************************************
+global _start
+_start:
+
+ mov ax, sp
+ xor dx, dx
+
+ mov cx, 16
+ div cx
+
+ and dx, dx
+ jz .L5
+
+ inc ax
+ jz .L6
+
+.L5:
+
+ mov bx, ss
+ add ax, bx
+
+ mov bx, ds
+ sub ax, bx
+ mov bx, ax
+
+ mov ah, HEX (4A)
+ int HEX (21)
+
+ mov di, offset _program_name
+ mov cx, HEX (41)
+
+ xor al, al
+ rep stosb
+
+ mov di, offset _cmd_line
+ mov cx, HEX (80)
+
+ xor al, al
+ rep stosb
+
+ mov di, offset _argv
+ mov cx, 132
+
+ xor al, al
+ rep stosb
+
+ mov word ptr [_argc], 0
+
+ mov di, offset _cmd_line
+ mov si, HEX (80)
+
+ xor ah, ah
+ lodsb
+
+ and ax, ax
+ jz .L4
+
+ mov cx, ax
+ rep movsb
+
+ xor al, al
+ stosb
+
+ mov di, offset _argv
+ add di, 2
+
+ mov si, offset _cmd_line
+ call _get_args
+
+.L4:
+
+ push es
+ push ds
+
+ xor bx, bx
+
+ mov ah, HEX (30)
+ int HEX (21)
+ xchg al, ah
+
+ cmp ax, HEX (0300)
+ jb .L2
+
+ mov ax, cs:[HEX (2C)]
+
+ and ax, ax
+ jz .L2
+
+ mov ds, ax
+ xor si, si
+
+ mov di, offset _program_name
+ xor ax, ax
+
+.L3:
+
+ mov al, [si]
+ inc si
+
+ and al, al
+ jnz .L3
+
+ mov al, [si]
+ inc si
+
+ and al, al
+ jnz .L3
+
+ mov al, [si]
+
+ and al, al
+ jz .L2
+
+ add si, 2
+ push si
+
+ call _strlen
+ add sp, 2
+
+ mov cx, ax
+ rep movsb
+
+ mov bx, offset _program_name
+
+.L2:
+
+ pop ds
+ pop es
+
+ mov di, offset _argv
+
+ mov ax, bx
+ stosw
+
+ inc word ptr [_argc]
+
+.L1:
+
+ mov bx, offset _argv
+ push bx
+
+ push word ptr [_argc]
+
+ call _main
+ add sp, 4
+
+.L6:
+
+ mov ah, HEX (4C)
+ int HEX (21)
+
+;******************************************************************************
+; @function _get_args
+;******************************************************************************
+_get_args:
+
+ push ax
+ push dx
+ push si
+ push di
+
+ mov dx, HEX (20)
+
+_get_args.skip_spaces:
+
+ lodsb
+
+ or al, al
+ jz _get_args.done
+
+ cmp al, ' '
+ je _get_args.skip_spaces
+
+ dec si
+
+_get_args.loop:
+
+ mov ax, si
+ stosw
+
+ inc word ptr [_argc]
+
+ push dx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _get_args.done
+
+ mov si, ax
+
+ mov byte ptr [si], 0
+ inc si
+
+ jmp short _get_args.skip_spaces
+
+_get_args.done:
+
+ xor ax, ax
+ stosw
+
+ pop di
+ pop si
+ pop dx
+ pop ax
+ ret
+
+;******************************************************************************
+; @function _strchr
+;******************************************************************************
+_strchr:
+
+ push bp
+ mov bp, sp
+
+ push si
+ push bx
+
+ mov bx, [bp + 6]
+ mov si, [bp + 4]
+
+_strchr.loop:
+
+ lodsb
+
+ or al, al
+ jz _strchr.done
+
+ cmp al, bl
+ je _strchr.found
+
+ jmp short _strchr.loop
+
+_strchr.found:
+
+ mov ax, si
+ dec ax
+
+ pop bx
+ pop si
+ pop bp
+ ret
+
+_strchr.done:
+
+ xor ax, ax
+
+ pop bx
+ pop si
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _strlen
+;******************************************************************************
+_strlen:
+
+ push bp
+ mov bp, sp
+
+ push cx
+ push si
+ push di
+
+ mov si, [bp + 4]
+ xor cx, cx
+
+_strlen.loop:
+
+ lodsb
+
+ or al, al
+ jz _strlen.done
+
+ inc cx
+ jmp short _strlen.loop
+
+_strlen.done:
+
+ mov ax, cx
+
+ pop di
+ pop si
+ pop cx
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_program_name: db HEX (41) dup (0)
+_cmd_line: db HEX (80) dup (0)
+
+_argv: db 132 dup (0)
+_argc: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file ctype.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _isalnum
+;******************************************************************************
+global _isalnum
+_isalnum:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0001)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isalpha
+;******************************************************************************
+global _isalpha
+_isalpha:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0002)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _iscntrl
+;******************************************************************************
+global _iscntrl
+_iscntrl:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0004)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isdigit
+;******************************************************************************
+global _isdigit
+_isdigit:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0008)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isgraph
+;******************************************************************************
+global _isgraph
+_isgraph:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0010)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _islower
+;******************************************************************************
+global _islower
+_islower:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0020)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isprint
+;******************************************************************************
+global _isprint
+_isprint:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0040)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _ispunct
+;******************************************************************************
+global _ispunct
+_ispunct:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0080)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isspace
+;******************************************************************************
+global _isspace
+_isspace:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0100)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isupper
+;******************************************************************************
+global _isupper
+_isupper:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0200)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _isxdigit
+;******************************************************************************
+global _isxdigit
+_isxdigit:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __isbufR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, HEX (0400)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _tolower
+;******************************************************************************
+global _tolower
+_tolower:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __tolowR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;******************************************************************************
+; @function _toupper
+;******************************************************************************
+global _toupper
+_toupper:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the base pointer with the stack pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the registers that will get clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the ax register with the value of the stack and zero
+ ;; out dx.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 4]
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Multiple by two to get the correct offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 2
+ mul cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the offset of our "array".
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, offset __toupR
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add two to skip the first entry.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add ax, 2
+ adc dx, 0
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Divide by 16 to get a segment:offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add the code segment to the value in ax to get the correct segment.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, cs
+ add ax, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; AX:DX should conatin the segment:offset of our "array" so
+ ;; set the extra segment to the calacaulted segment and dx to the
+ ;; calculated offset.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ mov bx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es:[bx]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the registers that got clobbered
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+__isbufR:
+
+ dw HEX (0000)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0104)
+ dw HEX (0104)
+ dw HEX (0104)
+ dw HEX (0104)
+ dw HEX (0104)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0004)
+ dw HEX (0140)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (0459)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (0653)
+ dw HEX (0653)
+ dw HEX (0653)
+ dw HEX (0653)
+ dw HEX (0653)
+ dw HEX (0653)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (0253)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (0473)
+ dw HEX (0473)
+ dw HEX (0473)
+ dw HEX (0473)
+ dw HEX (0473)
+ dw HEX (0473)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (0073)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (00D0)
+ dw HEX (0004)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+ dw HEX (0000)
+
+__tolowR:
+
+ dw HEX (FFFF)
+ dw HEX (0000)
+ dw HEX (0001)
+ dw HEX (0002)
+ dw HEX (0003)
+ dw HEX (0004)
+ dw HEX (0005)
+ dw HEX (0006)
+ dw HEX (0007)
+ dw HEX (0008)
+ dw HEX (0009)
+ dw HEX (000A)
+ dw HEX (000B)
+ dw HEX (000C)
+ dw HEX (000D)
+ dw HEX (000E)
+ dw HEX (000F)
+ dw HEX (0010)
+ dw HEX (0011)
+ dw HEX (0012)
+ dw HEX (0013)
+ dw HEX (0014)
+ dw HEX (0015)
+ dw HEX (0016)
+ dw HEX (0017)
+ dw HEX (0018)
+ dw HEX (0019)
+ dw HEX (001A)
+ dw HEX (001B)
+ dw HEX (001C)
+ dw HEX (001D)
+ dw HEX (001E)
+ dw HEX (001F)
+ dw HEX (0020)
+ dw HEX (0021)
+ dw HEX (0022)
+ dw HEX (0023)
+ dw HEX (0024)
+ dw HEX (0025)
+ dw HEX (0026)
+ dw HEX (0027)
+ dw HEX (0028)
+ dw HEX (0029)
+ dw HEX (002A)
+ dw HEX (002B)
+ dw HEX (002C)
+ dw HEX (002D)
+ dw HEX (002E)
+ dw HEX (002F)
+ dw HEX (0030)
+ dw HEX (0031)
+ dw HEX (0032)
+ dw HEX (0033)
+ dw HEX (0034)
+ dw HEX (0035)
+ dw HEX (0036)
+ dw HEX (0037)
+ dw HEX (0038)
+ dw HEX (0039)
+ dw HEX (003A)
+ dw HEX (003B)
+ dw HEX (003C)
+ dw HEX (003D)
+ dw HEX (003E)
+ dw HEX (003F)
+ dw HEX (0040)
+ dw HEX (0061)
+ dw HEX (0062)
+ dw HEX (0063)
+ dw HEX (0064)
+ dw HEX (0065)
+ dw HEX (0066)
+ dw HEX (0067)
+ dw HEX (0068)
+ dw HEX (0069)
+ dw HEX (006A)
+ dw HEX (006B)
+ dw HEX (006C)
+ dw HEX (006D)
+ dw HEX (006E)
+ dw HEX (006F)
+ dw HEX (0070)
+ dw HEX (0071)
+ dw HEX (0072)
+ dw HEX (0073)
+ dw HEX (0074)
+ dw HEX (0075)
+ dw HEX (0076)
+ dw HEX (0077)
+ dw HEX (0078)
+ dw HEX (0079)
+ dw HEX (007A)
+ dw HEX (005B)
+ dw HEX (005C)
+ dw HEX (005D)
+ dw HEX (005E)
+ dw HEX (005F)
+ dw HEX (0060)
+ dw HEX (0061)
+ dw HEX (0062)
+ dw HEX (0063)
+ dw HEX (0064)
+ dw HEX (0065)
+ dw HEX (0066)
+ dw HEX (0067)
+ dw HEX (0068)
+ dw HEX (0069)
+ dw HEX (006A)
+ dw HEX (006B)
+ dw HEX (006C)
+ dw HEX (006D)
+ dw HEX (006E)
+ dw HEX (006F)
+ dw HEX (0070)
+ dw HEX (0071)
+ dw HEX (0072)
+ dw HEX (0073)
+ dw HEX (0074)
+ dw HEX (0075)
+ dw HEX (0076)
+ dw HEX (0077)
+ dw HEX (0078)
+ dw HEX (0079)
+ dw HEX (007A)
+ dw HEX (007B)
+ dw HEX (007C)
+ dw HEX (007D)
+ dw HEX (007E)
+ dw HEX (007F)
+ dw HEX (0080)
+ dw HEX (0081)
+ dw HEX (0082)
+ dw HEX (0083)
+ dw HEX (0084)
+ dw HEX (0085)
+ dw HEX (0086)
+ dw HEX (0087)
+ dw HEX (0088)
+ dw HEX (0089)
+ dw HEX (008A)
+ dw HEX (008B)
+ dw HEX (008C)
+ dw HEX (008D)
+ dw HEX (008E)
+ dw HEX (008F)
+ dw HEX (0090)
+ dw HEX (0091)
+ dw HEX (0092)
+ dw HEX (0093)
+ dw HEX (0094)
+ dw HEX (0095)
+ dw HEX (0096)
+ dw HEX (0097)
+ dw HEX (0098)
+ dw HEX (0099)
+ dw HEX (009A)
+ dw HEX (009B)
+ dw HEX (009C)
+ dw HEX (009D)
+ dw HEX (009E)
+ dw HEX (009F)
+ dw HEX (00A0)
+ dw HEX (00A1)
+ dw HEX (00A2)
+ dw HEX (00A3)
+ dw HEX (00A4)
+ dw HEX (00A5)
+ dw HEX (00A6)
+ dw HEX (00A7)
+ dw HEX (00A8)
+ dw HEX (00A9)
+ dw HEX (00AA)
+ dw HEX (00AB)
+ dw HEX (00AC)
+ dw HEX (00AD)
+ dw HEX (00AE)
+ dw HEX (00AF)
+ dw HEX (00B0)
+ dw HEX (00B1)
+ dw HEX (00B2)
+ dw HEX (00B3)
+ dw HEX (00B4)
+ dw HEX (00B5)
+ dw HEX (00B6)
+ dw HEX (00B7)
+ dw HEX (00B8)
+ dw HEX (00B9)
+ dw HEX (00BA)
+ dw HEX (00BB)
+ dw HEX (00BC)
+ dw HEX (00BD)
+ dw HEX (00BE)
+ dw HEX (00BF)
+ dw HEX (00C0)
+ dw HEX (00C1)
+ dw HEX (00C2)
+ dw HEX (00C3)
+ dw HEX (00C4)
+ dw HEX (00C5)
+ dw HEX (00C6)
+ dw HEX (00C7)
+ dw HEX (00C8)
+ dw HEX (00C9)
+ dw HEX (00CA)
+ dw HEX (00CB)
+ dw HEX (00CC)
+ dw HEX (00CD)
+ dw HEX (00CE)
+ dw HEX (00CF)
+ dw HEX (00D0)
+ dw HEX (00D1)
+ dw HEX (00D2)
+ dw HEX (00D3)
+ dw HEX (00D4)
+ dw HEX (00D5)
+ dw HEX (00D6)
+ dw HEX (00D7)
+ dw HEX (00D8)
+ dw HEX (00D9)
+ dw HEX (00DA)
+ dw HEX (00DB)
+ dw HEX (00DC)
+ dw HEX (00DD)
+ dw HEX (00DE)
+ dw HEX (00DF)
+ dw HEX (00E0)
+ dw HEX (00E1)
+ dw HEX (00E2)
+ dw HEX (00E3)
+ dw HEX (00E4)
+ dw HEX (00E5)
+ dw HEX (00E6)
+ dw HEX (00E7)
+ dw HEX (00E8)
+ dw HEX (00E9)
+ dw HEX (00EA)
+ dw HEX (00EB)
+ dw HEX (00EC)
+ dw HEX (00ED)
+ dw HEX (00EE)
+ dw HEX (00EF)
+ dw HEX (00F0)
+ dw HEX (00F1)
+ dw HEX (00F2)
+ dw HEX (00F3)
+ dw HEX (00F4)
+ dw HEX (00F5)
+ dw HEX (00F6)
+ dw HEX (00F7)
+ dw HEX (00F8)
+ dw HEX (00F9)
+ dw HEX (00FA)
+ dw HEX (00FB)
+ dw HEX (00FC)
+ dw HEX (00FD)
+ dw HEX (00FE)
+ dw HEX (00FF)
+
+__toupR:
+
+ dw HEX (FFFF)
+ dw HEX (0000)
+ dw HEX (0001)
+ dw HEX (0002)
+ dw HEX (0003)
+ dw HEX (0004)
+ dw HEX (0005)
+ dw HEX (0006)
+ dw HEX (0007)
+ dw HEX (0008)
+ dw HEX (0009)
+ dw HEX (000A)
+ dw HEX (000B)
+ dw HEX (000C)
+ dw HEX (000D)
+ dw HEX (000E)
+ dw HEX (000F)
+ dw HEX (0010)
+ dw HEX (0011)
+ dw HEX (0012)
+ dw HEX (0013)
+ dw HEX (0014)
+ dw HEX (0015)
+ dw HEX (0016)
+ dw HEX (0017)
+ dw HEX (0018)
+ dw HEX (0019)
+ dw HEX (001A)
+ dw HEX (001B)
+ dw HEX (001C)
+ dw HEX (001D)
+ dw HEX (001E)
+ dw HEX (001F)
+ dw HEX (0020)
+ dw HEX (0021)
+ dw HEX (0022)
+ dw HEX (0023)
+ dw HEX (0024)
+ dw HEX (0025)
+ dw HEX (0026)
+ dw HEX (0027)
+ dw HEX (0028)
+ dw HEX (0029)
+ dw HEX (002A)
+ dw HEX (002B)
+ dw HEX (002C)
+ dw HEX (002D)
+ dw HEX (002E)
+ dw HEX (002F)
+ dw HEX (0030)
+ dw HEX (0031)
+ dw HEX (0032)
+ dw HEX (0033)
+ dw HEX (0034)
+ dw HEX (0035)
+ dw HEX (0036)
+ dw HEX (0037)
+ dw HEX (0038)
+ dw HEX (0039)
+ dw HEX (003A)
+ dw HEX (003B)
+ dw HEX (003C)
+ dw HEX (003D)
+ dw HEX (003E)
+ dw HEX (003F)
+ dw HEX (0040)
+ dw HEX (0041)
+ dw HEX (0042)
+ dw HEX (0043)
+ dw HEX (0044)
+ dw HEX (0045)
+ dw HEX (0046)
+ dw HEX (0047)
+ dw HEX (0048)
+ dw HEX (0049)
+ dw HEX (004A)
+ dw HEX (004B)
+ dw HEX (004C)
+ dw HEX (004D)
+ dw HEX (004E)
+ dw HEX (004F)
+ dw HEX (0050)
+ dw HEX (0051)
+ dw HEX (0052)
+ dw HEX (0053)
+ dw HEX (0054)
+ dw HEX (0055)
+ dw HEX (0056)
+ dw HEX (0057)
+ dw HEX (0058)
+ dw HEX (0059)
+ dw HEX (005A)
+ dw HEX (005B)
+ dw HEX (005C)
+ dw HEX (005D)
+ dw HEX (005E)
+ dw HEX (005F)
+ dw HEX (0060)
+ dw HEX (0041)
+ dw HEX (0042)
+ dw HEX (0043)
+ dw HEX (0044)
+ dw HEX (0045)
+ dw HEX (0046)
+ dw HEX (0047)
+ dw HEX (0048)
+ dw HEX (0049)
+ dw HEX (004A)
+ dw HEX (004B)
+ dw HEX (004C)
+ dw HEX (004D)
+ dw HEX (004E)
+ dw HEX (004F)
+ dw HEX (0050)
+ dw HEX (0051)
+ dw HEX (0052)
+ dw HEX (0053)
+ dw HEX (0054)
+ dw HEX (0055)
+ dw HEX (0056)
+ dw HEX (0057)
+ dw HEX (0058)
+ dw HEX (0059)
+ dw HEX (005A)
+ dw HEX (007B)
+ dw HEX (007C)
+ dw HEX (007D)
+ dw HEX (007E)
+ dw HEX (007F)
+ dw HEX (0080)
+ dw HEX (0081)
+ dw HEX (0082)
+ dw HEX (0083)
+ dw HEX (0084)
+ dw HEX (0085)
+ dw HEX (0086)
+ dw HEX (0087)
+ dw HEX (0088)
+ dw HEX (0089)
+ dw HEX (008A)
+ dw HEX (008B)
+ dw HEX (008C)
+ dw HEX (008D)
+ dw HEX (008E)
+ dw HEX (008F)
+ dw HEX (0090)
+ dw HEX (0091)
+ dw HEX (0092)
+ dw HEX (0093)
+ dw HEX (0094)
+ dw HEX (0095)
+ dw HEX (0096)
+ dw HEX (0097)
+ dw HEX (0098)
+ dw HEX (0099)
+ dw HEX (009A)
+ dw HEX (009B)
+ dw HEX (009C)
+ dw HEX (009D)
+ dw HEX (009E)
+ dw HEX (009F)
+ dw HEX (00A0)
+ dw HEX (00A1)
+ dw HEX (00A2)
+ dw HEX (00A3)
+ dw HEX (00A4)
+ dw HEX (00A5)
+ dw HEX (00A6)
+ dw HEX (00A7)
+ dw HEX (00A8)
+ dw HEX (00A9)
+ dw HEX (00AA)
+ dw HEX (00AB)
+ dw HEX (00AC)
+ dw HEX (00AD)
+ dw HEX (00AE)
+ dw HEX (00AF)
+ dw HEX (00B0)
+ dw HEX (00B1)
+ dw HEX (00B2)
+ dw HEX (00B3)
+ dw HEX (00B4)
+ dw HEX (00B5)
+ dw HEX (00B6)
+ dw HEX (00B7)
+ dw HEX (00B8)
+ dw HEX (00B9)
+ dw HEX (00BA)
+ dw HEX (00BB)
+ dw HEX (00BC)
+ dw HEX (00BD)
+ dw HEX (00BE)
+ dw HEX (00BF)
+ dw HEX (00C0)
+ dw HEX (00C1)
+ dw HEX (00C2)
+ dw HEX (00C3)
+ dw HEX (00C4)
+ dw HEX (00C5)
+ dw HEX (00C6)
+ dw HEX (00C7)
+ dw HEX (00C8)
+ dw HEX (00C9)
+ dw HEX (00CA)
+ dw HEX (00CB)
+ dw HEX (00CC)
+ dw HEX (00CD)
+ dw HEX (00CE)
+ dw HEX (00CF)
+ dw HEX (00D0)
+ dw HEX (00D1)
+ dw HEX (00D2)
+ dw HEX (00D3)
+ dw HEX (00D4)
+ dw HEX (00D5)
+ dw HEX (00D6)
+ dw HEX (00D7)
+ dw HEX (00D8)
+ dw HEX (00D9)
+ dw HEX (00DA)
+ dw HEX (00DB)
+ dw HEX (00DC)
+ dw HEX (00DD)
+ dw HEX (00DE)
+ dw HEX (00DF)
+ dw HEX (00E0)
+ dw HEX (00E1)
+ dw HEX (00E2)
+ dw HEX (00E3)
+ dw HEX (00E4)
+ dw HEX (00E5)
+ dw HEX (00E6)
+ dw HEX (00E7)
+ dw HEX (00E8)
+ dw HEX (00E9)
+ dw HEX (00EA)
+ dw HEX (00EB)
+ dw HEX (00EC)
+ dw HEX (00ED)
+ dw HEX (00EE)
+ dw HEX (00EF)
+ dw HEX (00F0)
+ dw HEX (00F1)
+ dw HEX (00F2)
+ dw HEX (00F3)
+ dw HEX (00F4)
+ dw HEX (00F5)
+ dw HEX (00F6)
+ dw HEX (00F7)
+ dw HEX (00F8)
+ dw HEX (00F9)
+ dw HEX (00FA)
+ dw HEX (00FB)
+ dw HEX (00FC)
+ dw HEX (00FD)
+ dw HEX (00FE)
+ dw HEX (00FF)
--- /dev/null
+;******************************************************************************
+; @file stdio.inc
+;******************************************************************************
+%ifndef _STDIO_INC
+%define _STDIO_INC
+
+%define __SRD 0x0004
+%define __SWR 0x0008
+%define __SRW 0x0010
+%define __SEOF 0x0020
+%define __SAPP 0x0100
+
+%endif ; _STDIO_INC
--- /dev/null
+;******************************************************************************
+; @file fcntl.inc
+;******************************************************************************
+%ifndef _FCNTL_INC
+%define _FCNTL_INC
+
+%define O_CREAT 0x0040
+%define O_TRUNC 0x0200
+%define O_APPEND 0x0400
+%define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+
+%define O_RDONLY (0)
+%define O_WRONLY (1)
+%define O_RDWR (2)
+
+%endif ; _FCNTL_INC
--- /dev/null
+;******************************************************************************
+; @file fclose.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fclose
+;******************************************************************************
+global _fclose
+_fclose:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actaully have some value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _fclose.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ xor si, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es:[si]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=3E to close the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (3E)
+ int HEX (21)
+ jc _fclose.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Free our pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push word ptr [bp + 4]
+
+ call _free
+ add sp, 2
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
+
+_fclose.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file feof.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _feof
+;******************************************************************************
+global _feof
+_feof:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actaully have some value.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _feof.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set up the extra segment and si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+ xor si, si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the flags from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, es:[si + 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached EOF?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, __SEOF
+ jz _feof.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return 1 to indicate that we reached EOF.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 1
+
+_feof.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
+
+_feof.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop es
+ pop bx
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file fgetc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _fgetc
+;******************************************************************************
+global _fgetc
+_fgetc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have actually pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz _fgetc.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ mov bx, es:[di + 0]
+ mov cx, es:[di + 2]
+
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the end of the file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test cx, __SEOF
+ jnz _fgetc.eof
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll read 1 byte.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 1
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Initialize the dx register with the address of the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, offset _tempbuf
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read # no of bytes into the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (3F)
+ int HEX (21)
+ jc _fgetc.error
+
+ and ax, ax
+ jnz _fgetc.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add an EOF marker to the flags,
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ or word ptr es:[di + 2], __SEOF
+ pop di
+ pop es
+
+ mov byte ptr cs:[_tempbuf], 0
+
+_fgetc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the character that was read and clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_tempbuf]
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fgetc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_tempbuf: db HEX (00)
--- /dev/null
+;******************************************************************************
+; @file flags.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <sys/fcntl.inc>
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _sflags
+;******************************************************************************
+global _sflags
+_sflags:
+
+ push bp
+ mov bp, sp
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+
+ mov si, word ptr [bp + 4]
+ lodsb
+
+ cmp al, 'r'
+ jne _sflags.not_read
+
+ mov bx, __SRD
+ mov cx, O_RDONLY
+ xor dx, dx
+
+ jmp _sflags.loop
+
+_sflags.not_read:
+
+ cmp al, 'w'
+ jne _sflags.not_write
+
+ mov bx, __SWR
+ mov cx, O_WRONLY
+ mov dx, O_CREAT | O_TRUNC
+
+ jmp _sflags.loop
+
+_sflags.not_write:
+
+ cmp al, 'a'
+ jne _sflags.not_append
+
+ mov bx, __SWR | __SAPP
+ mov cx, O_WRONLY
+ mov dx, O_CREAT | O_APPEND
+
+ jmp _sflags.loop
+
+_sflags.not_append:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out ax and set the carry flag to indicate an error.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_sflags.loop:
+
+ lodsb
+
+ or al, al
+ jz _sflags.done
+
+ cmp al, '+'
+ jne _sflags.next
+
+ mov di, __SRD | __SWR
+ not di
+
+ and bx, di
+ or bx, __SRW
+
+ mov di, O_ACCMODE
+ not di
+
+ and cx, di
+ or cx, O_RDWR
+
+_sflags.next:
+
+ jmp short _sflags.loop
+
+_sflags.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; The stack should contain an address for the flags at offset 6
+ ;; so store it in the di register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, word ptr [bp + 6]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in the cx register into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Or the value with the value stored in the dx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ or si, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the new value in the address that di points to.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov [di], si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the return to the value stored in bx and clear the carry flag to
+ ;; indicate success.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file fopen.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <sys/fcntl.inc>
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _fopen
+;******************************************************************************
+global _fopen
+_fopen:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push es
+ push si
+ push di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We want to extract the flags into our _oflags value so push
+ ;; the address of it to the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, offset _oflags
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Offset +6 on the stack should contain the mode string (i.e. r+) to use
+ ;; when opening the file so get the value and re-push that on the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 6]
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert our mode string into an integer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _sflags
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean-up the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If ax is zero then the flag string was invalid.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, ax
+ jz _fopen.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the return value into the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set ax to the value of the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, [_oflags]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we need to create the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test ax, O_CREAT
+ jnz _fopen.co
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value to remove O_CREAT, O_TRUNC and O_APPEND.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, O_ACCMODE
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=3D to open the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (3D)
+ int HEX (21)
+ jc _fopen.error
+
+_fopen.success:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the file handle in ax.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Allocate some memory for a pointer (i.e. FILE *).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, 16
+ xor dx, dx
+
+ push ax
+ push dx
+
+ call _malloc
+ add sp, 4
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure the malloc didn't fail.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, ax
+ jz _fopen.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll use es:di to store the values.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, ax
+ xor di, di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear out the memory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+ push cx
+
+ mov cx, 16
+ rep stosb
+
+ pop cx
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the file handle.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Store the flags.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, si
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We're not EOF yet.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stosw
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the value in the extra segment into ax.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, es
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fopen.co:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Are we appending the file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test ax, O_APPEND
+ jnz _fopen.append
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value to remove O_CREAT, O_TRUNC and O_APPEND.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, O_ACCMODE
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First try to open the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (3D)
+ int HEX (21)
+ jnc _fopen.success
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make the flags read-write.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, __SRD | __SWR
+ not di
+
+ and si, di
+ or si, __SRW
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Create the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (3C)
+ mov cx, HEX (20)
+ int HEX (21)
+ jc _fopen.error
+
+ jmp _fopen.success
+
+_fopen.append:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; And the value to remove O_CREAT, O_TRUNC and O_APPEND.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and ax, O_ACCMODE
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First try to open the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (3D)
+ int HEX (21)
+ jnc _fopen.move
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make the flags read-write.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, __SRD | __SWR
+ not di
+
+ and si, di
+ or si, __SRW
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Create the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 4]
+
+ mov ah, HEX (3C)
+ mov cx, HEX (20)
+ int HEX (21)
+ jc _fopen.error
+
+_fopen.move:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Copy the file handle into the bx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We want to move zero bytes from the end.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+ xor dx, dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Move the file pointer to the end of the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (4202)
+ int HEX (21)
+ jc _fopen.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Reset ax back to the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to our success code.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _fopen.success
+
+_fopen.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop es
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_oflags: dw HEX (0000)
--- /dev/null
+;******************************************************************************
+; @file fread.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include <stdio.inc>
+
+;******************************************************************************
+; @function _fread
+;******************************************************************************
+global _fread
+_fread:
+
+ 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 buffer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have actually buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;and si, si
+ ;jz _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 10]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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 _fread.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ mov bx, es:[di + 0]
+ mov dx, es:[di + 2]
+
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Have we reached the end of the file?
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ test dx, __SEOF
+ jnz _fread.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]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Read # no of bytes into the buffer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (3F)
+ int HEX (21)
+ jc _fread.error
+
+ and ax, ax
+ jnz _fread.read_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add an EOF marker to the flags,
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ or word ptr es:[di + 2], __SEOF
+ pop di
+ pop es
+
+ jmp short _fread.zero
+
+_fread.read_ok:
+
+ cmp cx, ax
+ je _fread.size_ok
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Add an EOF marker to the flags,
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ or word ptr es:[di + 2], __SEOF
+ pop di
+ pop es
+
+_fread.size_ok:
+
+ cmp word ptr [bp + 6], 0
+ je _fread.zero
+
+ xor dx, dx
+
+ mov cx, word ptr [bp + 6]
+ div cx
+
+ mov word ptr [bp - 2], ax
+ jmp _fread.done
+
+_fread.zero:
+
+ mov word ptr [bp - 2], 0
+
+_fread.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp - 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; 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
+
+_fread.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
--- /dev/null
+;******************************************************************************
+; @file fseek.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _fseek
+;******************************************************************************
+global _fseek
+_fseek:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the seek type off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 10]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the seek value off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov dx, word ptr [bp + 8]
+ mov cx, word ptr [bp + 6]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz _fseek.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ mov bx, es:[di + 0]
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Seek the file.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ah, HEX (42)
+ int HEX (21)
+ jc _fseek.error
+
+_fseek.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_fseek.error:
+
+ mov ax, -1
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file ftell.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _ftell
+;******************************************************************************
+global _ftell
+_ftell:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the pointer off the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we actually have a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and si, si
+ jz _ftell.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get our file handle from the pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push es
+ push di
+
+ mov es, si
+ xor di, di
+
+ mov bx, es:[di + 0]
+ pop di
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Seek the file with 0.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, HEX (4201)
+ xor cx, cx
+ xor dx, dx
+ int HEX (21)
+ jc _ftell.error
+
+_ftell.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
+
+_ftell.error:
+
+ mov ax, -1
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the base pointer and return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file free.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _free
+;******************************************************************************
+global _free
+_free:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=49 to free the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, word ptr [bp + 4]
+
+ mov ah, HEX (49)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop ax
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file malloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _malloc
+;******************************************************************************
+global _malloc
+_malloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push dx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 6]
+ mov dx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the size to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _malloc.ok
+
+_malloc.inc:
+
+ inc ax
+ jz _malloc.error
+
+_malloc.ok:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=48 to allocate the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bx, ax
+
+ mov ah, HEX (48)
+ int HEX (21)
+ jc _malloc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_malloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file realloc.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _realloc
+;******************************************************************************
+global _realloc
+_realloc:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push cx
+ push si
+ push di
+ push dx
+ push es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the size (in bytes) from the stack as well as the pointer to
+ ;; re-allocate.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, word ptr [bp + 8]
+ mov dx, word ptr [bp + 6]
+ mov bx, word ptr [bp + 4]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Make sure we have valid memory as a pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ and bx, bx
+ jz _realloc.calc
+
+ mov di, bx
+ dec di
+ mov es, di
+
+ xor di, di
+
+ cmp byte ptr es:[di], 'M'
+ jne _realloc.error
+
+ cmp byte ptr es:[di + 1], 'C'
+ jne _realloc.error
+
+ cmp byte ptr es:[di + 2], 'B'
+ jne _realloc.error
+
+_realloc.calc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Convert the size to paragraphs.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cx, 16
+ div cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If dx is non-zero then try to increase the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, 0
+ je _realloc.ok
+
+_realloc.inc:
+
+ inc ax
+ jz _realloc.error
+
+_realloc.ok:
+
+ mov si, ax
+
+ and bx, bx
+ jz _realloc.alloc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; First. lets try and resize the memory block.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push es
+
+ mov es, bx
+ mov bx, si
+
+ mov ah, HEX (4A)
+ int HEX (21)
+ pop es
+ pop bx
+ jnc _realloc.done
+
+_realloc.alloc:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Call int 21h/ah=48 to allocate the blocks.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ mov bx, si
+
+ mov ah, HEX (48)
+ int HEX (21)
+ pop bx
+ jc _realloc.error
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Only copy existing data if there was an original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov di, bx
+
+ and di, di
+ jz _realloc.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers that copy will clobber.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+ push ds
+
+ mov di, bx
+ mov ds, di
+
+ dec di
+
+ mov es, di
+ xor di, di
+
+ mov cx, word ptr es:[di + 3]
+ mov es, ax
+
+ cmp cx, bx
+ jb _realloc.copy
+
+ mov cx, bx
+
+_realloc.copy:
+
+ xor si, si
+ xor di, di
+
+ push cx
+
+ mov cx, 16
+ rep movsb
+
+ pop cx
+
+ mov si, es
+ inc si
+ mov es, si
+
+ mov di, ds
+ inc di
+ mov ds, di
+
+ loop _realloc.copy
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers that copy clobbered.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop si
+
+_realloc.free:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If we reached this point then free the original pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov es, bx
+
+ mov ah, HEX (49)
+ int HEX (21)
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the new pointer;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ax
+
+_realloc.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ clc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop di
+ pop si
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clear the carry flag and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
+
+_realloc.error:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Zero out the ax register and set the carry flag.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor ax, ax
+ stc
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop es
+ pop dx
+ pop di
+ pop si
+ pop cx
+ pop bx
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
--- /dev/null
+;******************************************************************************
+; @file memmove.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _memmove
+;******************************************************************************
+global _memmove
+_memmove:
+
+ push bp
+ mov bp, sp
+
+ push si
+ push di
+ push bx
+ push cx
+
+ mov di, word ptr [bp + 4]
+ mov si, word ptr [bp + 6]
+ mov cx, word ptr [bp + 8]
+
+.L3:
+
+ cmp di, si
+ ja .L2
+
+.L4:
+
+ and cx, cx
+ jz .L1
+
+ movsb
+ dec cx
+
+ jmp .L4
+
+ jmp .L1
+
+.L2:
+
+ and cx, cx
+ jz .L1
+
+ dec cx
+
+.L6:
+
+ and cx, cx
+ jz .L5
+
+ mov bx, si
+ add bx, cx
+
+ mov al, [si]
+
+ mov bx, di
+ add bx, cx
+
+ mov es:[di], al
+
+ dec cx
+ jmp .L6
+
+.L5:
+
+ mov bx, si
+ add bx, cx
+
+ mov al, [si]
+
+ mov bx, di
+ add bx, cx
+
+ mov es:[di], al
+
+.L1:
+
+ pop cx
+ pop bx
+ pop di
+ pop si
+
+ mov ax, word ptr [bp + 4]
+ clc
+
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file strchr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strchr
+;******************************************************************************
+global _strchr
+_strchr:
+
+ push bp
+ mov bp, sp
+
+ push si
+ push bx
+
+ mov bx, word ptr [bp + 6]
+ mov si, word ptr [bp + 4]
+
+_strchr.loop:
+
+ lodsb
+
+ or al, al
+ jz _strchr.done
+
+ cmp al, bl
+ je _strchr.found
+
+ jmp short _strchr.loop
+
+_strchr.found:
+
+ mov ax, si
+ dec ax
+
+ pop bx
+ pop si
+ pop bp
+ ret
+
+_strchr.done:
+
+ xor ax, ax
+
+ pop bx
+ pop si
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file strcmp.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strcmp
+;******************************************************************************
+global _strcmp
+_strcmp:
+
+ push bp
+ mov bp, sp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push bx
+ push si
+ push di
+
+ mov si, word ptr [bp + 6]
+ mov di, word ptr [bp + 4]
+
+_strcmp.loop:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we've reached the end of a string.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp byte ptr [si], 0
+ je _strcmp.check
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get one character from both si and di.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov bh, [si]
+ mov bl, [di]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If bh (byte from si) is less than bl (byte from di) then we're done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bh, bl
+ jb _strcmp.less
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If bh (byte from si) is greater than bl (byte from di) then we're done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp bh, bl
+ ja _strcmp.more
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Advance si and di to the next character
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ inc si
+ inc di
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Run the check again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp short _strcmp.loop
+
+_strcmp.less:
+
+ mov ax, -1
+ stc
+
+ jmp short _strcmp.done
+
+_strcmp.more:
+
+ mov ax, 1
+ stc
+
+ jmp short _strcmp.done
+
+_strcmp.check:
+
+ xor ax, ax
+ clc
+
+ cmp byte ptr [di], 0
+ je _strcmp.done
+
+ mov ax, -1
+ stc
+
+_strcmp.done:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers and return.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop di
+ pop si
+ pop bx
+
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file strcpy.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strcpy
+;******************************************************************************
+global _strcpy
+_strcpy:
+
+ push bp
+ mov bp, sp
+
+ push cx
+ push si
+ push di
+
+ mov si, word ptr [bp + 6]
+ mov di, word ptr [bp + 4]
+
+_strcpy.loop:
+
+ lodsb
+
+ or al, al
+ jz _strcpy.done
+
+ stosb
+ jmp short _strcpy.loop
+
+_strcpy.done:
+
+ mov ax, di
+
+ pop di
+ pop si
+ pop cx
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file strlen.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strlen
+;******************************************************************************
+global _strlen
+_strlen:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 2
+
+ push cx
+ push si
+ push di
+
+ mov si, word ptr [bp + 4]
+ mov word ptr [bp - 2], 0
+
+_strlen.loop:
+
+ lodsb
+
+ or al, al
+ jz _strlen.done
+
+ inc word ptr [bp - 2]
+ jmp short _strlen.loop
+
+_strlen.done:
+
+ mov ax, word ptr [bp - 2]
+
+ pop di
+ pop si
+ pop cx
+
+ add sp, 2
+ pop bp
+
+ ret
--- /dev/null
+;******************************************************************************
+; @file strrchr.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _strrchr
+;******************************************************************************
+global _strrchr
+_strrchr:
+
+ push bp
+ mov bp, sp
+
+ push si
+ push bx
+ push di
+
+ mov bx, word ptr [bp + 6]
+ mov si, word ptr [bp + 4]
+
+ xor di, di
+
+_strrchr.loop:
+
+ lodsb
+
+ or al, al
+ jz _strrchr.done
+
+ cmp al, bl
+ jne _strrchr.loop
+
+ mov di, si
+ dec di
+
+ jmp short _strrchr.loop
+
+_strrchr.done:
+
+ mov ax, di
+
+ pop di
+ pop bx
+ pop si
+ pop bp
+ ret
--- /dev/null
+;******************************************************************************
+; @file _udivmodsi4.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _udivmodsi4
+;******************************************************************************
+global _udivmodsi4
+_udivmodsi4:
+
+ push si
+ push bp
+
+ mov bp, sp
+ sub sp, 12
+
+ mov word ptr [bp - 4], 1
+ mov word ptr [bp - 2], 0
+ mov word ptr [bp - 8], 0
+ mov word ptr [bp - 6], 0
+
+ jmp .L2
+
+.L6:
+
+ shl word ptr [bp + 10]
+ rcl word ptr [bp + 12]
+ shl word ptr [bp - 4]
+ rcl word ptr [bp - 2]
+
+.L2:
+
+ mov ax, word ptr [bp + 8]
+ cmp ax, word ptr [bp + 12]
+ ja .L14
+
+ mov ax, word ptr [bp + 8]
+ cmp ax, word ptr [bp + 12]
+ jne .L8
+
+ mov ax, word ptr [bp + 6]
+ cmp ax, word ptr [bp + 10]
+ jbe .L3
+
+.L14:
+
+ mov dx, word ptr [bp - 4]
+ mov ax, word ptr [bp - 2]
+
+ or ax, dx
+ cmp ax, 1
+
+ test ax, ax
+ je .L8
+
+ mov ax, word ptr [bp + 10]
+ mov dx, word ptr [bp + 12]
+
+ test dx, dx
+ jge .L6
+
+.L3:
+
+ jmp .L8
+
+.L11:
+
+ mov ax, word ptr [bp + 12]
+
+ cmp ax, word ptr [bp + 8]
+ ja .L9
+
+ mov ax, word ptr [bp + 12]
+
+ cmp ax, word ptr [bp + 8]
+ jne .L15
+
+ mov ax, word ptr [bp + 10]
+
+ cmp ax, word ptr [bp + 6]
+ ja .L9
+
+.L15:
+
+ mov bx, word ptr [bp + 6]
+ mov si, word ptr [bp + 8]
+
+ mov ax, word ptr [bp + 10]
+ mov dx, word ptr [bp + 12]
+
+ mov cx, bx
+ sub cx, ax
+ mov word ptr [bp - 12], cx
+
+ mov cx, si
+ sbb cx, dx
+ mov word ptr [bp - 10], cx
+
+ mov ax, word ptr [bp - 12]
+ mov word ptr [bp + 6], ax
+ mov ax, word ptr [bp - 10]
+ mov word ptr [bp + 8], ax
+
+ mov dx, word ptr [bp - 8]
+ mov ax, word ptr [bp - 4]
+ or ax, dx
+ mov word ptr [bp - 8], ax
+
+ mov dx, word ptr [bp - 6]
+ mov ax, word ptr [bp - 2]
+ or ax, dx
+ mov word ptr [bp - 6], ax
+
+.L9:
+
+ shr word ptr [bp - 2]
+ rcr word ptr [bp - 4]
+
+ shr word ptr [bp + 12]
+ rcr word ptr [bp + 10]
+
+.L8:
+
+ mov dx, word ptr [bp - 4]
+ mov ax, word ptr [bp - 2]
+ or ax, dx
+ cmp ax, 1
+
+ test ax, ax
+ jne .L11
+
+ cmp word ptr [bp + 14], 0
+ je .L12
+
+ mov ax, word ptr [bp + 6]
+ mov dx, word ptr [bp + 8]
+
+ jmp .L13
+
+.L12:
+
+ mov ax, word ptr [bp - 8]
+ mov dx, word ptr [bp - 6]
+
+.L13:
+
+ add sp, 12
+ pop bp
+ pop si
+ ret
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := dosfstools parted binutils
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for d in $(TARGETS); do \
+ if [ ! -d "$(OBJDIR)/$$d" ]; then mkdir -p "$(OBJDIR)/$$d"; fi; \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" all; \
+ done
+
+clean:
+ for d in $(TARGETS); do \
+ if [ -d "$(OBJDIR)/$$d" ]; then \
+ $(MAKE) -C "$(OBJDIR)/$$d" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)/$$d" SRCDIR="$(SRCDIR)/$$d" clean; \
+ fi; \
+ done
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := dosfstools parted binutils
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%d in ($(TARGETS)) do ( \
+ ( if not exist "$(OBJDIR)/%%d" ( mkdir "$(OBJDIR)/%%d" ) ) & \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" all \
+ )
+
+clean:
+ for %%d in ($(TARGETS)) do ( \
+ if exist "$(OBJDIR)/%%d" ( \
+ $(MAKE) -C "$(OBJDIR)/%%d" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)/%%d" SRCDIR="$(SRCDIR)/%%d" clean \
+ ) \
+ )
--- /dev/null
+#******************************************************************************
+# @file Makefile.unix
+#******************************************************************************
+TARGETS := ar as ld
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for d in $(TARGETS); do \
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)/$$d" all; \
+ done
+
+clean:
+ for d in $(TARGETS); do \
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/$$d/Makefile.unix" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)/$$d" clean; \
+ done
--- /dev/null
+#******************************************************************************
+# @file Makefile.w32
+#******************************************************************************
+TARGETS := ar as ld
+
+OBJDIR ?= $(CURDIR)
+SRCDIR ?= $(CURDIR)
+
+all:
+ for %%d in ($(TARGETS)) do ( \
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)/%%d" all \
+ )
+
+clean:
+ for %%d in ($(TARGETS)) do ( \
+ $(MAKE) -C "$(OBJDIR)" -f "$(SRCDIR)/%%d/Makefile.w32" OBJDIR="$(OBJDIR)" SRCDIR="$(SRCDIR)/%%d" clean \
+ )
--- /dev/null
+Subproject commit d7ae5ccfda2892d7804ab86039a740547c089158
--- /dev/null
+Subproject commit 1c5f2de0ea49b930fc16bbf187b1adb64cd01832
--- /dev/null
+Subproject commit ee1bb0fe4d5e457480ff4ab46fd1f9cf40a1cfb2
--- /dev/null
+Subproject commit 2b218a0bd719edc90f0e6168b8c55c909ee67703
--- /dev/null
+Subproject commit d0bd265427872bba3161c4d1b4a73b8058d0cb9f