Fifth - virtual machine, operating system, programming language
Table of Contents
1. General
- This program is free software: released under Creative Commons Zero (CC0) license
- Program author:
- Svjatoslav Agejenko
- Homepage: https://svjatoslav.eu
- Email: mailto://svjatoslav@svjatoslav.eu
- Other software projects hosted at svjatoslav.eu
1.1. Source code
- Download latest snapshot in TAR GZ format
- Browse Git repository online
Clone Git repository using command:
git clone https://www3.svjatoslav.eu/git/fifth.git
2. Introduction
Fifth is self-hosting hobby computing environment that integrates a custom virtual machine, a Forth-inspired programming language, and operating system.
At its core lies a stack-based virtual CPU with two stacks (data and return), approximately 50 instructions, and a 4GB flat address space. This virtual machine executes the Fifth language — a concise, interactive, and extensible environment where every operation is a command that can be defined, redefined, or extended by the user. The language uses a custom character encoding (FSCII) with unique representations for control characters (e.g., space as FF instead of 20 in ASCII) and features an innovative hexadecimal number system visualized as squares split into four triangles, each representing a single bit—similar to Bibi-binary.
It includes a disk-based filesystem, a built-in text editor, 2D graphics capabilities, mouse and keyboard drivers, and tools for file management and memory allocation.
Released under the CC0 public domain license, Fifth is free for anyone to use, study, and modify. Whether you're a retro computing enthusiast, a systems programming student, or a curious developer.
2.1. Screenshots
Startup screen diplaying Fifth logo and full file list.
Sample words defined. Most of the words are commands that can be executed interactively from the command line or from a file. When executed, they can be selectively compiled or interpreted.
Built in text editor.
3. Installation
Just unpack all files, witout altering original directory structure, somewhere in your hard disk. For example:
C:\MISC\FIFTH\
To run fifth you need minimally just 2 files:
- EMULATOR.COM
- Virtual CPU emulator
- DISK.RAW
- Virtual disk file
For more information, please refer to Fifth distribution directory tree description.
4. Fifth distribution directory tree description
After downloading and unpacking the ZIP file you shoud get directory tree similar to this:
DOC - Fifth documentation
commands - documentation on Fifth built-in commands
modules - documentation on additional commands, realized as loadable modules
shots - Fifth screenshots
imageFile - files contained within 'disk.raw', just an extracted form.
source - source files
emulator - emulator source
util - utilites
disk.raw - Virtual disk file, has filesystem inside.
emulator.com - main executable.
5. Requirements
5.1. Software
- MS-DOS 6.22 with HIMEM.SYS loaded.
- Mouse driver (optional, if you have a mouse).
- CPU is initialized into Unreal Mode during operation.
- To recompile ASM sources, you can use FASM (Flat Assembler).
- To run Quick Basic utilities, use Microsoft Quick Basic 4.5.
- VESA support through BIOS or external driver (UNIVBE).
5.2. Hardware
- A minimum of a i386 CPU.
- 64 KB of free RAM below 640KB.
- 2 MB of free extended memory.
- A VESA-compatible video card.
6. Numbers representation within Fifth
Because we are in full experimentation mode here (no regard for compatibility whatsoever), why not to try also alternative number representation ?
Here alternative hexadecimal number representation format is devised:
Essentially square is split into 4 triangles. Each triangle represents one bit.
Fifth uses this hexadecimal format as primary throughout entire system.
See also: Bibi-binary.
7. Disk file map and its data structures
The `disk.raw` file is a raw disk image that contains both the boot code (loaded before filesystem initialization) and the filesystem structure. The disk layout is as follows:
7.1. Disk Allocation Table
| Offset | Length | Description |
|---|---|---|
| 0 | ~4 KiB | Operating system kernel in virtual CPU byte-code |
| 4 KiB | ~32 KiB | Human readable, early system initialization code |
| 37 KiB | ~65 KiB | FAT (File Allocation Table) |
| 101 KiB | ~16 MiB | Filesystem data area (stores file contents and directory structures) |
7.2. FAT Entry Format
The FAT tracks which disk sectors belong to each file.
| Code | Meaning |
|---|---|
| -2 | Last sector of a file chain |
| -1 | Unused (empty) sector |
| 0 – … | Pointer to the next sector in the file chain |
7.3. File Directory Entry Format
| Offset | Length | Description |
|---|---|---|
| 0 | 4 | File extension (4-byte FSCII string, e.g., "TXT ") |
| 4 | 16 | Filename (16-byte FSCII string, padded with spaces) |
| 20 | 4 | First block address |
| 24 | 4 | File size in bytes |
| 28 | 4 | Last modification timestamp (seconds since epoch) |
The directory entries are stored within the filesystem data area. Directory is just a file that list other files.
8. Core architecture
Fifth core is simply some amount of already compiled into machine code and linked together modules (entries in other words). In compilation process modules is compiled one by one and simply stored on top of already existing and growing core. Separately from core is kept dictionary, this is special list that contain names of compiled modules, variables etc. and they locations in core. Constants use dictionary space only. Random word can be removed from dictionary at any time. Currently dictionary can contain at most 1000 entries.
8.1. Dictionary entry format
| offset | length | description |
|---|---|---|
| 0 | 4 | 0 < previous entry |
| 0 = last | ||
| -1 = empty | ||
| 4 | 15 | module name string |
| 19 | 1 | entry type |
| 20 | 4 | entry data |
Core headers as linked list of module names make up something like dictionary. When some entry address is needed compiler can quickly run through headers backwards and find needed entry.
8.2. Possible module types
| type | description | "execute" action |
|---|---|---|
| 0 | data | compile "num" instruction |
| with address to module | ||
| 1 | submodule | compile "call" instruction |
| with address to module | ||
| 2 | imm. submodule | immediately call to module |
8.3. Memory map
| location | size | description |
|---|---|---|
| 0 | ~4096 | core |
| 1500000 | ~32000 | highlevel Fifth boot code |
| 200000h | core startup messages area | |
| 5200000 | end of dynamic memory space |
9. Dynamically loadable modules
9.1. Keyboard driver
KBD_@ ( – code ) get scancodes for pressed keys from keyboard.
KBD_down? ( key – result ) check is key with specified scancode
currently pressed down.
KBD_SC2FSCII ( code – FSCII ) convert key scancode into FSCII code,
or in FSK (Fifth standard keycode).
KBD_F@ ( – FSCII ) read pressed key FSCII or FSK, returns -1 if no
keys are pressed.
KBD_FW@ ( – FSCII ) read pressed key FSCII or FSK, if no keys is
are pressed then waits until there is.
FSK
—
In HEX.
FC backspace
FD TAB
FE enter
FF space
400 ESC
401 … F1 …
410 up
411 right
412 down
413 left
414 INS
415 DEL
416 home
417 end
418 PG/UP
419 PG/DN
9.2. Mouse driver
mousex var Mouse x coordinate.
mousey var Mouse y coordinate.
mousekeyl var Mouse left key.
mousekeym var Mouse middle key.
mousekeyr var Mouse right key.
mousec var Display current mouse coordinates in top left part of screen,
if true. (good for debugging)
mousepointer var Image buffer, holding current mouse pointer.
mouseadd ( ModuleAddr x1 x2 y1 y2 – ) Add specified area on screen,
into mause click buffer. If any mouse button is clicked on
that area, module at "ModuleAddr" will be executed.
mousebe var Amount of buffer elements.
mousedo ( – ) Updates mouse coordinates and keys. Parse mouse
click buffer, and draw mouse cursor to "screen".
9.3. 2D graphic library
- lineh ( color len x y imgbuf – )
- draws horisontal line from X,Y coordinates to right, with specified length.
- linev ( color len x y imgbuf – )
- draws vertical line down, from coordinates X,Y, with specified length.
- box ( color x2 x1 y2 y1 imgbuf – )
draws rectangular box. x2 bust be >= x1, y2 must be >= y1.
x1,y1-----------+ | | | | +-----------x2,y2
- flipv ( imgbuf – )
- flip image vertically.
- imgcoltrans ( ImgBuf Color ToColor – )
- Translate all pixels in specified image with "Color" into "ToColor".
- imgfill ( color x y imgbuf – )
- Fill image region starting at location X & Y with specified color.
9.4. Trigonometry functions
9.4.1. sin ( a – result )
Return sine of angle "a", where the:
- Input is scaled such that: 360 degrees = 2000 units (i.e., 1 unit = 0.18 degrees).
- The output is scaled to a 16-bit integer range of -10000 to 10000, where ±10000 represents ±1.0 in floating-point terms.
This fixed-point representation allows efficient computation using precomputed lookup tables, avoiding floating-point operations which are not supported by the virtual CPU's integer-only instruction set. The lookup table provides fast, sine values within the system's precision.
9.4.2. cos ( a – result )
Return cosine of angle "a", using the same scaling and fixed-point representation as the sin function. Input angles are scaled (360° = 2000 units), and outputs range from -10000 to 10000. Precomputed values in a lookup table ensure high performance for trigonometric calculations.
