From: Svjatoslav Agejenko Date: Fri, 20 Feb 2026 16:23:46 +0000 (+0200) Subject: Rename and migrate all `.inc` files to `.asm`: updated references. X-Git-Url: http://www2.svjatoslav.eu/gitweb/?a=commitdiff_plain;h=a8be3a6dec415d8c3b75d21274cdc91492b567ff;p=fifth.git Rename and migrate all `.inc` files to `.asm`: updated references. --- diff --git a/AGENTS.md b/AGENTS.md index 9dc5702..cfc4e11 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,11 +21,11 @@ editor, and a graphics editor. the build tools handle FSCII conversion. 3. *Two different assembly languages exist in this project:* - - =kernel/core.asm= and =kernel/define.inc= use the *virtual CPU's - own instruction set* (NOT x86). See the "Virtual CPU Instruction - Set" section below. - - =emulator/emulator.asm= and its =.inc= files are *x86 real-mode - DOS assembly* for FASM (Flat Assembler). + - =kernel/core.asm= and =kernel/define.asm= use + the *virtual CPU's* own instruction set (NOT x86). See the + "Virtual CPU Instruction Set" section below. + - =emulator/emulator.asm= and related =*.asm= files under emulator/ directory + are *x86 real-mode* DOS assembly for FASM (Flat Assembler). 4. *Binary files* (=.raw=, =.com=, =.dat=, =FNT_SYSTEM=, =I01_MCARROW=, =core.raw=, =emulator.com=) are compiled outputs @@ -57,17 +57,22 @@ editor, and a graphics editor. | =kernel/font.asm= | 8×8 bitmap font data (256 characters) | | =kernel/core.raw= | Compiled kernel binary (do not edit) | -## Emulator (x86 real-mode FASM assembly) -| File | Description | -|-------------------------|--------------------------------------------| -| =emulator/emulator.asm= | Main emulator: instruction dispatch loop | -| =emulator/system.inc= | XMS allocation, protected mode, A20 gate | -| =emulator/vidput.inc= | Image-to-image blit (opaque) | -| =emulator/tvidput.inc= | Image-to-image blit (transparent, FF=skip) | -| =emulator/charput.inc= | Character glyph rendering to image buffer | -| =emulator/kbdrive.inc= | Keyboard interrupt handler + ring buffer | -| =emulator/compile.sh= | Build script (runs =fasm emulator.asm=) | -| =emulator/emulator.com= | Compiled DOS COM binary (do not edit) | + ## Emulator (x86 real-mode FASM assembly) + | File | Description | + |------------------------------|-----------------------------------------------------------------| + | =emulator/emulator.asm= | Main emulator: instruction dispatch loop | + | =emulator/system.asm= | XMS allocation, protected mode, A20 gate | + | =emulator/kbdrive.asm= | Keyboard interrupt handler + ring buffer | + | =emulator/vidput.asm= | Image-to-image blit (opaque) | + | =emulator/tvidput.asm= | Image-to-image blit (with transparency support, FF=transparent) | + | =emulator/charput.asm= | Character glyph rendering to image buffer | + | =emulator/opcodes_00_09.asm= | Implementation for virtual machine opcodes 0-9. | + | =emulator/opcodes_10_19.asm= | Implementation for virtual machine opcodes 10-19. | + | =emulator/opcodes_20_29.asm= | Implementation for virtual machine opcodes 20-29. | + | =emulator/opcodes_30_39.asm= | Implementation for virtual machine opcodes 30-39. | + | =emulator/opcodes_40_49.asm= | Implementation for virtual machine opcodes 40-49. | + | =emulator/compile.sh= | Emulator build script | + | =emulator/emulator.com= | Compiled DOS COM binary (do not edit) | ## High-Level Boot Code (Fifth language) diff --git a/emulator/charput.asm b/emulator/charput.asm new file mode 100644 index 0000000..050df56 --- /dev/null +++ b/emulator/charput.asm @@ -0,0 +1,102 @@ +; Draw character +; +; Stack Effect: colorfg colorbg addrsrc addrdest x y -- +; +; Draws an 8x8 character from a source memory buffer to a destination +; image buffer at the specified (x, y) coordinates. Each byte in the +; source buffer represents one row of the character (8 bits per row), +; where each bit determines whether to use the foreground or background +; color for that pixel. +; +; Parameters: +; - colorfg: Foreground color value (0-255) +; - colorbg: Background color value (0-255) +; - addrsrc: Memory address pointing to 8 bytes of character data +; - addrdest: Base address of the destination image buffer +; - x: X-coordinate (0-based) where the character's left edge starts +; - y: Y-coordinate (0-based) where the character's top edge starts +; +; Example: +; 0xFF ; White foreground +; 0x00 ; Black background +; 0x3000 ; Character data address +; 0x5000 ; Video memory address +; 20 ; y +; 10 ; x +; charput +; +; Memory layout before execution: +; [es:edi] = y +; [es:edi+4] = x +; [es:edi+8] = addrdest +; [es:edi+12] = addrsrc +; [es:edi+16] = colorbg +; [es:edi+20] = colorfg +; +; Memory layout after execution: +; Character drawn at (x, y) in destination image + +op_47_xcharput: + mov eax, [es:edi] ; eax = y coordinate (top of stack) + mov [chary], eax ; store y coordinate + mov ecx, [es:edi+4] ; ecx = x coordinate (second on stack) + mov eax, [es:edi+8] ; eax = addrdest (destination image virtual address) + add eax, [xms_addr] ; convert virtual address to physical address + mov ebx, [es:eax] ; ebx = destination image width from image header + mov [sizex], ebx ; store destination image width (stride) + add eax, 8 ; skip past image header (width + height = 8 bytes) + add eax, ecx ; add x offset to base of pixel data + push eax ; save partial destination address on x86 stack + sub edx, edx ; clear edx for multiplication + mov eax, [chary] ; eax = y coordinate + mul dword [sizex] ; eax = y * image width (row offset in bytes) + pop ebx ; ebx = base + x offset + add eax, ebx ; eax = final destination pixel address + mov [addrdst], eax ; store destination address for character drawing + mov eax, [es:edi+12] ; eax = addrsrc (source font data virtual address) + add eax, [xms_addr] ; convert virtual address to physical address + mov [addrsrc], eax ; store source font data address + mov al, [es:edi+16] ; al = background color value + mov [colorbg], al ; store background color + mov al, [es:edi+20] ; al = foreground color value + mov [colorfg], al ; store foreground color + add edi, 24 ; pop all six arguments off the data stack + + mov [linenum], 8 ; linenum = 8 (number of rows in character glyph) +charl1: + mov eax, [addrsrc] ; eax = current source font data address + mov bx, [es:eax] ; bx = current row bitmap (8 bits used) + mov edx, [addrdst] ; edx = current destination pixel address + mov cx, 8 ; cx = 8 (number of pixels per row) +charl2: + dec cx ; decrement bit index (process bits 7 down to 0) + bt bx, cx ; test bit cx of the row bitmap + jnc charl3 ; if bit is 0 (clear), use background color + mov al, [colorfg] ; bit is 1 (set): al = foreground color + jmp charl4 ; skip to pixel write +charl3: + mov al, [colorbg] ; bit is 0 (clear): al = background color +charl4: + mov [es:edx], al ; write pixel color to destination + inc edx ; advance destination to next pixel (next column) + cmp cx, 0 ; check if all 8 pixels in this row are done + jne charl2 ; if not, process next pixel + + mov eax, [sizex] ; eax = image width (stride) + add [addrdst], eax ; advance destination to next row + inc [addrsrc] ; advance source to next byte (next row bitmap) + dec [linenum] ; decrement remaining line count + mov al, [linenum] ; al = remaining lines + cmp al, 0 ; check if all 8 rows are done + jne charl1 ; if not, draw next row + + jmp emu ; return to emulation loop + +colorfg db 0 +colorbg db 0 +charx dd 0 +chary dd 0 +addrsrc dd 0 +addrdst dd 0 +sizex dd 0 +linenum db 0 diff --git a/emulator/charput.inc b/emulator/charput.inc deleted file mode 100644 index 050df56..0000000 --- a/emulator/charput.inc +++ /dev/null @@ -1,102 +0,0 @@ -; Draw character -; -; Stack Effect: colorfg colorbg addrsrc addrdest x y -- -; -; Draws an 8x8 character from a source memory buffer to a destination -; image buffer at the specified (x, y) coordinates. Each byte in the -; source buffer represents one row of the character (8 bits per row), -; where each bit determines whether to use the foreground or background -; color for that pixel. -; -; Parameters: -; - colorfg: Foreground color value (0-255) -; - colorbg: Background color value (0-255) -; - addrsrc: Memory address pointing to 8 bytes of character data -; - addrdest: Base address of the destination image buffer -; - x: X-coordinate (0-based) where the character's left edge starts -; - y: Y-coordinate (0-based) where the character's top edge starts -; -; Example: -; 0xFF ; White foreground -; 0x00 ; Black background -; 0x3000 ; Character data address -; 0x5000 ; Video memory address -; 20 ; y -; 10 ; x -; charput -; -; Memory layout before execution: -; [es:edi] = y -; [es:edi+4] = x -; [es:edi+8] = addrdest -; [es:edi+12] = addrsrc -; [es:edi+16] = colorbg -; [es:edi+20] = colorfg -; -; Memory layout after execution: -; Character drawn at (x, y) in destination image - -op_47_xcharput: - mov eax, [es:edi] ; eax = y coordinate (top of stack) - mov [chary], eax ; store y coordinate - mov ecx, [es:edi+4] ; ecx = x coordinate (second on stack) - mov eax, [es:edi+8] ; eax = addrdest (destination image virtual address) - add eax, [xms_addr] ; convert virtual address to physical address - mov ebx, [es:eax] ; ebx = destination image width from image header - mov [sizex], ebx ; store destination image width (stride) - add eax, 8 ; skip past image header (width + height = 8 bytes) - add eax, ecx ; add x offset to base of pixel data - push eax ; save partial destination address on x86 stack - sub edx, edx ; clear edx for multiplication - mov eax, [chary] ; eax = y coordinate - mul dword [sizex] ; eax = y * image width (row offset in bytes) - pop ebx ; ebx = base + x offset - add eax, ebx ; eax = final destination pixel address - mov [addrdst], eax ; store destination address for character drawing - mov eax, [es:edi+12] ; eax = addrsrc (source font data virtual address) - add eax, [xms_addr] ; convert virtual address to physical address - mov [addrsrc], eax ; store source font data address - mov al, [es:edi+16] ; al = background color value - mov [colorbg], al ; store background color - mov al, [es:edi+20] ; al = foreground color value - mov [colorfg], al ; store foreground color - add edi, 24 ; pop all six arguments off the data stack - - mov [linenum], 8 ; linenum = 8 (number of rows in character glyph) -charl1: - mov eax, [addrsrc] ; eax = current source font data address - mov bx, [es:eax] ; bx = current row bitmap (8 bits used) - mov edx, [addrdst] ; edx = current destination pixel address - mov cx, 8 ; cx = 8 (number of pixels per row) -charl2: - dec cx ; decrement bit index (process bits 7 down to 0) - bt bx, cx ; test bit cx of the row bitmap - jnc charl3 ; if bit is 0 (clear), use background color - mov al, [colorfg] ; bit is 1 (set): al = foreground color - jmp charl4 ; skip to pixel write -charl3: - mov al, [colorbg] ; bit is 0 (clear): al = background color -charl4: - mov [es:edx], al ; write pixel color to destination - inc edx ; advance destination to next pixel (next column) - cmp cx, 0 ; check if all 8 pixels in this row are done - jne charl2 ; if not, process next pixel - - mov eax, [sizex] ; eax = image width (stride) - add [addrdst], eax ; advance destination to next row - inc [addrsrc] ; advance source to next byte (next row bitmap) - dec [linenum] ; decrement remaining line count - mov al, [linenum] ; al = remaining lines - cmp al, 0 ; check if all 8 rows are done - jne charl1 ; if not, draw next row - - jmp emu ; return to emulation loop - -colorfg db 0 -colorbg db 0 -charx dd 0 -chary dd 0 -addrsrc dd 0 -addrdst dd 0 -sizex dd 0 -linenum db 0 diff --git a/emulator/emulator.asm b/emulator/emulator.asm index 6185e1c..bcacad2 100644 --- a/emulator/emulator.asm +++ b/emulator/emulator.asm @@ -126,11 +126,11 @@ table: dw op_47_xcharput ; 47 - render character glyph -include 'opcodes_00_09.inc' -include 'opcodes_10_19.inc' -include 'opcodes_20_29.inc' -include 'opcodes_30_39.inc' -include 'opcodes_40_47.inc' +include 'opcodes_00_09.asm' +include 'opcodes_10_19.asm' +include 'opcodes_20_29.asm' +include 'opcodes_30_39.asm' +include 'opcodes_40_49.asm' file_seek: ; ( ecx - pointer to seek ) mov eax, 1024 @@ -186,7 +186,7 @@ diskload: ; ecx-fromdisk ebx-tomem call memmove ; ebx - from, edx - to, ecx - amount ret -include 'system.inc' -include 'kbdrive.inc' +include 'system.asm' +include 'kbdrive.asm' buf: ; pointer to end of the code diff --git a/emulator/kbdrive.asm b/emulator/kbdrive.asm new file mode 100644 index 0000000..9291131 --- /dev/null +++ b/emulator/kbdrive.asm @@ -0,0 +1,83 @@ +; Keyboard driver routines + +; KB_init +; +; Initializes the keyboard interrupt handler. +; Saves the old interrupt vector for INT 9h and sets up the new handler. +; +; Notes: +; - INT 9h is the keyboard interrupt vector. +; - The handler stores scan codes in a circular buffer. + +KB_init: + push es + push 0 + pop es + mov eax, [es:9*4] ; save old int vector + mov [KB_OldVect], eax + mov ax, cs ; set new int vector + shl eax, 16 + mov ax, KB_IntHandler + mov [es:9*4], eax + pop es + ret + +; KB_restore +; +; Restores the original keyboard interrupt handler. +; Used when exiting the emulator to restore the system's default handler. + +KB_restore: + mov eax, [KB_OldVect] + push es + push 0 + pop es + mov [es:9*4], eax + pop es + ret + +; KB_IntHandler +; +; Keyboard interrupt handler. +; Reads scan code from port 60h and stores it in the circular buffer. +; Then calls the original interrupt handler. + +KB_IntHandler: + pusha + in al, 60h + mov bx, [cs:KB_pntin] + mov byte [cs:bx+KB_buf], al + inc bx + cmp bx, 128 + jng KB_l1 + mov bx, 0 +KB_l1: mov [cs:KB_pntin], bx + popa + pushf ; Execute default code in old int vector + call dword [cs:KB_OldVect] + iret + +; KB_read +; +; Reads a scan code from the keyboard buffer. +; Returns the scan code in DL. +; If buffer is empty, returns 0. + +KB_read: ; returns scan code in: dl + mov dl, 0 + mov bx, [KB_pntout] + cmp bx, [KB_pntin] + je KB_l2 + mov dl, [bx+KB_buf] + inc bx + cmp bx, 128 + jng KB_l3 + mov bx, 0 +KB_l3: mov [KB_pntout], bx +KB_l2: ret + +KB_OldVect dd 0 +KB_pntin dw 0 +KB_pntout dw 0 +KB_buf db 0 +times 127 db 0 diff --git a/emulator/kbdrive.inc b/emulator/kbdrive.inc deleted file mode 100644 index 9291131..0000000 --- a/emulator/kbdrive.inc +++ /dev/null @@ -1,83 +0,0 @@ -; Keyboard driver routines - -; KB_init -; -; Initializes the keyboard interrupt handler. -; Saves the old interrupt vector for INT 9h and sets up the new handler. -; -; Notes: -; - INT 9h is the keyboard interrupt vector. -; - The handler stores scan codes in a circular buffer. - -KB_init: - push es - push 0 - pop es - mov eax, [es:9*4] ; save old int vector - mov [KB_OldVect], eax - mov ax, cs ; set new int vector - shl eax, 16 - mov ax, KB_IntHandler - mov [es:9*4], eax - pop es - ret - -; KB_restore -; -; Restores the original keyboard interrupt handler. -; Used when exiting the emulator to restore the system's default handler. - -KB_restore: - mov eax, [KB_OldVect] - push es - push 0 - pop es - mov [es:9*4], eax - pop es - ret - -; KB_IntHandler -; -; Keyboard interrupt handler. -; Reads scan code from port 60h and stores it in the circular buffer. -; Then calls the original interrupt handler. - -KB_IntHandler: - pusha - in al, 60h - mov bx, [cs:KB_pntin] - mov byte [cs:bx+KB_buf], al - inc bx - cmp bx, 128 - jng KB_l1 - mov bx, 0 -KB_l1: mov [cs:KB_pntin], bx - popa - pushf ; Execute default code in old int vector - call dword [cs:KB_OldVect] - iret - -; KB_read -; -; Reads a scan code from the keyboard buffer. -; Returns the scan code in DL. -; If buffer is empty, returns 0. - -KB_read: ; returns scan code in: dl - mov dl, 0 - mov bx, [KB_pntout] - cmp bx, [KB_pntin] - je KB_l2 - mov dl, [bx+KB_buf] - inc bx - cmp bx, 128 - jng KB_l3 - mov bx, 0 -KB_l3: mov [KB_pntout], bx -KB_l2: ret - -KB_OldVect dd 0 -KB_pntin dw 0 -KB_pntout dw 0 -KB_buf db 0 -times 127 db 0 diff --git a/emulator/opcodes_00_09.asm b/emulator/opcodes_00_09.asm new file mode 100644 index 0000000..eadc940 --- /dev/null +++ b/emulator/opcodes_00_09.asm @@ -0,0 +1,89 @@ +; Opcodes 0-9: nop, halt, kbd@, num, jmp, call, inc, dec, dup, drop +; Opcode 0 (xnop) is handled inline as the emu loop entry point. +; Opcode 1 (xhalt/quit) is handled in the main emulator file. + +op_02_kbd@: ; Read Keyboard: ( -- scancode ) + call KB_read ; read scancode from keyboard ring buffer into dl + sub edi, 4 ; make room on data stack for one element + mov [es:edi], dl ; push scancode onto data stack + + mov ah, 0bh ; DOS: check if key waiting in keyboard buffer + int 21h ; call DOS interrupt + cmp al, 0h ; al=0 means no key waiting + je emu ; if no key waiting, return to emulation loop + mov ah, 0 ; BIOS: read key from keyboard buffer + int 16h ; call BIOS interrupt (consume the key) + jmp emu ; return to emulation loop + +op_03_xnum: ; Push Literal: ( -- n ) + mov edx, dword [es:esi] ; read 32-bit literal from instruction stream + sub edi, 4 ; make room on data stack for one element + mov [es:edi], edx ; push the literal value onto data stack + add esi, 4 ; advance instruction pointer past the 32-bit literal + jmp emu ; return to emulation loop + +op_04_xjmp: ; Unconditional Jump: ( -- ) + mov esi, dword [es:esi] ; read 32-bit target address from instruction stream + add esi, [xms_addr] ; convert virtual address to physical address + jmp emu ; return to emulation loop + +op_05_xcall: ; Call Subroutine: ( -- ) R:( -- ret-addr ) + mov edx, dword [es:esi] ; read 32-bit target address from instruction stream + mov eax, [resp] ; load return stack pointer + sub eax, 4 ; make room on return stack for one element + mov ebx, esi ; copy current instruction pointer + add ebx, 4 ; advance past the 32-bit argument (return address) + sub ebx, [xms_addr] ; convert physical address to virtual address + mov [es:eax], ebx ; push return address onto return stack + mov [resp], eax ; store updated return stack pointer + mov esi, edx ; set instruction pointer to target address + add esi, [xms_addr] ; convert virtual address to physical address + jmp emu ; return to emulation loop + +op_06_xinc: ; Increment: ( n -- n+1 ) +; Increments the top of the data stack by 1. + + inc dword [es:edi] ; increment the top of the data stack in place + jmp emu ; return to emulation loop + +op_07_xdec: ; Decrement: ( n -- n-1 ) +; +; Decrements the top of the data stack by 1. +; +; Memory layout before execution: +; [es:edi] = n +; +; Memory layout after execution: +; [es:edi] = n-1 + + dec dword [es:edi] ; decrement the top of the data stack in place + jmp emu ; return to emulation loop + +op_08_xdup: ; Duplicate: ( n -- n n ) +; +; Duplicates the top element of the data stack. +; +; Memory layout before execution: +; [es:edi] = n +; +; Memory layout after execution: +; [es:edi] = n (new top) +; [es:edi+4] = n (original top) + + mov eax, [es:edi] ; copy top element to eax + sub edi, 4 ; make room on data stack for one element + mov [es:edi], eax ; push copy of top element onto stack + jmp emu ; return to emulation loop + +op_09_xdrop: ; Drop: ( n -- ) +; +; Removes the top element from the data stack. +; +; Memory layout before execution: +; [es:edi] = n +; +; Memory layout after execution: +; Stack pointer is adjusted; n is no longer on stack + + add edi, 4 ; pop top element off the stack + jmp emu ; return to emulation loop diff --git a/emulator/opcodes_00_09.inc b/emulator/opcodes_00_09.inc deleted file mode 100644 index d7a721c..0000000 --- a/emulator/opcodes_00_09.inc +++ /dev/null @@ -1,89 +0,0 @@ -; Opcodes 0-9: nop, halt, kbd@, num, jmp, call, inc, dec, dup, drop -; Opcode 0 (xnop) is handled inline as the emu loop entry point. -; Opcode 1 (xhalt/quit) is handled in the main emulator file. - -op_02_kbd@: ; Read Keyboard: ( -- scancode ) - call KB_read ; read scancode from keyboard ring buffer into dl - sub edi, 4 ; make room on data stack for one element - mov [es:edi], dl ; push scancode onto data stack - - mov ah, 0bh ; DOS: check if key waiting in keyboard buffer - int 21h ; call DOS interrupt - cmp al, 0h ; al=0 means no key waiting - je emu ; if no key waiting, return to emulation loop - mov ah, 0 ; BIOS: read key from keyboard buffer - int 16h ; call BIOS interrupt (consume the key) - jmp emu ; return to emulation loop - -op_03_xnum: ; Push Literal: ( -- n ) - mov edx, dword [es:esi] ; read 32-bit literal from instruction stream - sub edi, 4 ; make room on data stack for one element - mov [es:edi], edx ; push the literal value onto data stack - add esi, 4 ; advance instruction pointer past the 32-bit literal - jmp emu ; return to emulation loop - -op_04_xjmp: ; Unconditional Jump: ( -- ) - mov esi, dword [es:esi] ; read 32-bit target address from instruction stream - add e si, [xms_addr] ; convert virtual address to physical address - jmp emu ; return to emulation loop - -op_05_xcall: ; Call Subroutine: ( -- ) R:( -- ret-addr ) - mov edx, dword [es:esi] ; read 32-bit target address from instruction stream - mov eax, [resp] ; load return stack pointer - sub eax, 4 ; make room on return stack for one element - mov ebx, esi ; copy current instruction pointer - add ebx, 4 ; advance past the 32-bit argument (return address) - sub ebx, [xms_addr] ; convert physical address to virtual address - mov [es:eax], ebx ; push return address onto return stack - mov [resp], eax ; store updated return stack pointer - mov esi, edx ; set instruction pointer to target address - add esi, [xms_addr] ; convert virtual address to physical address - jmp emu ; return to emulation loop - -op_06_xinc: ; Increment: ( n -- n+1 ) -; Increments the top of the data stack by 1. - - inc dword [es:edi] ; increment the top of the data stack in place - jmp emu ; return to emulation loop - -op_07_xdec: ; Decrement: ( n -- n-1 ) -; -; Decrements the top of the data stack by 1. -; -; Memory layout before execution: -; [es:edi] = n -; -; Memory layout after execution: -; [es:edi] = n-1 - - dec dword [es:edi] ; decrement the top of the data stack in place - jmp emu ; return to emulation loop - -op_08_xdup: ; Duplicate: ( n -- n n ) -; -; Duplicates the top element of the data stack. -; -; Memory layout before execution: -; [es:edi] = n -; -; Memory layout after execution: -; [es:edi] = n (new top) -; [es:edi+4] = n (original top) - - mov eax, [es:edi] ; copy top element to eax - sub edi, 4 ; make room on data stack for one element - mov [es:edi], eax ; push copy of top element onto stack - jmp emu ; return to emulation loop - -op_09_xdrop: ; Drop: ( n -- ) -; -; Removes the top element from the data stack. -; -; Memory layout before execution: -; [es:edi] = n -; -; Memory layout after execution: -; Stack pointer is adjusted; n is no longer on stack - - add edi, 4 ; pop top element off the stack - jmp emu ; return to emulation loop diff --git a/emulator/opcodes_10_19.asm b/emulator/opcodes_10_19.asm new file mode 100644 index 0000000..11e5d4a --- /dev/null +++ b/emulator/opcodes_10_19.asm @@ -0,0 +1,92 @@ +; Opcodes 10-19: if, ret, c@, c!, push, pop, (unused), rot, disk@, disk! + +op_10_xif: ; Conditional Jump: ( flag -- ) + mov eax, [es:edi] ; eax = flag (top of data stack) + add edi, 4 ; pop flag off the data stack + cmp eax, 0 ; test if flag is zero + jne l2 ; if flag is non-zero, skip the jump + mov esi, [es:esi] ; read 32-bit target address from instruction stream + add esi, [xms_addr] ; convert virtual address to physical address + jmp emu ; return to emulation loop +l2: + add esi, 4 ; skip past the 32-bit jump target in instruction stream + jmp emu ; return to emulation loop + +op_11_xret: ; Return: ( -- ) R:( ret-addr -- ) + mov eax, [resp] ; load return stack pointer + mov esi, [es:eax] ; pop return address from return stack + add esi, [xms_addr] ; convert virtual address to physical address + add eax, 4 ; adjust return stack pointer (pop) + mov [resp], eax ; store updated return stack pointer + jmp emu ; return to emulation loop + +op_12_xc@: ; Fetch Byte: ( addr -- byte ) + mov eax, [es:edi] ; eax = virtual address from top of data stack + add eax, [xms_addr] ; convert virtual address to physical address + sub ecx, ecx ; clear ecx (zero-extend the byte) + mov cl, [es:eax] ; read one byte from memory into cl + mov [es:edi], ecx ; replace address on stack with the fetched byte value + jmp emu ; return to emulation loop + +op_13_xc!: ; Store Byte: ( byte addr -- ) + mov ebx, [es:edi] ; ebx = virtual address (top of stack) + add edi, 4 ; pop address off the data stack + mov ecx, [es:edi] ; ecx = byte value (second on stack, only cl used) + add edi, 4 ; pop byte value off the data stack + add ebx, [xms_addr] ; convert virtual address to physical address + mov [es:ebx], cl ; store low byte of ecx to memory + jmp emu ; return to emulation loop + +op_14_xpush: ; Push to Return Stack: ( n -- ) R:( -- n ) + mov ebx, [es:edi] ; ebx = top of data stack + add edi, 4 ; pop value off the data stack + mov eax, [resp] ; load return stack pointer + sub eax, 4 ; make room on return stack for one element + mov [es:eax], ebx ; push value onto return stack + mov [resp], eax ; store updated return stack pointer + jmp emu ; return to emulation loop + +op_15_xpop: ; Pop from Return Stack: ( -- n ) R:( n -- ) + mov eax, [resp] ; load return stack pointer + mov ebx, [es:eax] ; read value from top of return stack + add eax, 4 ; adjust return stack pointer (pop) + mov [resp], eax ; store updated return stack pointer + sub edi, 4 ; make room on data stack for one element + mov [es:edi], ebx ; push value onto data stack + jmp emu ; return to emulation loop + +op_17_xrot: ; Rotate: ( a b c -- b c a ) + mov ebx, [es:edi] ; ebx = c (top of stack) + mov ecx, [es:edi+4] ; ecx = b (second on stack) + mov edx, [es:edi+8] ; edx = a (third on stack) + mov [es:edi+8], ecx ; third slot = b + mov [es:edi+4], ebx ; second slot = c + mov [es:edi], edx ; top slot = a + jmp emu ; return to emulation loop + +op_18_xdisk@: ; Disk Load: ( sector mem -- ) + mov ebx, [es:edi] ; ebx = destination memory address (virtual) + add ebx, [xms_addr] ; convert virtual address to physical address + mov ecx, [es:edi+4] ; ecx = sector number + add edi, 8 ; pop both arguments off the data stack + call diskload ; load 1024 bytes: ecx=sector, ebx=destination + jmp emu ; return to emulation loop + +op_19_xdisk!: ; Disk Save: ( mem sector -- ) + mov ecx, [es:edi] ; ecx = sector number (top of stack) + call file_seek ; seek to the correct position in disk file + mov ecx, 1024 ; number of bytes to write + mov ebx, [es:edi+4] ; ebx = source memory address (virtual) + add edi, 8 ; pop both arguments off the data stack + add ebx, [xms_addr] ; convert virtual address to physical address + sub edx, edx ; clear edx + mov dx, cs ; edx = code segment + shl edx, 4 ; convert segment to linear address + add edx, buf ; edx = physical address of temporary buffer + call memmove ; copy from XMS to temporary buffer + mov ah, 40h ; DOS: write to file + mov bx, [fileh] ; file handle + mov cx, 1024 ; number of bytes to write + mov dx, buf ; source buffer address + int 21h ; call DOS interrupt + jmp emu ; return to emulation loop diff --git a/emulator/opcodes_10_19.inc b/emulator/opcodes_10_19.inc deleted file mode 100644 index 11e5d4a..0000000 --- a/emulator/opcodes_10_19.inc +++ /dev/null @@ -1,92 +0,0 @@ -; Opcodes 10-19: if, ret, c@, c!, push, pop, (unused), rot, disk@, disk! - -op_10_xif: ; Conditional Jump: ( flag -- ) - mov eax, [es:edi] ; eax = flag (top of data stack) - add edi, 4 ; pop flag off the data stack - cmp eax, 0 ; test if flag is zero - jne l2 ; if flag is non-zero, skip the jump - mov esi, [es:esi] ; read 32-bit target address from instruction stream - add esi, [xms_addr] ; convert virtual address to physical address - jmp emu ; return to emulation loop -l2: - add esi, 4 ; skip past the 32-bit jump target in instruction stream - jmp emu ; return to emulation loop - -op_11_xret: ; Return: ( -- ) R:( ret-addr -- ) - mov eax, [resp] ; load return stack pointer - mov esi, [es:eax] ; pop return address from return stack - add esi, [xms_addr] ; convert virtual address to physical address - add eax, 4 ; adjust return stack pointer (pop) - mov [resp], eax ; store updated return stack pointer - jmp emu ; return to emulation loop - -op_12_xc@: ; Fetch Byte: ( addr -- byte ) - mov eax, [es:edi] ; eax = virtual address from top of data stack - add eax, [xms_addr] ; convert virtual address to physical address - sub ecx, ecx ; clear ecx (zero-extend the byte) - mov cl, [es:eax] ; read one byte from memory into cl - mov [es:edi], ecx ; replace address on stack with the fetched byte value - jmp emu ; return to emulation loop - -op_13_xc!: ; Store Byte: ( byte addr -- ) - mov ebx, [es:edi] ; ebx = virtual address (top of stack) - add edi, 4 ; pop address off the data stack - mov ecx, [es:edi] ; ecx = byte value (second on stack, only cl used) - add edi, 4 ; pop byte value off the data stack - add ebx, [xms_addr] ; convert virtual address to physical address - mov [es:ebx], cl ; store low byte of ecx to memory - jmp emu ; return to emulation loop - -op_14_xpush: ; Push to Return Stack: ( n -- ) R:( -- n ) - mov ebx, [es:edi] ; ebx = top of data stack - add edi, 4 ; pop value off the data stack - mov eax, [resp] ; load return stack pointer - sub eax, 4 ; make room on return stack for one element - mov [es:eax], ebx ; push value onto return stack - mov [resp], eax ; store updated return stack pointer - jmp emu ; return to emulation loop - -op_15_xpop: ; Pop from Return Stack: ( -- n ) R:( n -- ) - mov eax, [resp] ; load return stack pointer - mov ebx, [es:eax] ; read value from top of return stack - add eax, 4 ; adjust return stack pointer (pop) - mov [resp], eax ; store updated return stack pointer - sub edi, 4 ; make room on data stack for one element - mov [es:edi], ebx ; push value onto data stack - jmp emu ; return to emulation loop - -op_17_xrot: ; Rotate: ( a b c -- b c a ) - mov ebx, [es:edi] ; ebx = c (top of stack) - mov ecx, [es:edi+4] ; ecx = b (second on stack) - mov edx, [es:edi+8] ; edx = a (third on stack) - mov [es:edi+8], ecx ; third slot = b - mov [es:edi+4], ebx ; second slot = c - mov [es:edi], edx ; top slot = a - jmp emu ; return to emulation loop - -op_18_xdisk@: ; Disk Load: ( sector mem -- ) - mov ebx, [es:edi] ; ebx = destination memory address (virtual) - add ebx, [xms_addr] ; convert virtual address to physical address - mov ecx, [es:edi+4] ; ecx = sector number - add edi, 8 ; pop both arguments off the data stack - call diskload ; load 1024 bytes: ecx=sector, ebx=destination - jmp emu ; return to emulation loop - -op_19_xdisk!: ; Disk Save: ( mem sector -- ) - mov ecx, [es:edi] ; ecx = sector number (top of stack) - call file_seek ; seek to the correct position in disk file - mov ecx, 1024 ; number of bytes to write - mov ebx, [es:edi+4] ; ebx = source memory address (virtual) - add edi, 8 ; pop both arguments off the data stack - add ebx, [xms_addr] ; convert virtual address to physical address - sub edx, edx ; clear edx - mov dx, cs ; edx = code segment - shl edx, 4 ; convert segment to linear address - add edx, buf ; edx = physical address of temporary buffer - call memmove ; copy from XMS to temporary buffer - mov ah, 40h ; DOS: write to file - mov bx, [fileh] ; file handle - mov cx, 1024 ; number of bytes to write - mov dx, buf ; source buffer address - int 21h ; call DOS interrupt - jmp emu ; return to emulation loop diff --git a/emulator/opcodes_20_29.asm b/emulator/opcodes_20_29.asm new file mode 100644 index 0000000..03aba5b --- /dev/null +++ b/emulator/opcodes_20_29.asm @@ -0,0 +1,95 @@ +; Opcodes 20-29: @, !, over, swap, plus, minus, mul, div, great, less + +op_20_x@: ; Fetch 32-bit: ( addr -- n ) + mov eax, [es:edi] ; eax = virtual address from top of data stack + add eax, [xms_addr] ; convert virtual address to physical address + mov eax, [es:eax] ; read 32-bit value from memory + mov [es:edi], eax ; replace address on stack with the fetched value + jmp emu ; return to emulation loop + +op_21_x!: ; Store 32-bit: ( n addr -- ) + mov eax, [es:edi] ; eax = virtual address (top of stack) + add eax, [xms_addr] ; convert virtual address to physical address + mov ecx, [es:edi+4] ; ecx = value to store (second on stack) + add edi, 8 ; pop both arguments off the data stack + mov [es:eax], ecx ; store 32-bit value to memory + jmp emu ; return to emulation loop + +op_22_xover: ; Over: ( a b -- a b a ) + mov ebx, [es:edi+4] ; ebx = a (second element on stack) + sub edi, 4 ; make room on data stack for one element + mov [es:edi], ebx ; push copy of a onto top of stack + jmp emu ; return to emulation loop + +op_23_xswap: ; Swap: ( a b -- b a ) + mov ebx, [es:edi] ; ebx = b (top of stack) + xchg ebx, [es:edi+4] ; exchange ebx with a (second on stack); ebx=a, [edi+4]=b + mov [es:edi], ebx ; top of stack = a + jmp emu ; return to emulation loop + +op_24_xplus: ; Add: ( n1 n2 -- n1+n2 ) + mov ebx, [es:edi] ; ebx = n2 (the addend — top of stack) + add edi, 4 ; pop n2 off the stack; n1 is now the new top + add [es:edi], ebx ; [es:edi] = n1 + n2 (add n2 to n1 in place) + jmp emu ; return to emulation loop + +op_25_xminus: ; Subtract: ( n1 n2 -- n1-n2 ) +; +; Pops the top two elements from the data stack, subtracts the top +; element (n2) from the second element (n1), and pushes the result. +; +; In Fifth source code, this corresponds to the "-" word: +; +; 10 3 - \ result is 7 (10 minus 3) +; +; Argument order: +; n1 is pushed first (sits deeper in the stack, at [es:edi+4]) +; n2 is pushed second (sits on top of the stack, at [es:edi]) +; +; Memory layout before execution: +; [es:edi] = n2 (top of stack — the value being subtracted) +; [es:edi+4] = n1 (second on stack — the value subtracted from) +; +; Memory layout after execution: +; [es:edi] = n1 - n2 (edi has been adjusted; old n2 slot is freed) + + mov ebx, [es:edi] ; ebx = n2 (the subtrahend — value to subtract) + add edi, 4 ; pop n2 off the stack; n1 is now the new top + sub [es:edi], ebx ; [es:edi] = n1 - n2 (subtract n2 from n1 in place) + jmp emu ; return to emulation loop + +op_26_xmul: ; Multiply (signed): ( n1 n2 -- n1*n2 ) + mov eax, [es:edi] ; eax = n2 (top of stack) + add edi, 4 ; pop n2 off the stack; n1 is now the new top + sub edx, edx ; clear edx before signed multiply + imul dword [es:edi] ; edx:eax = eax * n1 (signed multiply) + mov [es:edi], eax ; store low 32 bits of result as new top of stack + jmp emu ; return to emulation loop + +op_27_xdiv: ; Divide (signed): ( n1 n2 -- n1/n2 ) + add edi, 4 ; pop n2; n1 is now the new top (but we read n2 from edi-4) + mov eax, [es:edi] ; eax = n1 (the dividend) + cdq ; sign-extend eax into edx:eax for signed division + idiv dword [es:edi-4] ; eax = edx:eax / n2 (signed divide) + mov [es:edi], eax ; store quotient as new top of stack + jmp emu ; return to emulation loop + +op_28_xgreat: ; Greater Than: ( a b -- flag ) + mov eax, [es:edi] ; eax = b (top of stack) + add edi, 4 ; pop b off the stack; a is now the new top + mov edx, 0 ; edx = 0 (default: false) + cmp [es:edi], eax ; compare a with b + jng l3 ; if a is NOT greater than b, skip setting flag + dec edx ; edx = -1 (true flag, all bits set) +l3: mov [es:edi], edx ; store flag as new top of stack + jmp emu ; return to emulation loop + +op_29_xless: ; Less Than: ( a b -- flag ) + mov eax, [es:edi] ; eax = b (top of stack) + add edi, 4 ; pop b off the stack; a is now the new top + mov edx, 0 ; edx = 0 (default: false) + cmp [es:edi], eax ; compare a with b + jnl l4 ; if a is NOT less than b, skip setting flag + dec edx ; edx = -1 (true flag, all bits set) +l4: mov [es:edi], edx ; store flag as new top of stack + jmp emu ; return to emulation loop diff --git a/emulator/opcodes_20_29.inc b/emulator/opcodes_20_29.inc deleted file mode 100644 index 03aba5b..0000000 --- a/emulator/opcodes_20_29.inc +++ /dev/null @@ -1,95 +0,0 @@ -; Opcodes 20-29: @, !, over, swap, plus, minus, mul, div, great, less - -op_20_x@: ; Fetch 32-bit: ( addr -- n ) - mov eax, [es:edi] ; eax = virtual address from top of data stack - add eax, [xms_addr] ; convert virtual address to physical address - mov eax, [es:eax] ; read 32-bit value from memory - mov [es:edi], eax ; replace address on stack with the fetched value - jmp emu ; return to emulation loop - -op_21_x!: ; Store 32-bit: ( n addr -- ) - mov eax, [es:edi] ; eax = virtual address (top of stack) - add eax, [xms_addr] ; convert virtual address to physical address - mov ecx, [es:edi+4] ; ecx = value to store (second on stack) - add edi, 8 ; pop both arguments off the data stack - mov [es:eax], ecx ; store 32-bit value to memory - jmp emu ; return to emulation loop - -op_22_xover: ; Over: ( a b -- a b a ) - mov ebx, [es:edi+4] ; ebx = a (second element on stack) - sub edi, 4 ; make room on data stack for one element - mov [es:edi], ebx ; push copy of a onto top of stack - jmp emu ; return to emulation loop - -op_23_xswap: ; Swap: ( a b -- b a ) - mov ebx, [es:edi] ; ebx = b (top of stack) - xchg ebx, [es:edi+4] ; exchange ebx with a (second on stack); ebx=a, [edi+4]=b - mov [es:edi], ebx ; top of stack = a - jmp emu ; return to emulation loop - -op_24_xplus: ; Add: ( n1 n2 -- n1+n2 ) - mov ebx, [es:edi] ; ebx = n2 (the addend — top of stack) - add edi, 4 ; pop n2 off the stack; n1 is now the new top - add [es:edi], ebx ; [es:edi] = n1 + n2 (add n2 to n1 in place) - jmp emu ; return to emulation loop - -op_25_xminus: ; Subtract: ( n1 n2 -- n1-n2 ) -; -; Pops the top two elements from the data stack, subtracts the top -; element (n2) from the second element (n1), and pushes the result. -; -; In Fifth source code, this corresponds to the "-" word: -; -; 10 3 - \ result is 7 (10 minus 3) -; -; Argument order: -; n1 is pushed first (sits deeper in the stack, at [es:edi+4]) -; n2 is pushed second (sits on top of the stack, at [es:edi]) -; -; Memory layout before execution: -; [es:edi] = n2 (top of stack — the value being subtracted) -; [es:edi+4] = n1 (second on stack — the value subtracted from) -; -; Memory layout after execution: -; [es:edi] = n1 - n2 (edi has been adjusted; old n2 slot is freed) - - mov ebx, [es:edi] ; ebx = n2 (the subtrahend — value to subtract) - add edi, 4 ; pop n2 off the stack; n1 is now the new top - sub [es:edi], ebx ; [es:edi] = n1 - n2 (subtract n2 from n1 in place) - jmp emu ; return to emulation loop - -op_26_xmul: ; Multiply (signed): ( n1 n2 -- n1*n2 ) - mov eax, [es:edi] ; eax = n2 (top of stack) - add edi, 4 ; pop n2 off the stack; n1 is now the new top - sub edx, edx ; clear edx before signed multiply - imul dword [es:edi] ; edx:eax = eax * n1 (signed multiply) - mov [es:edi], eax ; store low 32 bits of result as new top of stack - jmp emu ; return to emulation loop - -op_27_xdiv: ; Divide (signed): ( n1 n2 -- n1/n2 ) - add edi, 4 ; pop n2; n1 is now the new top (but we read n2 from edi-4) - mov eax, [es:edi] ; eax = n1 (the dividend) - cdq ; sign-extend eax into edx:eax for signed division - idiv dword [es:edi-4] ; eax = edx:eax / n2 (signed divide) - mov [es:edi], eax ; store quotient as new top of stack - jmp emu ; return to emulation loop - -op_28_xgreat: ; Greater Than: ( a b -- flag ) - mov eax, [es:edi] ; eax = b (top of stack) - add edi, 4 ; pop b off the stack; a is now the new top - mov edx, 0 ; edx = 0 (default: false) - cmp [es:edi], eax ; compare a with b - jng l3 ; if a is NOT greater than b, skip setting flag - dec edx ; edx = -1 (true flag, all bits set) -l3: mov [es:edi], edx ; store flag as new top of stack - jmp emu ; return to emulation loop - -op_29_xless: ; Less Than: ( a b -- flag ) - mov eax, [es:edi] ; eax = b (top of stack) - add edi, 4 ; pop b off the stack; a is now the new top - mov edx, 0 ; edx = 0 (default: false) - cmp [es:edi], eax ; compare a with b - jnl l4 ; if a is NOT less than b, skip setting flag - dec edx ; edx = -1 (true flag, all bits set) -l4: mov [es:edi], edx ; store flag as new top of stack - jmp emu ; return to emulation loop diff --git a/emulator/opcodes_30_39.asm b/emulator/opcodes_30_39.asm new file mode 100644 index 0000000..2461061 --- /dev/null +++ b/emulator/opcodes_30_39.asm @@ -0,0 +1,65 @@ +; Opcodes 30-39: not, i, cprt@, cprt!, i2, i3, shl, shr, or, xor + +op_30_xnot: ; Bitwise NOT: ( n -- ~n ) + not dword [es:edi] ; invert all bits of top of data stack in place + jmp emu ; return to emulation loop + +op_31_xi: ; Copy Return Stack TOS: ( -- n ) R:( n -- n ) + mov ebx, [resp] ; ebx = return stack pointer + mov eax, [es:ebx] ; eax = value at top of return stack + sub edi, 4 ; make room on data stack for one element + mov [es:edi], eax ; push copy of return stack top onto data stack + jmp emu ; return to emulation loop + +op_32_xcprt@: ; Read I/O Port: ( port -- byte ) + mov dx, [es:edi] ; dx = port number from top of data stack + in al, dx ; read one byte from the I/O port + sub ecx, ecx ; clear ecx (zero-extend the byte) + mov cl, al ; cl = byte read from port + mov [es:edi], ecx ; replace port number on stack with the read byte + jmp emu ; return to emulation loop + +op_33_xcprt!: ; Write I/O Port: ( byte port -- ) + mov dx, [es:edi] ; dx = port number (top of stack) + mov al, [es:edi+4] ; al = byte value to write (second on stack) + add edi, 8 ; pop both arguments off the data stack + out dx, al ; write byte to the I/O port + jmp emu ; return to emulation loop + +op_34_xi2: ; Copy Return Stack 2nd: ( -- n ) + mov ebx, [resp] ; ebx = return stack pointer + mov eax, [es:ebx+4] ; eax = second element on return stack + sub edi, 4 ; make room on data stack for one element + mov [es:edi], eax ; push value onto data stack + jmp emu ; return to emulation loop + +op_35_xi3: ; Copy Return Stack 3rd: ( -- n ) + mov ebx, [resp] ; ebx = return stack pointer + mov eax, [es:ebx+8] ; eax = third element on return stack + sub edi, 4 ; make room on data stack for one element + mov [es:edi], eax ; push value onto data stack + jmp emu ; return to emulation loop + +op_36_xshl: ; Shift Left: ( n count -- n<>count ) + mov cl, [es:edi] ; cl = shift count (top of stack, only low byte used) + add edi, 4 ; pop count off the stack; n is now the new top + shr dword [es:edi], cl ; shift n right by cl bits in place (unsigned) + jmp emu ; return to emulation loop + +op_38_lor: ; Bitwise OR: ( a b -- a|b ) + mov eax, [es:edi] ; eax = b (top of stack) + add edi, 4 ; pop b off the stack; a is now the new top + or [es:edi], eax ; [es:edi] = a OR b (bitwise OR in place) + jmp emu ; return to emulation loop + +op_39_lxor: ; Bitwise XOR: ( a b -- a^b ) + mov eax, [es:edi] ; eax = b (top of stack) + add edi, 4 ; pop b off the stack; a is now the new top + xor [es:edi], eax ; [es:edi] = a XOR b (bitwise XOR in place) + jmp emu ; return to emulation loop diff --git a/emulator/opcodes_30_39.inc b/emulator/opcodes_30_39.inc deleted file mode 100644 index 2461061..0000000 --- a/emulator/opcodes_30_39.inc +++ /dev/null @@ -1,65 +0,0 @@ -; Opcodes 30-39: not, i, cprt@, cprt!, i2, i3, shl, shr, or, xor - -op_30_xnot: ; Bitwise NOT: ( n -- ~n ) - not dword [es:edi] ; invert all bits of top of data stack in place - jmp emu ; return to emulation loop - -op_31_xi: ; Copy Return Stack TOS: ( -- n ) R:( n -- n ) - mov ebx, [resp] ; ebx = return stack pointer - mov eax, [es:ebx] ; eax = value at top of return stack - sub edi, 4 ; make room on data stack for one element - mov [es:edi], eax ; push copy of return stack top onto data stack - jmp emu ; return to emulation loop - -op_32_xcprt@: ; Read I/O Port: ( port -- byte ) - mov dx, [es:edi] ; dx = port number from top of data stack - in al, dx ; read one byte from the I/O port - sub ecx, ecx ; clear ecx (zero-extend the byte) - mov cl, al ; cl = byte read from port - mov [es:edi], ecx ; replace port number on stack with the read byte - jmp emu ; return to emulation loop - -op_33_xcprt!: ; Write I/O Port: ( byte port -- ) - mov dx, [es:edi] ; dx = port number (top of stack) - mov al, [es:edi+4] ; al = byte value to write (second on stack) - add edi, 8 ; pop both arguments off the data stack - out dx, al ; write byte to the I/O port - jmp emu ; return to emulation loop - -op_34_xi2: ; Copy Return Stack 2nd: ( -- n ) - mov ebx, [resp] ; ebx = return stack pointer - mov eax, [es:ebx+4] ; eax = second element on return stack - sub edi, 4 ; make room on data stack for one element - mov [es:edi], eax ; push value onto data stack - jmp emu ; return to emulation loop - -op_35_xi3: ; Copy Return Stack 3rd: ( -- n ) - mov ebx, [resp] ; ebx = return stack pointer - mov eax, [es:ebx+8] ; eax = third element on return stack - sub edi, 4 ; make room on data stack for one element - mov [es:edi], eax ; push value onto data stack - jmp emu ; return to emulation loop - -op_36_xshl: ; Shift Left: ( n count -- n<>count ) - mov cl, [es:edi] ; cl = shift count (top of stack, only low byte used) - add edi, 4 ; pop count off the stack; n is now the new top - shr dword [es:edi], cl ; shift n right by cl bits in place (unsigned) - jmp emu ; return to emulation loop - -op_38_lor: ; Bitwise OR: ( a b -- a|b ) - mov eax, [es:edi] ; eax = b (top of stack) - add edi, 4 ; pop b off the stack; a is now the new top - or [es:edi], eax ; [es:edi] = a OR b (bitwise OR in place) - jmp emu ; return to emulation loop - -op_39_lxor: ; Bitwise XOR: ( a b -- a^b ) - mov eax, [es:edi] ; eax = b (top of stack) - add edi, 4 ; pop b off the stack; a is now the new top - xor [es:edi], eax ; [es:edi] = a XOR b (bitwise XOR in place) - jmp emu ; return to emulation loop diff --git a/emulator/opcodes_40_47.inc b/emulator/opcodes_40_47.inc deleted file mode 100644 index f21d87c..0000000 --- a/emulator/opcodes_40_47.inc +++ /dev/null @@ -1,107 +0,0 @@ -; Opcodes 40-47: vidmap, mouse@, vidput, cmove, cfill, tvidput, dep, charput - -op_40_xvidmap: ; Video Map: ( addr -- ) - mov edx, [es:edi] ; edx = virtual address of image buffer - add edx, [xms_addr] ; convert virtual address to physical address - add edi, 4 ; pop address off the data stack - push edi ; save data stack pointer - push esi ; save instruction pointer - push 0a000h ; push video memory segment - pop es ; es = video memory segment (A000h) - mov word [ds:gra], 0 ; reset VESA granule counter to 0 - push 0 ; push zero segment - pop ds ; ds = 0 (flat memory access) - mov esi, edx ; esi = source address (image buffer in XMS) -mapl1: - mov dx, [cs:gra] ; dx = current VESA granule number - xor bx, bx ; bx = 0 (window A) - mov ax, 4f05h ; VESA: set memory window position - int 10h ; call VESA BIOS - mov edi, 0 ; edi = 0 (start of video window) - mov cx, 4096 ; cx = number of dwords to copy (4096 * 4 = 16384 bytes) -mapl2: - mov eax, [ds:esi] ; read 4 bytes from source image buffer - add esi, 4 ; advance source pointer by 4 bytes - stosd ; write 4 bytes to video memory, advance edi - loop mapl2 ; repeat for all 4096 dwords in this granule - inc word [cs:gra] ; advance to next VESA granule - cmp word [cs:gra], 19 ; check if all 19 granules are done (19*16384=311296>=307200) - jne mapl1 ; if not done, process next granule - push 0 ; push zero segment - pop es ; restore es = 0 - push cs ; push code segment - pop ds ; restore ds = cs - pop esi ; restore instruction pointer - pop edi ; restore data stack pointer - jmp emu ; return to emulation loop -gra dw 0 ; current VESA granule number - - -op_41_xmouse@: ; Read Mouse: ( -- buttons dy dx ) - mov ax, 0bh ; mouse function: read motion counters - int 33h ; call mouse driver; cx=dx_motion, dx=dy_motion - push dx ; save dy (vertical motion) on x86 stack - sub eax, eax ; clear eax - mov ax, cx ; ax = dx_motion (horizontal motion) - cwd ; sign-extend ax into dx:ax - shl edx, 16 ; shift sign extension to upper 16 bits - add edx, eax ; edx = sign-extended 32-bit dx_motion - mov [es:edi-4], edx ; store dx (horizontal motion) below current stack top - pop ax ; restore dy (vertical motion) into ax - cwd ; sign-extend ax into dx:ax - shl edx, 16 ; shift sign extension to upper 16 bits - add edx, eax ; edx = sign-extended 32-bit dy_motion - mov [es:edi-8], edx ; store dy (vertical motion) further below stack top - mov ax, 3 ; mouse function: read button status - int 33h ; call mouse driver; bx=button state - sub eax, eax ; clear eax - mov ax, bx ; ax = button state - sub edi, 12 ; allocate 3 stack slots (buttons, dy, dx) - mov [es:edi], eax ; push button state as bottom of the three new elements - jmp emu ; return to emulation loop - -op_43_xcmove: ; Copy Memory: ( src dst count -- ) - mov ecx, [es:edi] ; ecx = byte count (top of stack) - add edi, 12 ; pop all three arguments off the data stack - mov edx, [es:edi-8] ; edx = destination address (virtual) - add edx, [xms_addr] ; convert destination virtual address to physical - mov ebx, [es:edi-4] ; ebx = source address (virtual) - add ebx, [xms_addr] ; convert source virtual address to physical - cmp ecx, 0 ; check if count is zero - je emu ; if zero bytes, nothing to do - cmp ebx, edx ; compare source and destination addresses - ja l8 ; if source > dest, copy forward (no overlap issue) - call memmove2 ; otherwise copy backward (handles overlapping regions) - jmp emu ; return to emulation loop -l8: call memmove ; copy forward: ebx=from, edx=to, ecx=count - jmp emu ; return to emulation loop - -op_44_xcfill: ; Fill Memory: ( byte addr count -- ) - mov ecx, [es:edi] ; ecx = byte count (top of stack) - mov edx, [es:edi+4] ; edx = destination address (virtual, second on stack) - add edx, [xms_addr] ; convert virtual address to physical address - mov eax, [es:edi+8] ; eax = fill byte value (third on stack, only al used) - add edi, 12 ; pop all three arguments off the data stack -l9: - cmp ecx, 0 ; check if remaining count is zero - je emu ; if zero, we are done - mov [es:edx], al ; store fill byte at current destination - inc edx ; advance destination pointer - dec ecx ; decrement remaining count - jmp l9 ; repeat for next byte - -op_46_xdep: ; Stack Depth: ( -- depth ) - sub eax, eax ; clear eax - mov ax, cs ; ax = code segment - shl eax, 4 ; convert segment to linear address - add eax, buf ; eax = linear address of buffer area - add eax, 20000 ; eax = base of data stack (stack bottom) - sub eax, edi ; eax = number of bytes used on stack - shr eax, 2 ; convert bytes to 32-bit cell count (divide by 4) - sub edi, 4 ; make room on data stack for one element - mov [es:edi], eax ; push stack depth onto data stack - jmp emu ; return to emulation loop - -include 'vidput.inc' -include 'tvidput.inc' -include 'charput.inc' diff --git a/emulator/opcodes_40_49.asm b/emulator/opcodes_40_49.asm new file mode 100644 index 0000000..68c871b --- /dev/null +++ b/emulator/opcodes_40_49.asm @@ -0,0 +1,107 @@ +; Opcodes 40-47: vidmap, mouse@, vidput, cmove, cfill, tvidput, dep, charput + +op_40_xvidmap: ; Video Map: ( addr -- ) + mov edx, [es:edi] ; edx = virtual address of image buffer + add edx, [xms_addr] ; convert virtual address to physical address + add edi, 4 ; pop address off the data stack + push edi ; save data stack pointer + push esi ; save instruction pointer + push 0a000h ; push video memory segment + pop es ; es = video memory segment (A000h) + mov word [ds:gra], 0 ; reset VESA granule counter to 0 + push 0 ; push zero segment + pop ds ; ds = 0 (flat memory access) + mov esi, edx ; esi = source address (image buffer in XMS) +mapl1: + mov dx, [cs:gra] ; dx = current VESA granule number + xor bx, bx ; bx = 0 (window A) + mov ax, 4f05h ; VESA: set memory window position + int 10h ; call VESA BIOS + mov edi, 0 ; edi = 0 (start of video window) + mov cx, 4096 ; cx = number of dwords to copy (4096 * 4 = 16384 bytes) +mapl2: + mov eax, [ds:esi] ; read 4 bytes from source image buffer + add esi, 4 ; advance source pointer by 4 bytes + stosd ; write 4 bytes to video memory, advance edi + loop mapl2 ; repeat for all 4096 dwords in this granule + inc word [cs:gra] ; advance to next VESA granule + cmp word [cs:gra], 19 ; check if all 19 granules are done (19*16384=311296>=307200) + jne mapl1 ; if not done, process next granule + push 0 ; push zero segment + pop es ; restore es = 0 + push cs ; push code segment + pop ds ; restore ds = cs + pop esi ; restore instruction pointer + pop edi ; restore data stack pointer + jmp emu ; return to emulation loop +gra dw 0 ; current VESA granule number + + +op_41_xmouse@: ; Read Mouse: ( -- buttons dy dx ) + mov ax, 0bh ; mouse function: read motion counters + int 33h ; call mouse driver; cx=dx_motion, dx=dy_motion + push dx ; save dy (vertical motion) on x86 stack + sub eax, eax ; clear eax + mov ax, cx ; ax = dx_motion (horizontal motion) + cwd ; sign-extend ax into dx:ax + shl edx, 16 ; shift sign extension to upper 16 bits + add edx, eax ; edx = sign-extended 32-bit dx_motion + mov [es:edi-4], edx ; store dx (horizontal motion) below current stack top + pop ax ; restore dy (vertical motion) into ax + cwd ; sign-extend ax into dx:ax + shl edx, 16 ; shift sign extension to upper 16 bits + add edx, eax ; edx = sign-extended 32-bit dy_motion + mov [es:edi-8], edx ; store dy (vertical motion) further below stack top + mov ax, 3 ; mouse function: read button status + int 33h ; call mouse driver; bx=button state + sub eax, eax ; clear eax + mov ax, bx ; ax = button state + sub edi, 12 ; allocate 3 stack slots (buttons, dy, dx) + mov [es:edi], eax ; push button state as bottom of the three new elements + jmp emu ; return to emulation loop + +op_43_xcmove: ; Copy Memory: ( src dst count -- ) + mov ecx, [es:edi] ; ecx = byte count (top of stack) + add edi, 12 ; pop all three arguments off the data stack + mov edx, [es:edi-8] ; edx = destination address (virtual) + add edx, [xms_addr] ; convert destination virtual address to physical + mov ebx, [es:edi-4] ; ebx = source address (virtual) + add ebx, [xms_addr] ; convert source virtual address to physical + cmp ecx, 0 ; check if count is zero + je emu ; if zero bytes, nothing to do + cmp ebx, edx ; compare source and destination addresses + ja l8 ; if source > dest, copy forward (no overlap issue) + call memmove2 ; otherwise copy backward (handles overlapping regions) + jmp emu ; return to emulation loop +l8: call memmove ; copy forward: ebx=from, edx=to, ecx=count + jmp emu ; return to emulation loop + +op_44_xcfill: ; Fill Memory: ( byte addr count -- ) + mov ecx, [es:edi] ; ecx = byte count (top of stack) + mov edx, [es:edi+4] ; edx = destination address (virtual, second on stack) + add edx, [xms_addr] ; convert virtual address to physical address + mov eax, [es:edi+8] ; eax = fill byte value (third on stack, only al used) + add edi, 12 ; pop all three arguments off the data stack +l9: + cmp ecx, 0 ; check if remaining count is zero + je emu ; if zero, we are done + mov [es:edx], al ; store fill byte at current destination + inc edx ; advance destination pointer + dec ecx ; decrement remaining count + jmp l9 ; repeat for next byte + +op_46_xdep: ; Stack Depth: ( -- depth ) + sub eax, eax ; clear eax + mov ax, cs ; ax = code segment + shl eax, 4 ; convert segment to linear address + add eax, buf ; eax = linear address of buffer area + add eax, 20000 ; eax = base of data stack (stack bottom) + sub eax, edi ; eax = number of bytes used on stack + shr eax, 2 ; convert bytes to 32-bit cell count (divide by 4) + sub edi, 4 ; make room on data stack for one element + mov [es:edi], eax ; push stack depth onto data stack + jmp emu ; return to emulation loop + +include 'vidput.asm' +include 'tvidput.asm' +include 'charput.asm' diff --git a/emulator/system.asm b/emulator/system.asm new file mode 100644 index 0000000..2028a0e --- /dev/null +++ b/emulator/system.asm @@ -0,0 +1,162 @@ +; System initialization and management routines + +; system_init +; +; Initializes the system by: +; - Checking for 80386 or better CPU +; - Checking for protected mode +; - Checking for XMS (Extended Memory Specification) support +; - Allocating and locking extended memory +; - Setting up A20 gate +; +; Notes: +; - Uses DOS interrupts for XMS operations. +; - Allocates the largest possible block of extended memory. + +system_init: + mov ax,7202h + push ax + popf + pushf + pop bx + cmp ax,bx + je processor_ok + mov dx, badcpu + mov ah,9 + int 21h + mov ah,4Ch + int 21h + badcpu db 'required 80386 or better',24h +processor_ok: + smsw ax + test al,1 + jz mode_ok + mov dx, badmode + mov ah,9 + int 21h + mov ah,4Ch + int 21h + badmode db 'error: CPU in protected mode',24h +mode_ok: + mov ax,4300h ; check for XMS + int 2Fh + cmp al,80h ; XMS present? + je xms_ok + mov dx, badxms + mov ah,9 + int 21h + jmp system_exit + badxms db 'error: HIMEM.SYS not loaded',24h +xms_ok: + mov ax,350Dh + int 21h + mov word [irq_5],bx + mov word [irq_5+2],es + push cs + pop es + mov ax,250Dh + mov dx,int_13 + int 21h + + push es + mov ax,4310h ; get XMS driver address + int 2Fh + mov word [xms_call],bx ; store XMS driver address + mov word [xms_call+2],es + pop es + mov ah,3 ; enable A20 + call far dword [xms_call] + mov ah,8 ; get free extended memory size + xor bl,bl + call far dword [xms_call] + or bl,bl + mov dx,ax + movzx eax,ax + shl eax,10 + mov ah,9 ; allocate largest memory block + call far dword [xms_call] + mov [xms_handle],dx + mov ah,0Ch ; lock extended memory block + call far dword [xms_call] + shl edx,16 + mov dx,bx + mov [xms_addr],edx ; store memory block address + ret + + +; system_exit +; +; Cleans up system resources before exiting: +; - Unlocks and frees extended memory +; - Restores original interrupt handler for INT 13h +; - Exits to DOS + +system_exit: + cmp [xms_handle],0 + je sys_exit + mov ah, 0dh ; unlock extended memory block + mov dx, [xms_handle] + call far dword [xms_call] + mov ah, 0ah ; free extended memory block + call far dword [xms_call] +sys_exit: + mov ax, 250dh + mov dx, word [irq_5] + mov ds, word [irq_5+2] + int 21h + pop ax + mov ah, 4ch + int 21h + +; int_13 +; +; Interrupt handler for INT 13h (disk services) +; Used for switching to protected mode and back. + +int_13: push eax + mov al, 00001011b ; OCW3 - read IRQ in-service register + out 20h, al + in al, 20h + test al, 00100000b ; is IRQ 5 in service? + jz exception + pop eax + jmp dword 0:0 + label irq_5 dword at $-4 +exception: + push ds es fs gs + cli ; disable interrupts + xor eax, eax ; calculate linear address of GDT + mov ax, cs + shl eax, 4 + add eax, GDT + mov dword [cs:GDTR+2],eax + lgdt pword [cs:GDTR] ; load GDT register + mov eax, cr0 ; switch to protected mode + or al, 1 + mov cr0, eax + jmp pm_start + pm_start: + mov ax, 1 shl 3 ; load 32-bit data descriptor + mov ds, ax ; to all data segment registers + mov es, ax + mov fs, ax + mov gs, ax + mov eax, cr0 ; switch back to real mode + and al, not 1 + mov cr0, eax + jmp pm_end + pm_end: + sti ; enable interrupts + pop gs fs es ds + pop eax + iret + +GDTR dw 2*8-1 ; limit of GDT + dd ? ; linear address of GDT + +GDT rw 4 ; null descriptor + dw 0FFFFh, 0, 9200h, 8Fh ; 32-bit data descriptor + +xms_call dd 0 ; XMS driver pointer +xms_handle dw 0 ; handle of XMS memory block +xms_addr dd 0 ; address to XMS block diff --git a/emulator/system.inc b/emulator/system.inc deleted file mode 100644 index 2028a0e..0000000 --- a/emulator/system.inc +++ /dev/null @@ -1,162 +0,0 @@ -; System initialization and management routines - -; system_init -; -; Initializes the system by: -; - Checking for 80386 or better CPU -; - Checking for protected mode -; - Checking for XMS (Extended Memory Specification) support -; - Allocating and locking extended memory -; - Setting up A20 gate -; -; Notes: -; - Uses DOS interrupts for XMS operations. -; - Allocates the largest possible block of extended memory. - -system_init: - mov ax,7202h - push ax - popf - pushf - pop bx - cmp ax,bx - je processor_ok - mov dx, badcpu - mov ah,9 - int 21h - mov ah,4Ch - int 21h - badcpu db 'required 80386 or better',24h -processor_ok: - smsw ax - test al,1 - jz mode_ok - mov dx, badmode - mov ah,9 - int 21h - mov ah,4Ch - int 21h - badmode db 'error: CPU in protected mode',24h -mode_ok: - mov ax,4300h ; check for XMS - int 2Fh - cmp al,80h ; XMS present? - je xms_ok - mov dx, badxms - mov ah,9 - int 21h - jmp system_exit - badxms db 'error: HIMEM.SYS not loaded',24h -xms_ok: - mov ax,350Dh - int 21h - mov word [irq_5],bx - mov word [irq_5+2],es - push cs - pop es - mov ax,250Dh - mov dx,int_13 - int 21h - - push es - mov ax,4310h ; get XMS driver address - int 2Fh - mov word [xms_call],bx ; store XMS driver address - mov word [xms_call+2],es - pop es - mov ah,3 ; enable A20 - call far dword [xms_call] - mov ah,8 ; get free extended memory size - xor bl,bl - call far dword [xms_call] - or bl,bl - mov dx,ax - movzx eax,ax - shl eax,10 - mov ah,9 ; allocate largest memory block - call far dword [xms_call] - mov [xms_handle],dx - mov ah,0Ch ; lock extended memory block - call far dword [xms_call] - shl edx,16 - mov dx,bx - mov [xms_addr],edx ; store memory block address - ret - - -; system_exit -; -; Cleans up system resources before exiting: -; - Unlocks and frees extended memory -; - Restores original interrupt handler for INT 13h -; - Exits to DOS - -system_exit: - cmp [xms_handle],0 - je sys_exit - mov ah, 0dh ; unlock extended memory block - mov dx, [xms_handle] - call far dword [xms_call] - mov ah, 0ah ; free extended memory block - call far dword [xms_call] -sys_exit: - mov ax, 250dh - mov dx, word [irq_5] - mov ds, word [irq_5+2] - int 21h - pop ax - mov ah, 4ch - int 21h - -; int_13 -; -; Interrupt handler for INT 13h (disk services) -; Used for switching to protected mode and back. - -int_13: push eax - mov al, 00001011b ; OCW3 - read IRQ in-service register - out 20h, al - in al, 20h - test al, 00100000b ; is IRQ 5 in service? - jz exception - pop eax - jmp dword 0:0 - label irq_5 dword at $-4 -exception: - push ds es fs gs - cli ; disable interrupts - xor eax, eax ; calculate linear address of GDT - mov ax, cs - shl eax, 4 - add eax, GDT - mov dword [cs:GDTR+2],eax - lgdt pword [cs:GDTR] ; load GDT register - mov eax, cr0 ; switch to protected mode - or al, 1 - mov cr0, eax - jmp pm_start - pm_start: - mov ax, 1 shl 3 ; load 32-bit data descriptor - mov ds, ax ; to all data segment registers - mov es, ax - mov fs, ax - mov gs, ax - mov eax, cr0 ; switch back to real mode - and al, not 1 - mov cr0, eax - jmp pm_end - pm_end: - sti ; enable interrupts - pop gs fs es ds - pop eax - iret - -GDTR dw 2*8-1 ; limit of GDT - dd ? ; linear address of GDT - -GDT rw 4 ; null descriptor - dw 0FFFFh, 0, 9200h, 8Fh ; 32-bit data descriptor - -xms_call dd 0 ; XMS driver pointer -xms_handle dw 0 ; handle of XMS memory block -xms_addr dd 0 ; address to XMS block diff --git a/emulator/tvidput.asm b/emulator/tvidput.asm new file mode 100644 index 0000000..3d100d1 --- /dev/null +++ b/emulator/tvidput.asm @@ -0,0 +1,173 @@ +; Blit image with transparency support +; +; Stack Effect: addr1 addr2 x y -- +; +; Copies a portion of image1 to image2 at the specified (x, y) +; coordinates with transparency support. Pixels in image1 with value +; 255 (0xFF) are treated as transparent and are not copied to the +; destination. +; +; Parameters: +; - addr1: Address of the source image structure (width, height, data) +; - addr2: Address of the destination image structure +; - x: X-coordinate in destination where to start copying +; - y: Y-coordinate in destination where to start copying +; +; Image Structure Format: +; - Offset 0: Image width (32-bit) +; - Offset 4: Image height (32-bit) +; - Offset 8: Base address of image data (32-bit pointer) +; +; Example: +; 0x1000 ; Source image structure +; 0x2000 ; Destination image structure +; 50 ; x +; 50 ; y +; tvidput +; +; Memory layout before execution: +; [es:edi] = y +; [es:edi+4] = x +; [es:edi+8] = addr2 +; [es:edi+12] = addr1 +; +; Memory layout after execution: +; Destination image updated with source image data (transparent pixels skipped) + +op_45_xtvidput: +mov ebx, edi ; ebx = saved data stack pointer for reading arguments +mov eax, [es:ebx] ; eax = y coordinate +mov [cory], eax ; store y coordinate +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = x coordinate +mov [corx], eax ; store x coordinate + +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = addr2 (destination image virtual address) +add eax, [xms_addr] ; convert virtual address to physical address +mov ecx, [es:eax] ; ecx = destination image width +mov [img2x], ecx ; store destination image width +add eax, 4 ; advance to height field +mov ecx, [es:eax] ; ecx = destination image height +mov [img2y], ecx ; store destination image height +add eax, 4 ; advance past header to pixel data +mov [img2a], eax ; store destination image data address + +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = addr1 (source image virtual address) +add eax, [xms_addr] ; convert virtual address to physical address +mov ecx, [es:eax] ; ecx = source image width +mov [img1x], ecx ; store source image width +add eax, 4 ; advance to height field +mov ecx, [es:eax] ; ecx = source image height +mov [img1y], ecx ; store source image height +add eax, 4 ; advance past header to pixel data +mov [img1a], eax ; store source image data address + +add ebx, 4 ; advance past all arguments +mov edi, ebx ; pop all four arguments off the data stack + +cmp dword [cory] , 0 ; calculate Y start: is y >= 0? +jl tvidl1 ; if y < 0, need to clip from top +mov dword [starty], 0 ; y >= 0: start copying from row 0 of source +jmp tvidl2 +tvidl1: +mov eax, [cory] ; eax = negative y offset +neg eax ; eax = number of rows to skip in source +mov [starty], eax ; store start row (skip clipped rows) +tvidl2: + +cmp dword [corx] , 0 ; calculate X start: is x >= 0? +jl tvidl3 ; if x < 0, need to clip from left +mov dword [startx], 0 ; x >= 0: start copying from column 0 of source +jmp tvidl4 +tvidl3: +mov eax, [corx] ; eax = negative x offset +neg eax ; eax = number of columns to skip in source +mov [startx], eax ; store start column (skip clipped columns) +tvidl4: + +mov eax, [cory] ; calculate Y end: does source extend past destination? +add eax, [img1y] ; eax = y + source height +cmp eax, [img2y] ; compare with destination height +jg tvidl5 ; if exceeds destination, clip +mov eax, [img1y] ; no clipping needed: end = source height +mov [endy], eax ; store Y end +jmp tvidl6 +tvidl5: +mov eax, [img2y] ; eax = destination height +sub eax, [cory] ; eax = destination height - y (max rows that fit) +mov [endy], eax ; store clipped Y end +tvidl6: + +mov eax, [corx] ; calculate X end: does source extend past destination? +add eax, [img1x] ; eax = x + source width +cmp eax, [img2x] ; compare with destination width +jg tvidl7 ; if exceeds destination, clip +mov eax, [img1x] ; no clipping needed: end = source width +mov [endx], eax ; store X end +jmp tvidl8 +tvidl7: +mov eax, [img2x] ; eax = destination width +sub eax, [corx] ; eax = destination width - x (max columns that fit) +mov [endx], eax ; store clipped X end +tvidl8: + +mov eax, [endy] ; calculate Y length (number of rows to copy) +sub eax, [starty] ; eax = endy - starty +cmp eax, 0 ; check if any rows to copy +jle emu ; if zero or negative, nothing to draw +mov [lengthy], eax ; store row count + +mov eax, [endx] ; calculate X length (number of columns to copy) +sub eax, [startx] ; eax = endx - startx +cmp eax, 0 ; check if any columns to copy +jle emu ; if zero or negative, nothing to draw +mov [lengthx], eax ; store column count + +mov eax, [starty] ; calculate source image start address +mov ebx, [img1x] ; ebx = source image width (stride) +sub edx, edx ; clear edx for multiplication +mul ebx ; eax = starty * source width +add eax, [img1a] ; add source data base address +add eax, [startx] ; add starting column offset +mov [img1start], eax ; store source start address + +mov eax, [cory] ; calculate destination image start address +add eax, [starty] ; eax = y + starty (destination row) +mov ebx, [img2x] ; ebx = destination image width (stride) +sub edx, edx ; clear edx for multiplication +mul ebx ; eax = destination row * destination width +add eax, [img2a] ; add destination data base address +add eax, [corx] ; add x coordinate offset +add eax, [startx] ; add starting column offset +mov [img2start], eax ; store destination start address + +tvidl9: +mov ebx, [img1start] ; ebx = current source row address +mov ecx, [lengthx] ; ecx = number of pixels to copy per row +mov edx, [img2start] ; edx = current destination row address + +tmemmove: ; transparent copy: ebx=from, edx=to, ecx=count +cmp ecx, 0 ; check if remaining count is zero +je tl11 ; if zero, done with this row +mov al, [es:ebx] ; al = source pixel +cmp al, 255 ; is pixel transparent (0xFF)? +je tl12 ; if transparent, skip writing to destination +mov [es:edx], al ; copy non-transparent pixel to destination +tl12: +inc ebx ; advance source pointer +inc edx ; advance destination pointer +dec ecx ; decrement remaining pixel count +jmp tmemmove ; repeat for next pixel +tl11: + +mov eax, [img1x] ; eax = source image width (stride) +add [img1start], eax ; advance source address to next row +mov eax, [img2x] ; eax = destination image width (stride) +add [img2start], eax ; advance destination address to next row +dec dword [lengthy] ; decrement remaining row count +cmp [lengthy], 0 ; check if more rows to copy +jg tvidl9 ; if yes, copy next row + +jmp emu ; return to emulation loop diff --git a/emulator/tvidput.inc b/emulator/tvidput.inc deleted file mode 100644 index 3d100d1..0000000 --- a/emulator/tvidput.inc +++ /dev/null @@ -1,173 +0,0 @@ -; Blit image with transparency support -; -; Stack Effect: addr1 addr2 x y -- -; -; Copies a portion of image1 to image2 at the specified (x, y) -; coordinates with transparency support. Pixels in image1 with value -; 255 (0xFF) are treated as transparent and are not copied to the -; destination. -; -; Parameters: -; - addr1: Address of the source image structure (width, height, data) -; - addr2: Address of the destination image structure -; - x: X-coordinate in destination where to start copying -; - y: Y-coordinate in destination where to start copying -; -; Image Structure Format: -; - Offset 0: Image width (32-bit) -; - Offset 4: Image height (32-bit) -; - Offset 8: Base address of image data (32-bit pointer) -; -; Example: -; 0x1000 ; Source image structure -; 0x2000 ; Destination image structure -; 50 ; x -; 50 ; y -; tvidput -; -; Memory layout before execution: -; [es:edi] = y -; [es:edi+4] = x -; [es:edi+8] = addr2 -; [es:edi+12] = addr1 -; -; Memory layout after execution: -; Destination image updated with source image data (transparent pixels skipped) - -op_45_xtvidput: -mov ebx, edi ; ebx = saved data stack pointer for reading arguments -mov eax, [es:ebx] ; eax = y coordinate -mov [cory], eax ; store y coordinate -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = x coordinate -mov [corx], eax ; store x coordinate - -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = addr2 (destination image virtual address) -add eax, [xms_addr] ; convert virtual address to physical address -mov ecx, [es:eax] ; ecx = destination image width -mov [img2x], ecx ; store destination image width -add eax, 4 ; advance to height field -mov ecx, [es:eax] ; ecx = destination image height -mov [img2y], ecx ; store destination image height -add eax, 4 ; advance past header to pixel data -mov [img2a], eax ; store destination image data address - -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = addr1 (source image virtual address) -add eax, [xms_addr] ; convert virtual address to physical address -mov ecx, [es:eax] ; ecx = source image width -mov [img1x], ecx ; store source image width -add eax, 4 ; advance to height field -mov ecx, [es:eax] ; ecx = source image height -mov [img1y], ecx ; store source image height -add eax, 4 ; advance past header to pixel data -mov [img1a], eax ; store source image data address - -add ebx, 4 ; advance past all arguments -mov edi, ebx ; pop all four arguments off the data stack - -cmp dword [cory] , 0 ; calculate Y start: is y >= 0? -jl tvidl1 ; if y < 0, need to clip from top -mov dword [starty], 0 ; y >= 0: start copying from row 0 of source -jmp tvidl2 -tvidl1: -mov eax, [cory] ; eax = negative y offset -neg eax ; eax = number of rows to skip in source -mov [starty], eax ; store start row (skip clipped rows) -tvidl2: - -cmp dword [corx] , 0 ; calculate X start: is x >= 0? -jl tvidl3 ; if x < 0, need to clip from left -mov dword [startx], 0 ; x >= 0: start copying from column 0 of source -jmp tvidl4 -tvidl3: -mov eax, [corx] ; eax = negative x offset -neg eax ; eax = number of columns to skip in source -mov [startx], eax ; store start column (skip clipped columns) -tvidl4: - -mov eax, [cory] ; calculate Y end: does source extend past destination? -add eax, [img1y] ; eax = y + source height -cmp eax, [img2y] ; compare with destination height -jg tvidl5 ; if exceeds destination, clip -mov eax, [img1y] ; no clipping needed: end = source height -mov [endy], eax ; store Y end -jmp tvidl6 -tvidl5: -mov eax, [img2y] ; eax = destination height -sub eax, [cory] ; eax = destination height - y (max rows that fit) -mov [endy], eax ; store clipped Y end -tvidl6: - -mov eax, [corx] ; calculate X end: does source extend past destination? -add eax, [img1x] ; eax = x + source width -cmp eax, [img2x] ; compare with destination width -jg tvidl7 ; if exceeds destination, clip -mov eax, [img1x] ; no clipping needed: end = source width -mov [endx], eax ; store X end -jmp tvidl8 -tvidl7: -mov eax, [img2x] ; eax = destination width -sub eax, [corx] ; eax = destination width - x (max columns that fit) -mov [endx], eax ; store clipped X end -tvidl8: - -mov eax, [endy] ; calculate Y length (number of rows to copy) -sub eax, [starty] ; eax = endy - starty -cmp eax, 0 ; check if any rows to copy -jle emu ; if zero or negative, nothing to draw -mov [lengthy], eax ; store row count - -mov eax, [endx] ; calculate X length (number of columns to copy) -sub eax, [startx] ; eax = endx - startx -cmp eax, 0 ; check if any columns to copy -jle emu ; if zero or negative, nothing to draw -mov [lengthx], eax ; store column count - -mov eax, [starty] ; calculate source image start address -mov ebx, [img1x] ; ebx = source image width (stride) -sub edx, edx ; clear edx for multiplication -mul ebx ; eax = starty * source width -add eax, [img1a] ; add source data base address -add eax, [startx] ; add starting column offset -mov [img1start], eax ; store source start address - -mov eax, [cory] ; calculate destination image start address -add eax, [starty] ; eax = y + starty (destination row) -mov ebx, [img2x] ; ebx = destination image width (stride) -sub edx, edx ; clear edx for multiplication -mul ebx ; eax = destination row * destination width -add eax, [img2a] ; add destination data base address -add eax, [corx] ; add x coordinate offset -add eax, [startx] ; add starting column offset -mov [img2start], eax ; store destination start address - -tvidl9: -mov ebx, [img1start] ; ebx = current source row address -mov ecx, [lengthx] ; ecx = number of pixels to copy per row -mov edx, [img2start] ; edx = current destination row address - -tmemmove: ; transparent copy: ebx=from, edx=to, ecx=count -cmp ecx, 0 ; check if remaining count is zero -je tl11 ; if zero, done with this row -mov al, [es:ebx] ; al = source pixel -cmp al, 255 ; is pixel transparent (0xFF)? -je tl12 ; if transparent, skip writing to destination -mov [es:edx], al ; copy non-transparent pixel to destination -tl12: -inc ebx ; advance source pointer -inc edx ; advance destination pointer -dec ecx ; decrement remaining pixel count -jmp tmemmove ; repeat for next pixel -tl11: - -mov eax, [img1x] ; eax = source image width (stride) -add [img1start], eax ; advance source address to next row -mov eax, [img2x] ; eax = destination image width (stride) -add [img2start], eax ; advance destination address to next row -dec dword [lengthy] ; decrement remaining row count -cmp [lengthy], 0 ; check if more rows to copy -jg tvidl9 ; if yes, copy next row - -jmp emu ; return to emulation loop diff --git a/emulator/vidput.asm b/emulator/vidput.asm new file mode 100644 index 0000000..c9151bf --- /dev/null +++ b/emulator/vidput.asm @@ -0,0 +1,177 @@ +; Blit image without transparency +; +; Stack Effect: addr1 addr2 x y -- +; +; Copies a portion of image1 to image2 at the specified (x, y) +; coordinates with clipping. Every pixel is copied regardless of value. +; +; Parameters: +; - addr1: Address of the source image structure (width, height, data) +; - addr2: Address of the destination image structure +; - x: X-coordinate in destination where to start copying +; - y: Y-coordinate in destination where to start copying +; +; Image Structure Format: +; - Offset 0: Image width (32-bit) +; - Offset 4: Image height (32-bit) +; - Offset 8: Base address of image data (32-bit pointer) +; +; Example: +; 0x1000 ; Source image structure +; 0x2000 ; Destination image structure +; 50 ; x +; 50 ; y +; vidput +; +; Memory layout before execution: +; [es:edi] = y +; [es:edi+4] = x +; [es:edi+8] = addr2 +; [es:edi+12] = addr1 +; +; Memory layout after execution: +; Destination image updated with source image data + +op_42_xvidput: +mov ebx, edi ; ebx = saved data stack pointer for reading arguments +mov eax, [es:ebx] ; eax = y coordinate +mov [cory], eax ; store y coordinate +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = x coordinate +mov [corx], eax ; store x coordinate + +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = addr2 (destination image virtual address) +add eax, [xms_addr] ; convert virtual address to physical address +mov ecx, [es:eax] ; ecx = destination image width +mov [img2x], ecx ; store destination image width +add eax, 4 ; advance to height field +mov ecx, [es:eax] ; ecx = destination image height +mov [img2y], ecx ; store destination image height +add eax, 4 ; advance past header to pixel data +mov [img2a], eax ; store destination image data address + +add ebx, 4 ; advance to next stack slot +mov eax, [es:ebx] ; eax = addr1 (source image virtual address) +add eax, [xms_addr] ; convert virtual address to physical address +mov ecx, [es:eax] ; ecx = source image width +mov [img1x], ecx ; store source image width +add eax, 4 ; advance to height field +mov ecx, [es:eax] ; ecx = source image height +mov [img1y], ecx ; store source image height +add eax, 4 ; advance past header to pixel data +mov [img1a], eax ; store source image data address + +add ebx, 4 ; advance past all arguments +mov edi, ebx ; pop all four arguments off the data stack + +cmp dword [cory] , 0 ; calculate Y start: is y >= 0? +jl vidl1 ; if y < 0, need to clip from top +mov dword [starty], 0 ; y >= 0: start copying from row 0 of source +jmp vidl2 +vidl1: +mov eax, [cory] ; eax = negative y offset +neg eax ; eax = number of rows to skip in source +mov [starty], eax ; store start row (skip clipped rows) +vidl2: + +cmp dword [corx] , 0 ; calculate X start: is x >= 0? +jl vidl3 ; if x < 0, need to clip from left +mov dword [startx], 0 ; x >= 0: start copying from column 0 of source +jmp vidl4 +vidl3: +mov eax, [corx] ; eax = negative x offset +neg eax ; eax = number of columns to skip in source +mov [startx], eax ; store start column (skip clipped columns) +vidl4: + +mov eax, [cory] ; calculate Y end: does source extend past destination? +add eax, [img1y] ; eax = y + source height +cmp eax, [img2y] ; compare with destination height +jg vidl5 ; if exceeds destination, clip +mov eax, [img1y] ; no clipping needed: end = source height +mov [endy], eax ; store Y end +jmp vidl6 +vidl5: +mov eax, [img2y] ; eax = destination height +sub eax, [cory] ; eax = destination height - y (max rows that fit) +mov [endy], eax ; store clipped Y end +vidl6: + +mov eax, [corx] ; calculate X end: does source extend past destination? +add eax, [img1x] ; eax = x + source width +cmp eax, [img2x] ; compare with destination width +jg vidl7 ; if exceeds destination, clip +mov eax, [img1x] ; no clipping needed: end = source width +mov [endx], eax ; store X end +jmp vidl8 +vidl7: +mov eax, [img2x] ; eax = destination width +sub eax, [corx] ; eax = destination width - x (max columns that fit) +mov [endx], eax ; store clipped X end +vidl8: + +mov eax, [endy] ; calculate Y length (number of rows to copy) +sub eax, [starty] ; eax = endy - starty +cmp eax, 0 ; check if any rows to copy +jle emu ; if zero or negative, nothing to draw +mov [lengthy], eax ; store row count + +mov eax, [endx] ; calculate X length (number of columns to copy) +sub eax, [startx] ; eax = endx - startx +cmp eax, 0 ; check if any columns to copy +jle emu ; if zero or negative, nothing to draw +mov [lengthx], eax ; store column count + +mov eax, [starty] ; calculate source image start address +mov ebx, [img1x] ; ebx = source image width (stride) +sub edx, edx ; clear edx for multiplication +mul ebx ; eax = starty * source width +add eax, [img1a] ; add source data base address +add eax, [startx] ; add starting column offset +mov [img1start], eax ; store source start address + +mov eax, [cory] ; calculate destination image start address +add eax, [starty] ; eax = y + starty (destination row) +mov ebx, [img2x] ; ebx = destination image width (stride) +sub edx, edx ; clear edx for multiplication +mul ebx ; eax = destination row * destination width +add eax, [img2a] ; add destination data base address +add eax, [corx] ; add x coordinate offset +add eax, [startx] ; add starting column offset +mov [img2start], eax ; store destination start address + +vidl9: +mov ebx, [img1start] ; ebx = current source row address +mov ecx, [lengthx] ; ecx = number of bytes (pixels) to copy per row +mov edx, [img2start] ; edx = current destination row address +call memmove ; copy one row of pixels: ebx=from, edx=to, ecx=count + +mov eax, [img1x] ; eax = source image width (stride) +add [img1start], eax ; advance source address to next row +mov eax, [img2x] ; eax = destination image width (stride) +add [img2start], eax ; advance destination address to next row +dec dword [lengthy] ; decrement remaining row count +cmp [lengthy], 0 ; check if more rows to copy +jg vidl9 ; if yes, copy next row + +jmp emu ; return to emulation loop + +cory dd 0 +corx dd 0 +img2x dd 0 +img2y dd 0 +img2a dd 0 +img1x dd 0 +img1y dd 0 +img1a dd 0 + +starty dd 0 +startx dd 0 +endy dd 0 +endx dd 0 +lengthx dd 0 +lengthy dd 0 + +img1start dd 0 +img2start dd 0 diff --git a/emulator/vidput.inc b/emulator/vidput.inc deleted file mode 100644 index c9151bf..0000000 --- a/emulator/vidput.inc +++ /dev/null @@ -1,177 +0,0 @@ -; Blit image without transparency -; -; Stack Effect: addr1 addr2 x y -- -; -; Copies a portion of image1 to image2 at the specified (x, y) -; coordinates with clipping. Every pixel is copied regardless of value. -; -; Parameters: -; - addr1: Address of the source image structure (width, height, data) -; - addr2: Address of the destination image structure -; - x: X-coordinate in destination where to start copying -; - y: Y-coordinate in destination where to start copying -; -; Image Structure Format: -; - Offset 0: Image width (32-bit) -; - Offset 4: Image height (32-bit) -; - Offset 8: Base address of image data (32-bit pointer) -; -; Example: -; 0x1000 ; Source image structure -; 0x2000 ; Destination image structure -; 50 ; x -; 50 ; y -; vidput -; -; Memory layout before execution: -; [es:edi] = y -; [es:edi+4] = x -; [es:edi+8] = addr2 -; [es:edi+12] = addr1 -; -; Memory layout after execution: -; Destination image updated with source image data - -op_42_xvidput: -mov ebx, edi ; ebx = saved data stack pointer for reading arguments -mov eax, [es:ebx] ; eax = y coordinate -mov [cory], eax ; store y coordinate -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = x coordinate -mov [corx], eax ; store x coordinate - -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = addr2 (destination image virtual address) -add eax, [xms_addr] ; convert virtual address to physical address -mov ecx, [es:eax] ; ecx = destination image width -mov [img2x], ecx ; store destination image width -add eax, 4 ; advance to height field -mov ecx, [es:eax] ; ecx = destination image height -mov [img2y], ecx ; store destination image height -add eax, 4 ; advance past header to pixel data -mov [img2a], eax ; store destination image data address - -add ebx, 4 ; advance to next stack slot -mov eax, [es:ebx] ; eax = addr1 (source image virtual address) -add eax, [xms_addr] ; convert virtual address to physical address -mov ecx, [es:eax] ; ecx = source image width -mov [img1x], ecx ; store source image width -add eax, 4 ; advance to height field -mov ecx, [es:eax] ; ecx = source image height -mov [img1y], ecx ; store source image height -add eax, 4 ; advance past header to pixel data -mov [img1a], eax ; store source image data address - -add ebx, 4 ; advance past all arguments -mov edi, ebx ; pop all four arguments off the data stack - -cmp dword [cory] , 0 ; calculate Y start: is y >= 0? -jl vidl1 ; if y < 0, need to clip from top -mov dword [starty], 0 ; y >= 0: start copying from row 0 of source -jmp vidl2 -vidl1: -mov eax, [cory] ; eax = negative y offset -neg eax ; eax = number of rows to skip in source -mov [starty], eax ; store start row (skip clipped rows) -vidl2: - -cmp dword [corx] , 0 ; calculate X start: is x >= 0? -jl vidl3 ; if x < 0, need to clip from left -mov dword [startx], 0 ; x >= 0: start copying from column 0 of source -jmp vidl4 -vidl3: -mov eax, [corx] ; eax = negative x offset -neg eax ; eax = number of columns to skip in source -mov [startx], eax ; store start column (skip clipped columns) -vidl4: - -mov eax, [cory] ; calculate Y end: does source extend past destination? -add eax, [img1y] ; eax = y + source height -cmp eax, [img2y] ; compare with destination height -jg vidl5 ; if exceeds destination, clip -mov eax, [img1y] ; no clipping needed: end = source height -mov [endy], eax ; store Y end -jmp vidl6 -vidl5: -mov eax, [img2y] ; eax = destination height -sub eax, [cory] ; eax = destination height - y (max rows that fit) -mov [endy], eax ; store clipped Y end -vidl6: - -mov eax, [corx] ; calculate X end: does source extend past destination? -add eax, [img1x] ; eax = x + source width -cmp eax, [img2x] ; compare with destination width -jg vidl7 ; if exceeds destination, clip -mov eax, [img1x] ; no clipping needed: end = source width -mov [endx], eax ; store X end -jmp vidl8 -vidl7: -mov eax, [img2x] ; eax = destination width -sub eax, [corx] ; eax = destination width - x (max columns that fit) -mov [endx], eax ; store clipped X end -vidl8: - -mov eax, [endy] ; calculate Y length (number of rows to copy) -sub eax, [starty] ; eax = endy - starty -cmp eax, 0 ; check if any rows to copy -jle emu ; if zero or negative, nothing to draw -mov [lengthy], eax ; store row count - -mov eax, [endx] ; calculate X length (number of columns to copy) -sub eax, [startx] ; eax = endx - startx -cmp eax, 0 ; check if any columns to copy -jle emu ; if zero or negative, nothing to draw -mov [lengthx], eax ; store column count - -mov eax, [starty] ; calculate source image start address -mov ebx, [img1x] ; ebx = source image width (stride) -sub edx, edx ; clear edx for multiplication -mul ebx ; eax = starty * source width -add eax, [img1a] ; add source data base address -add eax, [startx] ; add starting column offset -mov [img1start], eax ; store source start address - -mov eax, [cory] ; calculate destination image start address -add eax, [starty] ; eax = y + starty (destination row) -mov ebx, [img2x] ; ebx = destination image width (stride) -sub edx, edx ; clear edx for multiplication -mul ebx ; eax = destination row * destination width -add eax, [img2a] ; add destination data base address -add eax, [corx] ; add x coordinate offset -add eax, [startx] ; add starting column offset -mov [img2start], eax ; store destination start address - -vidl9: -mov ebx, [img1start] ; ebx = current source row address -mov ecx, [lengthx] ; ecx = number of bytes (pixels) to copy per row -mov edx, [img2start] ; edx = current destination row address -call memmove ; copy one row of pixels: ebx=from, edx=to, ecx=count - -mov eax, [img1x] ; eax = source image width (stride) -add [img1start], eax ; advance source address to next row -mov eax, [img2x] ; eax = destination image width (stride) -add [img2start], eax ; advance destination address to next row -dec dword [lengthy] ; decrement remaining row count -cmp [lengthy], 0 ; check if more rows to copy -jg vidl9 ; if yes, copy next row - -jmp emu ; return to emulation loop - -cory dd 0 -corx dd 0 -img2x dd 0 -img2y dd 0 -img2a dd 0 -img1x dd 0 -img1y dd 0 -img1a dd 0 - -starty dd 0 -startx dd 0 -endy dd 0 -endx dd 0 -lengthx dd 0 -lengthy dd 0 - -img1start dd 0 -img2start dd 0 diff --git a/kernel/compile.sh b/kernel/compile.sh new file mode 100755 index 0000000..33caaac --- /dev/null +++ b/kernel/compile.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Compile the Fifth virtual machine emulator using FASM (Flat Assembler). +# This script checks whether fasm is installed and offers to install it +# via apt-get if it is missing, then assembles emulator.asm into the +# DOS COM binary (emulator.com). + +if ! command -v fasm &> /dev/null; then + echo "fasm (flat assembler) is not installed." + read -p "Would you like to install it? (y/n): " choice + if [[ "$choice" =~ ^[Yy]$ ]]; then + sudo apt-get update && sudo apt-get install -y fasm + if [ $? -ne 0 ]; then + echo "Failed to install fasm." + exit 1 + fi + else + echo "fasm is required to continue. Exiting." + exit 1 + fi +fi + +fasm core.asm diff --git a/kernel/core.asm b/kernel/core.asm index 2cb74c4..a6c6583 100644 --- a/kernel/core.asm +++ b/kernel/core.asm @@ -1,6 +1,6 @@ ; core of Fifth -include 'define.inc' +include 'define.asm' link = 0 org 0 diff --git a/kernel/define.asm b/kernel/define.asm new file mode 100644 index 0000000..d8c4aa6 --- /dev/null +++ b/kernel/define.asm @@ -0,0 +1,81 @@ +; Virtual machine CPU opcodes definitions, so that we can use these opcodes to compile +; initial binary kernel using Flat Assembler. +; +; Note: Virtual CPU supports more opcodes, but we don't need them +; to build initial kernel, therefore they are not defined here. + +macro xnop +{ db 0 } +macro xhalt +{ db 1 } +macro kbd@ +{ db 2 } +macro xnum arg1 +{ db 3 + dd arg1 } +macro head arg1, arg2, arg3, arg4 +{ dd link + link = $-4 + db arg1 + db arg2 + len = (24-5)-($-link) + times len db 177 + db arg3 + dd arg4 } +macro xjmp arg1 +{ db 4 + dd arg1 } +macro xcall arg1 +{ db 5 + dd arg1 } +macro xinc +{ db 6 } +macro xdec +{ db 7 } +macro xdup +{ db 8 } +macro xdrop +{ db 9 } +macro xif arg1 +{ db 10 + dd arg1 } +macro xret +{ db 11 } +macro xc@ +{ db 12 } +macro xc! +{ db 13 } +macro xpush +{ db 14 } +macro xpop +{ db 15 } +macro xrot +{ db 17 } +macro xdisk@ +{ db 18 } +macro xdisk! +{ db 19 } +macro x@ +{ db 20 } +macro x! +{ db 21 } +macro xover +{ db 22 } +macro xswap +{ db 23 } +macro xplus +{ db 24 } +macro xminus +{ db 25 } +macro xmul +{ db 26 } +macro xcmpg +{ db 28 } +macro xcmpl +{ db 29 } +macro xcprt! +{ db 33 } +macro xcmove +{ db 43 } +macro xcfill +{ db 44 } diff --git a/kernel/define.inc b/kernel/define.inc deleted file mode 100644 index e8785af..0000000 --- a/kernel/define.inc +++ /dev/null @@ -1,79 +0,0 @@ -; Virtual CPU machine code definitions -; For assembling with FASM (Flat Assembler). -; Rest is defined in highlevel code. - -macro xnop -{ db 0 } -macro xhalt -{ db 1 } -macro kbd@ -{ db 2 } -macro xnum arg1 -{ db 3 - dd arg1 } -macro head arg1, arg2, arg3, arg4 -{ dd link - link = $-4 - db arg1 - db arg2 - len = (24-5)-($-link) - times len db 177 - db arg3 - dd arg4 } -macro xjmp arg1 -{ db 4 - dd arg1 } -macro xcall arg1 -{ db 5 - dd arg1 } -macro xinc -{ db 6 } -macro xdec -{ db 7 } -macro xdup -{ db 8 } -macro xdrop -{ db 9 } -macro xif arg1 -{ db 10 - dd arg1 } -macro xret -{ db 11 } -macro xc@ -{ db 12 } -macro xc! -{ db 13 } -macro xpush -{ db 14 } -macro xpop -{ db 15 } -macro xrot -{ db 17 } -macro xdisk@ -{ db 18 } -macro xdisk! -{ db 19 } -macro x@ -{ db 20 } -macro x! -{ db 21 } -macro xover -{ db 22 } -macro xswap -{ db 23 } -macro xplus -{ db 24 } -macro xminus -{ db 25 } -macro xmul -{ db 26 } -macro xcmpg -{ db 28 } -macro xcmpl -{ db 29 } -macro xcprt! -{ db 33 } -macro xcmove -{ db 43 } -macro xcfill -{ db 44 }