Fifth - virtual machine opcodes 10 – 19

Table of Contents

1. Overview

This document describes virtual machine opcodes 10 through 19. These opcodes provide conditional branching, subroutine return, byte-level memory access, stack-to-return-stack operations, stack rotation, and disk I/O.

Quick Reference:

Opcode Name Stack Effect Bytecode Size Purpose
10 if flag -- 5 bytes Conditional jump (jump if zero)
11 ret -- 1 byte Return from subroutine
12 c@ addr – byte 1 byte Read byte from memory
13 c! byte addr -- 1 byte Write byte to memory
14 push n -- 1 byte Move data to return stack
15 pop – n 1 byte Move data from return stack
16 unused -- 1 byte Reserved for future use. Currently acts as nop.
17 rot a b c – b c a 1 byte Rotate three stack elements
18 disk@ sector addr -- 1 byte Read 1KB sector from disk
19 disk! addr sector -- 1 byte Write 1KB sector to disk

2. 10: if (Conditional Jump)

Property Value
Opcode 10 (0x0A)
Name if
Stack ( flag – )
Bytecode 0A followed by 4-byte target address

Description:

Pops the top value from the data stack. If the value is zero, jumps to the address embedded in the instruction stream. If the value is non-zero, skips the address and continues with the next instruction.

This "jump if false" semantics is exactly what is needed to jump/skip over code because comparison condition was not met:

#1: <comparison logic, leaves comparison result on the top of data stack>
#2: <jmp instruction + pointer to #4 address>
#3:   <this code will be executed conditionally, if comparison was true>
#4: <any other code that follows after IF ... THEN ... block.>

Bytecode Format:

0A aa aa aa aa
│  └──────────┘ 32-bit target address (little-endian)
└ opcode

When to Use

  • Implementing conditional branches in control structures
  • Building if-then-else constructs (the "else" branch)
  • Loop exit conditions

Important Notes:

  • The jump is taken when flag is ZERO (false condition)
  • This is actually "jump if false" semantics
  • High-level Fifth words like if then else compile to this opcode
  • The address is a virtual address in the VM's address space

3. 11: ret (Return from Subroutine)

Property Value
Opcode 11 (0x0B)
Name ret
Stack ( – )
R. Stack ( ret-addr – )
Bytecode Single byte: 0B

Description:

Returns from a subroutine by popping the return address from the return stack and jumping to it. This is the counterpart to the call opcode (5).

When to Use:

  • Ending subroutine/word definitions
  • Early exit from subroutines

Example:

; Subroutine at address 0x2000:
03 2A 00 00 00          ; num 42 - push a value
0B                      ; ret - return to caller

In Fifth source code:

: myword ( -- n )
  2A                    \ push 42
;                       \ compiles to ret

3.1. Important Notes

  • Each ret must have a matching call to maintain return stack balance
  • Unbalanced call/ret pairs will corrupt the return stack
  • The return stack is also used by push and pop opcodes
  • Return addresses are virtual addresses (without xms_addr offset)

4. 12: c@ (Fetch Byte from Memory)

Property Value
Opcode 12 (0x0C)
Name c@ (c-fetch)
Stack ( addr – byte )
Bytecode Single byte: 0C

Description:

Reads a single byte from the specified memory address and pushes it onto the data stack. The byte value is zero-extended to 32 bits (padded with zeros in the upper 24 bits).

When to Use:

  • Reading character data from strings
  • Parsing binary data structures
  • Reading individual pixels from image buffers

Example:

Read a byte from address 0x1000:

03 00 10 00 00      ; num 0x1000 - push address
0C                  ; c@ - read byte
; Stack now contains: byte-value (0-255, zero-extended)

Important Notes:

  • The byte is zero-extended: reading 0xFF gives 0x000000FF on stack
  • The address is a virtual address (xms_addr is added internally)

5. 13: c! (Store Byte to Memory)

Property Value
Opcode 13 (0x0D)
Name c! (c-store)
Stack ( byte addr – )
Bytecode Single byte: 0D

Description:

Stores a single byte to the specified memory address. The byte value is taken from the low 8 bits of the value on the stack. The upper 24 bits are ignored.

When to Use:

  • Writing character data to strings
  • Building binary data structures
  • Drawing individual pixels to image buffers

Example:

Store byte 0x42 at address 0x1000:

03 42 00 00 00      ; num 0x42 - byte value to store
03 00 10 00 00      ; num 0x1000 - destination address
0D                  ; c! - store byte
; Memory at 0x1000 now contains 0x42

Important Notes:

  • Upper 24 bits are ignored (no error if value > 255)
  • The address is a virtual address

6. 14: push (Move Data to Return Stack)

Property Value
Opcode 14 (0x0E)
Name push
Stack ( n – )
R. Stack ( – n )
Bytecode Single byte: 0E

Description:

Moves the top value from the data stack to the return stack. This provides temporary storage that doesn't interfere with data stack operations.

When to Use:

  • Temporarily saving values during complex stack manipulations

Example:

Save a value for later retrieval:

03 2A 00 00 00      ; num 42 - push value onto data stack
0E                  ; push - move 42 to return stack
; Data stack is now empty
; Return stack now contains 42

; ... do other work ...

0F                  ; pop - retrieve 42 from return stack
; Data stack now contains 42

Important Notes:

  • Must be balanced with pop to avoid return stack corruption
  • Do not mix carelessly with call /=ret= pairs
  • The return stack grows downward (like the data stack)
  • Popping too many times can corrupt return addresses

7. 15: pop (Move Data from Return Stack)

Property Value
Opcode 15 (0x0F)
Name pop
Stack ( – n )
R. Stack ( n – )
Bytecode Single byte: 0F

Description:

Moves the top value from the return stack to the data stack. This is the inverse of the push opcode.

When to Use:

  • Retrieving temporarily saved values

Example:

Retrieve a saved value:

; Assuming return stack contains 42 (from previous 'push')
0F                  ; pop - move 42 from return stack to data stack
; Data stack now contains 42
; Return stack top item removed

Important Notes:

  • Popping from an empty return stack causes undefined behavior
  • Always ensure there's a value on the return stack before calling pop
  • Balance every push with a corresponding pop

7.1. Related Opcode: i

The i opcode (31) copies (rather than moves) the top of the return stack to the data stack, leaving the return stack unchanged.

Opcode Action R. Stack Effect
i Copy top to data stack <unchanged>
pop Move top to data stack n --

8. 16: (Unused/Reserved)

Opcode 16 (0x10) is reserved for future use. Opcode currently behaves as nop instruction.

9. 17: rot (Rotate Three Stack Elements)

Property Value
Opcode 17 (0x11)
Name rot
Stack ( n1 n2 n3 – n2 n3 n1 )
Bytecode Single byte: 11

Description

Rotates the top three values on the data stack. The third item from the top moves to the top, while the top two items shift down.

Visual Representation:

Before:  [ ... n1 n2 n3 ]   (n3 is on top)
After:   [ ... n2 n3 n1 ]   (n1 is now on top)

Rotation direction: the deepest of the three (n1) rotates to the top.

When to Use:

  • Accessing values buried deeper on the stack
  • Swapping values in multi-item calculations

Example:

03 01 00 00 00      ; num 1 - push n1
03 02 00 00 00      ; num 2 - push n2
03 03 00 00 00      ; num 3 - push n3
; Stack: [ 1 2 3 ] with 3 on top

11                  ; rot
; Stack: [ 2 3 1 ] with 1 on top

Important Notes:

  • Requires at least three items on the data stack
  • Rotating with fewer items causes undefined behavior
  • This is a rotation, not a swap - all three elements move

10. 18: disk@ (Read Disk Sector)

Property Value
Opcode 18 (0x12)
Name disk@ (disk-fetch)
Stack ( sector addr – )
Bytecode Single byte: 12

Description:

Reads one sector (1024 bytes) from the virtual disk into memory at the specified address.

Parameters:

  • sector (top of stack): Sector number to read from (0-based)
  • addr (second): Destination memory address for the data

When to Use:

  • Loading program code from disk
  • Reading data files
  • Accessing filesystem structures

Example:

Read sector 16 into memory at 0x2000:

03 10 00 00 00      ; num 16 - sector number
03 00 20 00 00      ; num 0x2000 - destination address
12                  ; disk@ - read sector
; 1024 bytes from sector 16 now at address 0x2000

10.1. Technical Details

  • One sector = 1024 bytes (1 KB)
  • Sector numbering starts at 0
  • Uses DOS file I/O to access the virtual disk image
  • The virtual disk is typically a file named disk.img or similar

10.2. Important Notes

  • The address is a virtual address in the VM's address space
  • Reading beyond the end of the disk file may return zeros or cause errors
  • The disk is accessed through DOS file handles, not BIOS interrupts

11. 19: disk! (Write Disk Sector)

Property Value
Opcode 19 (0x13)
Name disk! (disk-store)
Stack ( addr sector – )
Bytecode Single byte: 13

Description

Writes one sector (1024 bytes) from memory to the virtual disk at the specified sector number.

Parameters:

  • addr (top of stack): Source memory address
  • sector (second): Sector number to write to (0-based)

When to Use:

  • Saving program data to disk
  • Modifying filesystem structures
  • Persisting state across emulator sessions

Example:

Write memory at 0x2000 to sector 16:

03 00 20 00 00      ; num 0x2000 - source address
03 10 00 00 00      ; num 16 - sector number
13                  ; disk! - write sector
; 1024 bytes from address 0x2000 written to sector 16

Technical Details:

  • One sector = 1024 bytes (1 KB)
  • Data is first copied to a temporary buffer in conventional memory before being written to disk (required for XMS memory access)
  • Writing to sector 0 may corrupt the bootloader/kernel

Stack Order Note:

The stack order is ( addr sector -- ), which is reversed from disk@ ( sector addr -- ). This is because the data source (addr) is "produced" first, then the destination (sector) is specified.

Important Notes

  • The address is a virtual address
  • Writing to the disk image is immediate (no buffering)
  • Be careful not to overwrite critical sectors (kernel, filesystem)

Created: 2026-02-24 Tue 23:35

Validate