From 3bc911f5bcac3bf643bdc95785031d808183616e Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Thu, 22 Aug 2024 16:30:38 +0100 Subject: [PATCH] Parse all disks in freeldr and bug fixes --- build/chimaera.img | Bin 368640 -> 368640 bytes build/chimaera.vhd | Bin 34120704 -> 34120704 bytes src/Makefile.unix | 2 +- src/boot/freeldr/Makefile.unix | 2 +- src/boot/freeldr/Makefile.w32 | 2 +- src/boot/freeldr/core/Makefile.unix | 2 +- src/boot/freeldr/core/Makefile.w32 | 2 +- src/boot/freeldr/core/config.asm | 4 +- src/boot/freeldr/core/disk.asm | 738 ++++++ src/boot/freeldr/core/divide.asm | 125 ++ src/boot/freeldr/core/fat.asm | 105 +- src/boot/freeldr/core/file.asm | 494 ++-- .../freeldr/{libc/stdlib => core}/free.asm | 6 +- src/boot/freeldr/core/freeldr.asm | 980 ++++---- src/boot/freeldr/core/int21.asm | 727 +++++- src/boot/freeldr/core/invalid.asm | 125 ++ src/boot/freeldr/core/xmalloc.asm | 28 +- src/boot/freeldr/core/xrealloc.asm | 156 +- src/boot/freeldr/freeldr.cfg | 3 +- src/boot/freeldr/lib/Makefile.unix | 20 + src/boot/freeldr/lib/Makefile.w32 | 20 + src/boot/freeldr/lib/crt/Makefile.unix | 25 + src/boot/freeldr/lib/crt/Makefile.w32 | 25 + src/boot/freeldr/lib/crt/ctype.asm | 1988 +++++++++++++++++ .../{libc => lib/crt}/stdio/fclose.asm | 0 .../freeldr/{libc => lib/crt}/stdio/feof.asm | 0 .../freeldr/{libc => lib/crt}/stdio/fopen.asm | 0 .../freeldr/{libc => lib/crt}/stdio/fread.asm | 0 .../{libc => lib/crt}/string/memmove.asm | 0 .../{libc => lib/crt}/string/strlen.asm | 0 src/boot/freeldr/libc/Makefile.unix | 35 - src/boot/freeldr/libc/Makefile.w32 | 35 - src/boot/freeldr/libc/stdlib/malloc.asm | 90 - src/boot/freeldr/libc/stdlib/realloc.asm | 233 -- src/kernel/disk.asm | 20 +- src/kernel/divide.asm | 184 +- src/kernel/kernel.asm | 15 +- 37 files changed, 4742 insertions(+), 1449 deletions(-) create mode 100644 src/boot/freeldr/core/divide.asm rename src/boot/freeldr/{libc/stdlib => core}/free.asm (92%) create mode 100644 src/boot/freeldr/core/invalid.asm create mode 100644 src/boot/freeldr/lib/Makefile.unix create mode 100644 src/boot/freeldr/lib/Makefile.w32 create mode 100644 src/boot/freeldr/lib/crt/Makefile.unix create mode 100644 src/boot/freeldr/lib/crt/Makefile.w32 create mode 100644 src/boot/freeldr/lib/crt/ctype.asm rename src/boot/freeldr/{libc => lib/crt}/stdio/fclose.asm (100%) rename src/boot/freeldr/{libc => lib/crt}/stdio/feof.asm (100%) rename src/boot/freeldr/{libc => lib/crt}/stdio/fopen.asm (100%) rename src/boot/freeldr/{libc => lib/crt}/stdio/fread.asm (100%) rename src/boot/freeldr/{libc => lib/crt}/string/memmove.asm (100%) rename src/boot/freeldr/{libc => lib/crt}/string/strlen.asm (100%) delete mode 100644 src/boot/freeldr/libc/Makefile.unix delete mode 100644 src/boot/freeldr/libc/Makefile.w32 delete mode 100644 src/boot/freeldr/libc/stdlib/malloc.asm delete mode 100644 src/boot/freeldr/libc/stdlib/realloc.asm diff --git a/build/chimaera.img b/build/chimaera.img index 8e2c89e7b051f5c104df4a9ec0efe8b6c14be85c..4066ef5b2d0939bb27bc7d312ea185f65dc28108 100644 GIT binary patch delta 13663 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 delta 12624 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

%9mqB0 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 QpE0?=M}Pcb_(sM50zP^%n*aa+ delta 15635 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 0x05ff) + 1 = 0060:0000 -> 0x0600. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + add di, 16 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Loop back to the clear the segment. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + jmp short _clear_memory + +_check_disks: + + mov cx, 2 + +.L1: + + and cx, cx + jz .L2 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; The very first thing we do is allocate at least 1 disk for use + ;; with floppies. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, HEX (80) + push ax + + xor ax, ax + push ax + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Try to allocate memory, this should never return if it fails. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + call _xmalloc + add sp, 4 + + 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 + push ax + + xor ax, ax + push ax + + call _xmalloc + add sp, 4 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Store the value. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - sti + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Make sure that the keyboard buffer is cleared. + ;; Start in the root of the disk. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - call _clear_kbd + xor ax, ax + stosw + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Convert the sectors per cluster to a word. + ;; 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 al, [_sectors_per_cluster] - cbw - mov [_secsperclust], ax + mov ax, 1024 + push ax + + xor ax, ax + push ax + + call _xmalloc + add sp, 4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; How big is a cluster, really? + ;; Store the value. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mul word ptr [_bytes_per_sector] - mov [_clustsize], ax + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Get the screen size. + ;; Decrement cx and loop back for next drive. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - call _adjust_screen + dec cx + jnz .L1 -_setup_malloc: +.L2: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; First we'll move the value in the stack pointer into the ax register - ;; and clear the dx register. + ;; Zero out ah and put the drive number in al. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax, sp - xor dx, dx + xor ah, ah + mov al, cs:[_drive_no] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Divide by 16 to get the segment. + ;; Are we booted from a floppy or hard disk? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov cx, 16 - div cx + test al, HEX (80) + jnz .L6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Do we have any left over bytes (size % 16). + ;; Set the selected disk as the drive number. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - and dx, dx + mov cs:[_selected_disk], ax + inc word ptr cs:[_selected_disk] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Nope, so we got the right segment. + ;; Okay, we are booted from a floppy so we need to figure out which + ;; address it is within our _Vec_parts "structure". ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - jz _segment_ok + 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Yep, we have linguring bytes so increase the segment. + ;; Try and read the drive. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - inc ax + 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 .L3 + + call _error + db "panic: failed to read boot drive", HEX (0D), HEX (0A), HEX (00) + +.L3: + + cmp byte ptr ss:[bx + 0], HEX (EB) + jne .L14 + cmp byte ptr ss:[bx + 2], HEX (90) + jne .L14 + + jmp .L15 + +.L14: + + call _error + db "panic: seleteced disk does not have a valid/supported parition", HEX (0D), HEX (0A), HEX (00) + +.L15: + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; If the zero flag is set then we have overflowed - ;; (greater than 65535 bytes) + ;; Copy the BPB to our "structure". ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - jnz _segment_ok + push ds + + mov ax, ss + mov ds, ax + + mov si, bx + add si, 11 + + mov cx, 25 + rep movsb + + pop ds ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Just for good measure set the data segment to the code segment. + ;; Store the drive number. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax, cs - mov ds, ax + mov al, cs:[_drive_no] + stosb ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Print an error. + ;; Floppies should be FAT12 so pad with zeros. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - call _error - db "segment overflow", HEX (0D), HEX (0A), HEX (00) - -_segment_ok: - + xor ax, ax + stosw + stosw + + xor dx, dx + push di + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; 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. + ;; Calculate the offset of the first FAT. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov bx, ss - add ax, bx + mov si, ss:[bx + 28] + mov di, ss:[bx + 30] - mov [_free_seg], ax + add si, ss:[bx + 14] + adc di, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Get the total memory (in KBs) and convert it to paragrahps for the - ;; maximum segment value. + ;; Move the value in di to dx and restore di. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - int HEX (12) + mov cx, di + pop di - mov cl, 6 - shl ax, cl + push ax - mov [_max_seg], ax + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Save the offset for later use. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, si + stosw + + mov ax, cx + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Initialize the di register with our free segment. + ;; Repush di and reset the di register. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov di, [_free_seg] + pop ax + + push di + mov di, cx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Zero out the ax register ready for stosw. + ;; Calculate how many sectors both FATs require. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - xor ax, ax - -_clear_memory: - + mov al, ss:[bx + 16] + cbw + mul word ptr ss:[bx + 22] + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; If we've reached out max segment then we've cleared all our - ;; free memory. + ;; Adjust the FAT offset to get the root directory offset. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - cmp di, [_max_seg] - je _setup_interrupts + add si, ax + adc di, dx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Preserve some registers. + ;; Move the value in di to dx and restore di. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - push cx - push di - push es + mov cx, di + pop di + + push ax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Initialize the extra segment with the value in the di register. + ;; Save the offset for later use. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov es, di + mov ax, si + stosw + + mov ax, cx + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Zero out the di register. + ;; Repush di and reset the di register. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - xor di, di + pop ax + + push di + mov di, cx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; We'll be clearing 128 words (i.e 128 * 2) at a time. + ;; Calculate how many sectors the root directory requires. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov cx, 128 + mov ax, HEX (0020) + mul word ptr ss:[bx + 17] + div word ptr ss:[bx + 11] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Store the value in the ax register into es:di unitl cx is zero. + ;; Adjust the root offset to get the data offset. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - rep stosw + add si, ax + adc di, dx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Restore our registers. + ;; Move the value in di to dx and restore di. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - pop es + mov dx, di pop di - pop cx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Add 16 to get the next segment. - ;; - ;; E.g. (0050:00ff -> 0x05ff) + 1 = 0060:0000 -> 0x0600. + ;; Save the offset for later use. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - add di, 16 + mov ax, si + stosw + + mov ax, dx + stosw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Loop back to the clear the segment. + ;; Floppies shouldn't have a sector mask or shift. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - jmp short _clear_memory + 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 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; No info sector. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor ax, ax + stosw -_setup_interrupts: +.L6: + + call _get_hard_disk_partitions + +.L7: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Preserve registers. + ;; Reserve 1024 bytes for a fat segment. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, 1024 push ax - push bx - push dx - push si - push di - push es - push ds - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Disable interrupts while we set everything up. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - cli + xor ax, ax + push ax + + call _xmalloc + add sp, 4 + mov cs:[_fat_seg], ax + +_setup_interrupts: + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Setup si and bx to point to our list and list end. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -734,13 +799,13 @@ _setup_interrupts: xor ax, ax mov es, ax -.L6: +.L4: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Make sure we're not at the end of our interrupts list. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp si, bx - je .L7 + je .L5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Load a byte from DS:SI to the al register. @@ -795,9 +860,9 @@ _setup_interrupts: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Loop back for the next entry (if there is one). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - jmp short .L6 + jmp short .L4 -.L7: +.L5: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Re-enable interrupts. @@ -805,42 +870,37 @@ _setup_interrupts: sti ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Restore registers. + ;; Make sure the data segment is actually initialized to the + ;; code segment. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - 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 + mov ax, cs + mov ds, ax - push ax - push dx + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; We also want to make sure the extra segment is initialized to the + ;; code segment. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov es, ax - call _xmalloc - add sp, 4 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Initialize the base pointer with the stack pointer. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov bp, sp - mov [_fat_seg], ax - -_reserve_scratch: - - mov ax, [_bytes_per_sector] + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Zero out all other registers. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor si, si + xor di, di + xor ax, ax + xor bx, bx + xor cx, cx xor dx, dx - push ax - push dx - - call _xmalloc - add sp, 4 - - mov [_disk_scratch], ax + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Decrement the selected disk by 1. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + dec word ptr cs:[_selected_disk] _main: @@ -935,12 +995,12 @@ _config_ok: mov cx, cs:[_menu_entries + 4] and cx, cx - jnz .L8 + jnz .L11 call _error db "error: no entries found in config file", HEX (0D), HEX (0A), HEX (00) -.L8: +.L11: call _run_menu @@ -1279,13 +1339,13 @@ _segment_ok2: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Copy the jump. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax, cs:[_fat_jump + 0] + mov al, cs:[_fat_jump + 0] stosb - mov ax, cs:[_fat_jump + 1] + mov al, cs:[_fat_jump + 1] stosb - mov ax, cs:[_fat_jump + 2] + mov al, cs:[_fat_jump + 2] stosb ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1371,12 +1431,16 @@ _freeldr_cfg3: db "/freeldr.cfg", HEX (00) _interrupts_list: - db HEX (19) - dw _int19_handler - dw HEX (0000) + 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 HEX (21) - dw _int21_dispatch - dw HEX (0000) + db INT21_VECTOR + dw _int21_dispatch, HEX (0000) _interrupts_list_end: diff --git a/src/boot/freeldr/core/int21.asm b/src/boot/freeldr/core/int21.asm index 0e5c2c6..4259003 100644 --- a/src/boot/freeldr/core/int21.asm +++ b/src/boot/freeldr/core/int21.asm @@ -5,6 +5,450 @@ % define HEX(y) 0x##y %endif +;****************************************************************************** +; @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 + push ds + + xor si, si + mov ds, ax + + lodsw + + lodsw + mov cs:[_sectors_per_fat32], ax + + lodsw + mov cs:[_sectors_per_fat32 + 2], ax + + lodsw + mov cs:[_disk_scratch], ax + + mov di, offset _fat_bpb + push es + + mov ax, cs + mov es, ax + + mov cx, 25 + rep movsb + + pop es + + 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 + + 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], 0 + mov word ptr cs:[_fat_sector + 2], 0 + + 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: + + 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 ;****************************************************************************** @@ -111,37 +555,19 @@ _int21_dispatch.list: ;; Open File Using Handle. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; db HEX (3D) - dw int21_3D + dw _int21_3D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Close File Using Handle. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; db HEX (3E) - dw int21_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 + dw _int21_3F _int21_dispatch.list_end: @@ -169,7 +595,7 @@ iretc.ret: ;****************************************************************************** -; @function int21_3D +; @function _int21_3D ; @brief Open File Using Handle ; ; @in AL -> Open access mode. @@ -177,25 +603,64 @@ iretc.ret: ; ; @out AX -> File handle. Error code if CF is set. ;****************************************************************************** -int21_3D: +_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 +; @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: +_int21_3E: call _close_file jmp iretc ;****************************************************************************** -; @function int21_3F +; @function _int21_3F ; @brief Read From File or Device Using Handle ; ; @in BX -> File handle.. @@ -204,52 +669,180 @@ int21_3E: ; ; @out AX -> Number of bytes read. Error code if CF is set. ;****************************************************************************** -int21_3F: +_int21_3F: - call _read_file - jmp iretc + 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] -;****************************************************************************** -; @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: +_int21_3F.copy: - call _alloc_mem - jmp iretc + push si + push ds + push ax + push cx + + mov ds, ax + xor si, si + + lodsw + mov cs:[_sectors_per_fat32], ax + + lodsw + mov cs:[_sectors_per_fat32 + 2], ax + + mov di, offset _fat_bpb + mov ax, cs + mov es, ax + + mov cx, 25 + rep movsb + + lodsb + mov cs:[_drive_no], al + + lodsw + mov cs:[_root_cluster], ax + + lodsw + mov cs:[_root_cluster + 2], ax + + lodsw + mov cs:[_fat_start], ax + + lodsw + mov cs:[_fat_start + 2], ax + + lodsw + mov cs:[_root_start], ax + + lodsw + mov cs:[_root_start + 2], ax + + lodsw + mov cs:[_data_start], ax + + lodsw + mov cs:[_data_start + 2], ax + + lodsw + mov cs:[_fat_secmask], ax + + lodsw + mov cs:[_fat_secshift], ax + + lodsw + mov cs:[_clustsize], ax + + lodsw + ;mov cs:[_info_sector], ax + + mov bx, cs:[_root_cluster] + mov cx, cs:[_root_cluster + 2] + + or bx, cx + + and bx, bx + jnz _int21_3F.fat32 + + call _getfattype + jmp _int21_3F.read -;****************************************************************************** -; @function int21_49 -; @brief Free Allocated Memeory Blocks -; -; @in ES -> Segment of the block to be returned (MCB + lpara). -; @out AX -> Clear. -;****************************************************************************** -int21_49: +_int21_3F.fat32: - call _free_mem - jmp iretc + mov ax, offset _convert_cluster32 + mov cs:[_convert_cluster], ax + + mov ax, offset _nextcluster_fat32 + mov cs:[_next_cluster], ax -;****************************************************************************** -; @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: +_int21_3F.read: + + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 + + pop cx + 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 - call _resize_mem +_int21_3F.done: + + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop bp + jmp iretc diff --git a/src/boot/freeldr/core/invalid.asm b/src/boot/freeldr/core/invalid.asm new file mode 100644 index 0000000..cbe419f --- /dev/null +++ b/src/boot/freeldr/core/invalid.asm @@ -0,0 +1,125 @@ +;****************************************************************************** +; @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 + +_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 + +_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) diff --git a/src/boot/freeldr/core/xmalloc.asm b/src/boot/freeldr/core/xmalloc.asm index cb56c1e..9734782 100644 --- a/src/boot/freeldr/core/xmalloc.asm +++ b/src/boot/freeldr/core/xmalloc.asm @@ -30,14 +30,30 @@ _xmalloc: mov dx, [bp + 4] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Call malloc. + ;; Convert the size to paragraphs. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - push ax - push dx + mov cx, 16 + div cx - call _malloc - add sp, 4 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; If dx is non-zero then try to increase the count. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + cmp dx, 0 + je _xmalloc.ok + +_xmalloc.inc: + + inc ax + jz _xmalloc.error + +_xmalloc.ok: + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Try and allocate the memory. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov bx, ax + call _alloc_mem jc _xmalloc.error push ax @@ -115,4 +131,4 @@ _xmalloc.error: ;; so just error out. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; call _error - db "Memory full (malloc)", HEX (0D), HEX (0A), HEX (00) + db "panic: failed to alloc memory in xmalloc", HEX (0D), HEX (0A), HEX (00) diff --git a/src/boot/freeldr/core/xrealloc.asm b/src/boot/freeldr/core/xrealloc.asm index 1443176..4785504 100644 --- a/src/boot/freeldr/core/xrealloc.asm +++ b/src/boot/freeldr/core/xrealloc.asm @@ -29,21 +29,159 @@ _xrealloc: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ax, [bp + 8] mov dx, [bp + 6] - mov si, [bp + 4] + mov bx, [bp + 4] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Call realloc. + ;; Make sure we have valid memory as a pointer. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - push ax - push dx - push si + and bx, bx + jz _xrealloc.calc + + mov di, bx + dec di + mov es, di + + xor di, di - call _realloc - add sp, 6 + cmp byte ptr es:[di], 'M' + jne _xrealloc.error - and ax, ax + cmp byte ptr es:[di + 1], 'C' + jne _xrealloc.error + + cmp byte ptr es:[di + 2], 'B' + jne _xrealloc.error + +_xrealloc.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 _xrealloc.ok + +_xrealloc.inc: + + inc ax jz _xrealloc.error +_xrealloc.ok: + + mov si, ax + + and bx, bx + jz _xrealloc.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 _xrealloc.done + +_xrealloc.alloc: + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Try and allocate the memory. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + push bx + + mov bx, si + call _alloc_mem + + pop bx + jc _xrealloc.error + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Only copy existing data if there was an original pointer. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov di, bx + + and di, di + jz _xrealloc.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 _xrealloc.copy + + mov cx, bx + +_xrealloc.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 _xrealloc.copy + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Restore registers that copy clobbered. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + pop ds + pop si + +_xrealloc.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 + _xrealloc.done: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -91,4 +229,4 @@ _xrealloc.error: ;; so just error out. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; call _error - db "Memory full (realloc)", HEX (0D), HEX (0A), HEX (00) + db "panic: failed to alloc memory in krealloc", HEX (0D), HEX (0A), HEX (00) diff --git a/src/boot/freeldr/freeldr.cfg b/src/boot/freeldr/freeldr.cfg index 2cf568e..ee79cff 100644 --- a/src/boot/freeldr/freeldr.cfg +++ b/src/boot/freeldr/freeldr.cfg @@ -1,6 +1,5 @@ default chimaera -#timeout 10 -timeout 0 +timeout 10 label chimaera title Chimaera OS diff --git a/src/boot/freeldr/lib/Makefile.unix b/src/boot/freeldr/lib/Makefile.unix new file mode 100644 index 0000000..a477ba8 --- /dev/null +++ b/src/boot/freeldr/lib/Makefile.unix @@ -0,0 +1,20 @@ +#****************************************************************************** +# @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 diff --git a/src/boot/freeldr/lib/Makefile.w32 b/src/boot/freeldr/lib/Makefile.w32 new file mode 100644 index 0000000..08f1adf --- /dev/null +++ b/src/boot/freeldr/lib/Makefile.w32 @@ -0,0 +1,20 @@ +#****************************************************************************** +# @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 \ + ) \ + ) diff --git a/src/boot/freeldr/lib/crt/Makefile.unix b/src/boot/freeldr/lib/crt/Makefile.unix new file mode 100644 index 0000000..5617cda --- /dev/null +++ b/src/boot/freeldr/lib/crt/Makefile.unix @@ -0,0 +1,25 @@ +#****************************************************************************** +# @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: 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 $@ $< diff --git a/src/boot/freeldr/lib/crt/Makefile.w32 b/src/boot/freeldr/lib/crt/Makefile.w32 new file mode 100644 index 0000000..bc7ba91 --- /dev/null +++ b/src/boot/freeldr/lib/crt/Makefile.w32 @@ -0,0 +1,25 @@ +#****************************************************************************** +# @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: 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 $@ $< diff --git a/src/boot/freeldr/lib/crt/ctype.asm b/src/boot/freeldr/lib/crt/ctype.asm new file mode 100644 index 0000000..2bb0937 --- /dev/null +++ b/src/boot/freeldr/lib/crt/ctype.asm @@ -0,0 +1,1988 @@ +;****************************************************************************** +; @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) diff --git a/src/boot/freeldr/libc/stdio/fclose.asm b/src/boot/freeldr/lib/crt/stdio/fclose.asm similarity index 100% rename from src/boot/freeldr/libc/stdio/fclose.asm rename to src/boot/freeldr/lib/crt/stdio/fclose.asm diff --git a/src/boot/freeldr/libc/stdio/feof.asm b/src/boot/freeldr/lib/crt/stdio/feof.asm similarity index 100% rename from src/boot/freeldr/libc/stdio/feof.asm rename to src/boot/freeldr/lib/crt/stdio/feof.asm diff --git a/src/boot/freeldr/libc/stdio/fopen.asm b/src/boot/freeldr/lib/crt/stdio/fopen.asm similarity index 100% rename from src/boot/freeldr/libc/stdio/fopen.asm rename to src/boot/freeldr/lib/crt/stdio/fopen.asm diff --git a/src/boot/freeldr/libc/stdio/fread.asm b/src/boot/freeldr/lib/crt/stdio/fread.asm similarity index 100% rename from src/boot/freeldr/libc/stdio/fread.asm rename to src/boot/freeldr/lib/crt/stdio/fread.asm diff --git a/src/boot/freeldr/libc/string/memmove.asm b/src/boot/freeldr/lib/crt/string/memmove.asm similarity index 100% rename from src/boot/freeldr/libc/string/memmove.asm rename to src/boot/freeldr/lib/crt/string/memmove.asm diff --git a/src/boot/freeldr/libc/string/strlen.asm b/src/boot/freeldr/lib/crt/string/strlen.asm similarity index 100% rename from src/boot/freeldr/libc/string/strlen.asm rename to src/boot/freeldr/lib/crt/string/strlen.asm diff --git a/src/boot/freeldr/libc/Makefile.unix b/src/boot/freeldr/libc/Makefile.unix deleted file mode 100644 index b3b5803..0000000 --- a/src/boot/freeldr/libc/Makefile.unix +++ /dev/null @@ -1,35 +0,0 @@ -#****************************************************************************** -# @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 $@ $< diff --git a/src/boot/freeldr/libc/Makefile.w32 b/src/boot/freeldr/libc/Makefile.w32 deleted file mode 100644 index d4f502c..0000000 --- a/src/boot/freeldr/libc/Makefile.w32 +++ /dev/null @@ -1,35 +0,0 @@ -#****************************************************************************** -# @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 $@ $< diff --git a/src/boot/freeldr/libc/stdlib/malloc.asm b/src/boot/freeldr/libc/stdlib/malloc.asm deleted file mode 100644 index bebd0ec..0000000 --- a/src/boot/freeldr/libc/stdlib/malloc.asm +++ /dev/null @@ -1,90 +0,0 @@ -;****************************************************************************** -; @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 diff --git a/src/boot/freeldr/libc/stdlib/realloc.asm b/src/boot/freeldr/libc/stdlib/realloc.asm deleted file mode 100644 index 2e43b97..0000000 --- a/src/boot/freeldr/libc/stdlib/realloc.asm +++ /dev/null @@ -1,233 +0,0 @@ -;****************************************************************************** -; @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 diff --git a/src/kernel/disk.asm b/src/kernel/disk.asm index ded082d..56ab33c 100644 --- a/src/kernel/disk.asm +++ b/src/kernel/disk.asm @@ -543,15 +543,17 @@ _get_partition_info: add sp, 26 clc - jmp .L20 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Restore the base pointer and return to caller. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + pop bp + ret .L22: add sp, 26 stc - -.L20: - + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Restore the base pointer and return to caller. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -634,17 +636,17 @@ _get_hard_disk_partitions: push ax call _get_partition_info + jnc .L20 + add sp, 4 and ax, ax jz .L15 - jnc .L16 - mov es, ax xor bx, bx - cmp es:[bx + 29], dl + cmp es:[bx + 33], dl jne .L16 .L17: @@ -659,6 +661,10 @@ _get_hard_disk_partitions: jmp .L15 +.L20: + + add sp, 4 + .L16: push ds diff --git a/src/kernel/divide.asm b/src/kernel/divide.asm index 0018abf..447935a 100644 --- a/src/kernel/divide.asm +++ b/src/kernel/divide.asm @@ -60,189 +60,65 @@ _divide_handler.init: 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. + ;; Zero out the si register. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - 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 + xor si, si + +_divide_handler.loop: + + cmp si, 12 * 2 + jae _divide_handler.done - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Print the stack and base pointers. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax, word ptr [bp + 2] - add ax, 3 * 2 ; return address, offset, segment. - call _writehex + mov ax, si + xor dx, dx - mov al, ' ' - call _writechr - call _writechr - call _writechr - call _writechr + mov cx, 12 + div cx - mov ax, word ptr [bp] - call _writehex + and dx, dx + jnz _divide_handler.print - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; 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 + +_divide_handler.print: + + mov ax, word ptr [bp + si] call _writehex - mov al, ' ' - call _writechr - call _writechr - call _writechr - call _writechr + inc si + inc si - pop ax - call _writehex + mov ax, si + xor dx, dx - mov al, ' ' - call _writechr - call _writechr - call _writechr - call _writechr + mov cx, 12 + div cx - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; Get the value of bx off the stack and print it. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - pop ax - call _writehex + and dx, dx + jz _divide_handler.loop - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; 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 - + jmp _divide_handler.loop + +_divide_handler.done: + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Print a newline. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -272,4 +148,4 @@ _divide_handler.reboot: _divide_handler.msg: - db "Trap to vector 0: Divide overflow at ", HEX (00) + db "Trap to vector 0: Divide overflow", HEX (00) diff --git a/src/kernel/kernel.asm b/src/kernel/kernel.asm index 70afdd2..2f8689b 100644 --- a/src/kernel/kernel.asm +++ b/src/kernel/kernel.asm @@ -401,7 +401,7 @@ _check_disks: ;; Decrement cx and loop back for next drive. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dec cx - jmp .L10 + jnz .L10 .L13: @@ -463,11 +463,20 @@ _check_disks: .L11: cmp byte ptr ss:[bx + 0], HEX (EB) - jne .L10 + jne .L15 cmp byte ptr ss:[bx + 2], HEX (90) - jne .L10 + jne .L15 + jmp .L18 + +.L15: + + call _error + db "panic: seleteced disk does not have a valid/supported parition", HEX (0D), HEX (0A), HEX (00) + +.L18: + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Next we'll copy the BPB to our "structure". ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -- 2.34.1