commit c99ecaa6205325bc1aa4d29d467e93c90da3a7c4 Author: DeaDvey Date: Sat Jun 7 14:58:48 2025 +0100 initial commit, asm operating system with the MikeOS bootloader diff --git a/build-linux.sh b/build-linux.sh new file mode 100755 index 0000000..bf0a29b --- /dev/null +++ b/build-linux.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# This script assembles the CrawOS bootloader, kernel and programs +# with NASM, and then creates floppy and CD images (on Linux) + +# Only the root user can mount the floppy disk image as a virtual +# drive (loopback mounting), in order to copy across the files + +# (If you need to blank the floppy image: 'mkdosfs disk_images/crawos.flp') + + +if test "`whoami`" != "root" ; then + echo "You must be logged in as root to build (for loopback mounting)" + echo "Enter 'su' or 'sudo bash' to switch to root" + exit +fi + + +if [ ! -e disk_images/crawos.flp ] +then + echo ">>> Creating new CrawOS floppy image..." + mkdosfs -C disk_images/crawos.flp 1440 || exit +fi + + +echo ">>> Assembling bootloader..." + +nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit + + +echo ">>> Assembling CrawOS kernel..." + +cd source +nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit +cd .. + + +echo ">>> Assembling programs..." + + +echo ">>> Adding bootloader to floppy image..." + +dd status=noxfer conv=notrunc if=source/bootload/bootload.bin of=disk_images/crawos.flp || exit + + +echo ">>> Copying CrawOS kernel and programs..." + +rm -rf tmp-loop + +mkdir tmp-loop && mount -o loop -t vfat disk_images/crawos.flp tmp-loop && cp source/kernel.bin tmp-loop/ + + +sleep 0.2 + +echo ">>> Unmounting loopback floppy..." + +umount tmp-loop || exit + +rm -rf tmp-loop + + +echo ">>> Creating CD-ROM ISO image..." + +rm -f disk_images/crawos.iso +mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.flp disk_images/ || exit + +echo '>>> Done!' + +sudo qemu-system-i386 -drive file=disk_images/crawos.flp,index=0,if=floppy,format=raw + diff --git a/build-macos.sh b/build-macos.sh new file mode 100755 index 0000000..853de09 --- /dev/null +++ b/build-macos.sh @@ -0,0 +1,117 @@ +#!/bin/bash -u + +if ! [ "$(id -u)" -eq 0 ]; then + echo "[halt] Not running with superuser privileges." + exit 1 +fi + +echo "[okay] running as superuser." + +vercomp() { + [ "$1" = "$2" ] && return 0 + + local IFS=. + local i ver1=($1) ver2=($2) + unset IFS + if [ "${#ver1[@]}" -ne "${#ver2[@]}" ]; then + echo "[halt] versions being compared don't have the same form!" >&2 + echo "[halt] '$1' vs '$2'" >&2 + exit 1 + fi + + for ((i = 0; i < ${#ver1[@]}; ++i)); do + (( ${ver1[i]} > ${ver2[i]} )) && return 1 + (( ${ver1[i]} < ${ver2[i]} )) && return 2 + done + + return 0 +} + +nasm_version_check () { + vercomp $1 $2 + case $? in + 0) op='=';; + 1) op='>';; + 2) op='<';; + esac + if [ $op = '=' ] || [ $op = '>' ]; then + echo "[okay] nasm version at least '$2'" + return 0 + else + echo "[halt] nasm version is too low" >&2 + return 1 + fi +} + +# Main +declare -r NASM_VER_REGEX='[0-9]+\.[0-9]+\.[0-9]+' +declare -r MINIMUM_NASM_VERSION=2.10.09 +declare -r NASM_PATH=$(which nasm) + +declare current_nasm_version= + +if [ -z "$NASM_PATH" ]; then + echo "[halt] nasm was not found on the system! Make sure it is named nasm and is in the path." + exit 1 +fi + +current_nasm_version=$(nasm -v) + +[ $? -ne 0 ] && echo '[halt] error calling nasm' >&2 && exit 1 + +if [[ "$current_nasm_version" =~ $NASM_VER_REGEX ]]; then + current_nasm_version=${BASH_REMATCH[0]} + echo "[okay] found current nasm version of '$current_nasm_version'" +else + echo "[halt] could not determine nasm version" >&2 + exit 1 +fi + +nasm_version_check "$current_nasm_version" "$MINIMUM_NASM_VERSION" + +[ $? -ne 0 ] && echo "[halt] nasm not found or version is incompatible" >&2 && exit 1 + +"$NASM_PATH" -O0 -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit 1 +echo "[okay] assembled bootloader" + +cd source +"$NASM_PATH" -O0 -f bin -o kernel.bin kernel.asm || exit 1 +echo "[okay] assembled kernel" +cd .. + +cd programs +for i in *.asm; do + "$NASM_PATH" -O0 -f bin $i -o "$(basename $i .asm).bin" || exit 1 + echo "[okay] assembled program: $i" +done +echo "[okay] assembled all programs" +cd .. + +cp disk_images/mikeos.flp disk_images/mikeos.dmg +echo "[okay] copied floppy image" + +dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.dmg || exit 1 +echo "[okay] added bootloader to image" + +tmp_file=$(mktemp -d /tmp/$(basename $0).XXXXXX) +[ $? -ne 0 ] && echo "[halt] error creating a temp file" >&2 && exit 1 + +dev=$(echo -n $(hdid -nobrowse -nomount disk_images/mikeos.dmg)) +[ $? -ne 0 ] && echo "[halt] could not create disk from image" >&2 && exit 1 + +mount -t msdos "$dev" "$tmp_file" +[ $? -ne 0 ] && echo "[halt] could not mount "$dev"" >&2 && exit 1 + +cp source/kernel.bin "$tmp_file/" +cp programs/*.bin programs/*.bas programs/sample.pcx programs/vedithlp.txt programs/gen.4th programs/hello.512 "$tmp_file" +echo "[okay] added programs to image" + +diskutil umount "$tmp_file" +hdiutil detach "$dev" +rm -rf "$tmp_file" +echo "[okay] unmounted floppy image" + +rm -f disk_images/mikeos.iso +mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/mikeos.iso -b mikeos.dmg disk_images/ || exit 1 +echo "[okay] converted floppy to ISO-8859-1 image" +echo "[done] build completed" diff --git a/build-openbsd.sh b/build-openbsd.sh new file mode 100755 index 0000000..b47967a --- /dev/null +++ b/build-openbsd.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# This script assembles the MikeOS bootloader, kernel and programs +# with NASM, and then creates floppy and CD images (on OpenBSD) + +# Only the root user can mount the floppy disk image as a virtual +# drive (loopback mounting), in order to copy across the files + + +echo "Experimental OpenBSD build script..." + + +if test "`whoami`" != "root" ; then + echo "You must be logged in as root to build (for loopback mounting)" + echo "Enter 'su' to switch to root" + exit +fi + + +if [ ! -e disk_images/mikeos.flp ] +then + echo ">>> Creating new MikeOS floppy image..." + dd if=/dev/zero of=disk_images/mikeos.flp bs=512 count=2880 || exit + vnconfig vnd3 disk_images/mikeos.flp && newfs_msdos -f 1440 vnd3c && vnconfig -u vnd3 || exit +fi + + +echo ">>> Assembling bootloader..." + +nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit + + +echo ">>> Assembling MikeOS kernel..." + +cd source +nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit +cd .. + + +echo ">>> Assembling programs..." + +cd programs + +for i in *.asm +do + nasm -O0 -w+orphan-labels -f bin $i -o `basename $i .asm`.bin || exit +done + +cd .. + + +echo ">>> Adding bootloader to floppy image..." + +dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.flp || exit + + +echo ">>> Copying MikeOS kernel and programs..." + +rm -rf tmp-loop +vnconfig vnd3 disk_images/mikeos.flp || exit + +mkdir tmp-loop && mount -t msdos /dev/vnd3c tmp-loop && cp source/kernel.bin tmp-loop/ + +cp programs/*.bin programs/*.bas programs/sample.pcx programs/vedithlp.txt programs/gen.4th programs/hello.512 tmp-loop + +echo ">>> Unmounting loopback floppy..." + +umount tmp-loop || exit + +vnconfig -u vnd3 || exit +rm -rf tmp-loop + + +echo ">>> Creating CD-ROM ISO image..." + +rm -f disk_images/mikeos.iso +mkisofs -quiet -V 'MIKEOS' -r -J -o disk_images/mikeos.iso -b mikeos.flp disk_images/ || exit + +echo '>>> Done!' + diff --git a/buildwin.bat b/buildwin.bat new file mode 100755 index 0000000..de5693b --- /dev/null +++ b/buildwin.bat @@ -0,0 +1,40 @@ +@echo off +echo Build script for Windows +echo. + +echo Assembling bootloader... +cd source\bootload +nasm -O0 -f bin -o bootload.bin bootload.asm +cd .. + +echo Assembling MikeOS kernel... +nasm -O0 -f bin -o kernel.bin kernel.asm + +echo Assembling programs... +cd ..\programs + for %%i in (*.asm) do nasm -O0 -f bin %%i + for %%i in (*.bin) do del %%i + for %%i in (*.) do ren %%i %%i.bin +cd .. + +echo Adding bootsector to disk image... +cd disk_images +dd count=2 seek=0 bs=512 if=..\source\bootload\bootload.bin of=.\mikeos.flp +cd .. + +echo Mounting disk image... +imdisk -a -f disk_images\mikeos.flp -s 1440K -m B: + +echo Copying kernel and applications to disk image... +copy source\kernel.bin b:\ +copy programs\*.bin b:\ +copy programs\sample.pcx b:\ +copy programs\vedithlp.txt b:\ +copy programs\gen.4th b:\ +copy programs\hello.512 b:\ +copy programs\*.bas b:\ + +echo Dismounting disk image... +imdisk -D -m B: + +echo Done! diff --git a/disk_images/crawos.flp b/disk_images/crawos.flp new file mode 100644 index 0000000..5f644b3 Binary files /dev/null and b/disk_images/crawos.flp differ diff --git a/disk_images/crawos.iso b/disk_images/crawos.iso new file mode 100644 index 0000000..ff1313c Binary files /dev/null and b/disk_images/crawos.iso differ diff --git a/doc/CHANGES.TXT b/doc/CHANGES.TXT new file mode 100755 index 0000000..22ce626 --- /dev/null +++ b/doc/CHANGES.TXT @@ -0,0 +1,1057 @@ +================================================================== +MikeOS -- Open source 16-bit operating system for x86 PCs +Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT +================================================================== + + +4.7.0 (9 April 2022) +-------------------- + +# Many updates to programs/edit.asm from Pablo Gonzalez and Mark M: + add support for more than screen-visible columns; show filename on top; + show current line and column; add "open file" option; remove + unnecessary screen redraws + +# Many updates to programs/monitor.asm: separate commands to input and + execute code; 'd' command added to dump (in hex) a specified range + of memory to the screen; 'p' command added to poke (insert) a byte + into a memory location; code can now be entered in lower-case + +# Added programs/vedit.asm from John Endler: a Vi-like text editor + +# Added programs/editbin.asm from John Endler: a binary file editor + +# Added programs/codebyte.asm from John Endler: a machine code byte + editor (plus sample file hello.512) + +# Added programs/life.asm from John Endler: an implementation of Conway's + Game of Life + +# Added programs/pong.asm from John Endler: a retro Pong-like game + (press Esc to exit) + +# Added programs/line.asm from John Endler: a demo using VGA video mode + (press F to speed up, S to slow down, C to clear and Esc to exit) + +# Updated programs/forth.asm to version 1.53 (from Walt Nagel) + +# Added programs/gen.4th (referenced in the Forth manual) + +# source/features/disk.asm: updated os_get_file_list and int_filename_convert + to handle extensions with fewer than three bytes; create file uses actual + file creation date and time; full 32-bit file size returned in EBX + (transparent to older programs) + +# source/features/string.asm: new system call: os_string_to_long_int + +# source/features/math.asm: small update to pseudo-random number generator + +# source/features/ports.asm: os_serial_port_enable returns modem status in AX + +# source/features/screen.asm: added BP to register dump + +# Updated API version to 18, for new system call mentioned above + +# Renamed programs/serial.asm to programs/terminal.asm + +# Renamed build-osx.sh to build-macos.sh + +# Updated programs/sample.pcx + +# Documentation fixes and updates + + + +4.6.1 (17 March 2019) +--------------------- + +# Updated build-osx.sh (thanks to Pete Dietl) + +# Changed "KB" to "KiB" in documentation for clarity + +# Updated "MikeTron" game in EXAMPLE.BAS from TachyonOS + + + +4.6 (9 February 2019) +--------------------- + +# Added Forth program documentation (doc/handbook-forth.html) + +# Added command "ls" (long listing) to CLI + +# Improved string dump display + +# Corrected jumps out of range in string.asm + +# Updated MikeBASIC Plus Plus (MBPP.BAS) to version 4.1.0 + +# Updated Memory Manipulator (MEMEDIT.BAS) to 3.2.0 + +# Updated Calculator (CALC.BAS) to 2.1.0 + +# Updated ASCII Artist (DRAW.BAS) to 3.1.0 + +# BASIC: Added keywords STORE and LOAD to STRING command + +# os_wait_for_key now uses HLT instructions to save power + +# The CLI "dir" command now presents files in a four column format + +# Bumped API version to 17 + +# os_input_string now requires an additional parameter for output size + +# Added "!=" operator to the "if" command in the basic interpreter + +# Fixes and improvements to build and test scripts + + + +4.5 (21 December 2014) +---------------------- + +# New program: Forth interpreter (FORTH.BIN) from Walt Nagel; source code is programs/forth.asm + +# New program: Mega Archiver (ARCHIVE.BAS) from Joshua Beck + +# New game: FISHER.BIN from Jasper Ziller + +# Updated MikeBASIC Plus Plus (MBPP.BAS) to version 3.2.3 + +# Updated Memory Manipulator (MEMEDIT.BAS) to 3.1.1 + +# Updated Calculator (CALC.BAS) to version 2.0.1 + +# Updated Cosmic Flight (CF.BAS) to 2.0.2 + +# Updated ASCII Artist (DRAW.BAS) to 3.0.1 + +# Updated KEYBOARD.BIN with accidentals (from Robert Looney) + +# Updated build-openbsd.sh (from Takayoshi Sasano) + +# Updated build-osx.sh (from Caleb Xu) + +# Fix: always show cursor when returning from BASIC in EDIT.BIN + +# source/features/basic.asm: do_cls: change "int 10" to "int 10h" + +# Changed "kigalo" to "kigali" in HANGMAN.BAS + +# Changed "bueno saires" to "buenos aires" in HANGMAN.BAS + +# Changed "qemu" to "qemu-system-i386" in test-linux.sh + +# Updated URL for Windows QEMU in doc/handbook-sysdev.html + +# Handbook fixes + + + +4.4 (23 March 2013) +------------------- + +# New game: MikeOS Sudoku (SUDOKU.BAS), a puzzle game + +# New game: Cosmic Flight (CF.BAS) from Joshua + +# BASIC: string additions now possible with literal strings, other string + variables, or numeric variables, eg: $1 = $2 + "foo" + x + "bar" + +# BASIC: Use "x = VARIABLES" to determine where BASIC stores its numeric + variables + +# BASIC: New BREAK command to halt execution and show line number + +# BASIC: Now displays line numbers with error messages + +# BASIC: New CASE command from Joshua (changes case of a string) + +# BASIC: New ELSE keyword from Joshua (used with IF) + +# BASIC: New FILES command from Joshua (shows file listing from disk) + +# Updated MikeBASIC Plus Plus (MBPP.BAS) to version 3.2.1 + +# Updated Calculator (CALC.BAS) to 2.0.0 + +# Bump API to version 16 + +# Handbook fixes + + + +4.3.1 (28 April 2012) +--------------------- + +# Updated to latest version of ASCII Artist (draw.bas) + +# Updated to latest version of MikeBASIC++ (mbpp.bas) + +# source/features/basic.asm fixes from Joshua Beck + + + +4.3 (24 February 2012) +---------------------- + +# New game: MUNCHER.BAS, an apple-eating action game + +# New game: ADVNTURE.BAS, a text adventure + +# Updated to latest versions of MEMEDIT, CALC and DRAW + +# MikeBASIC++ (MBPP.BAS) library included on the disk + +# BASIC: DO + LOOP UNTIL/WHILE/ENDLESS loops implemented + +# BASIC: New STRING command to get or set bytes at locations in a string + +# BASIC: New PEEKINT and POKEINT commands + +# BASIC: INK keyword added to get current colour + +# BASIC: FOR/NEXT loops now accept variables (eg "FOR X = Y TO Z") + +# BASIC: PRINT no longer scrolls if followed by semi colon on last line + (with the exception of HEX) + +# BASIC: NUMBER added, to convert between strings and integers + +# BASIC: RENAME and SIZE commands added + +# BASIC: ASKFILE command, which shows the file selector + +# BASIC: Sums now check for division by zero and break with an error + +# BASIC: ALERT command can now take a string variable + +# BASIC: LISTBOX added -- shows list dialog box where first string + is "Foo,Bar,Baz" and second and third are help + +# BASIC: INCLUDE added, to append another BAS file onto the end of the + current one and call routines in it + +# BASIC: CURSPOS added, to get cursor position + +# BASIC: CURSCOL added, to get colour of character under the cursor + +# BASIC: Can use var = TIMER to get lower word value of system clock + +# BASIC: PAGE added to switch between working and active (display) pages + +# BASIC: LEN added to get length of string + +# BASIC: DELETE added to delete files + +# BASIC: READ added to read data from label + +# BASIC: INK command added for printing strings + +# BASIC: AND added to IF + +# BASIC: ALERT, ASKFILE and LISTBOX preserve cursor location + +# BASIC: Added VERSION keyword to get the API version + +# BASIC: SAVE returns 2 in R variable if file exists + +# USB drive floppy disk emulation updates from Mike Gonta + +# VIEWER can now read BAS files + +# SERIAL now clears screen after initial dialog box + +# HANGMAN now limits input to "a" to "z" keys (and Esc) + +# Fix CLI bug (eg running COPY internal command even if user had intended + to run a program called COPYMEGA.BIN) + +# MIKETRON.BAS removed (code included in EXAMPLE.BAS) + +# Bump API to version 15 + + + +4.2 (30 September 2011) +----------------------- + +# New program: Memory Manipulator (MEMEDIT.BAS) from Joshua Beck: a + colourful program for editing bytes in memory, written in BASIC + +# New program: ASCII Artist (DRAW.BAS) from Joshua Beck: lets you draw, + load and save images created with ASCII characters + +# New program: MikeTron Reloaded (MIKETRON.BAS) from Joshua Beck: new + features, bonuses and explosion effects + +# New program: Calculator (CALC.BAS) from Joshua Beck + +# CLI has new file management operations to complement FILEMAN program: + COPY, REN, DEL and SIZE + +# EDIT now supports the facility to make a new file with the F3 key + +# EDIT can take an existing file as a parameter at the command line: + eg "edit myfile.txt" + +# EDIT will no longer let you run BASIC on an empty file + +# CLI supports argument passing: program receives the string of parameters + in SI, or SI = 0 if no parameters are specified + +# os_run_basic now takes a parameter string in SI and copies it into the + first BASIC string ($1), unless SI = 0 + +# New system call: os_string_tokenize from Matej Horvat -- reads tokens + separated by a specified character from a string + +# os_file_remove now restores all registers to previous state after use + +# SERIAL program offers to quit out before activating serial ports + +# TEST.PCX updated and renamed to SAMPLE.PCX + +# Bugfix: os_get_time_string vector is 0054h, not 0055h + +# Reordered code inclusion: source/features/basic.asm is now last in kernel + +# Bump API to version 14 + + + +4.1.2 (18 July 2011) +-------------------- + +# Added "-O0" (no-optimisation) option to all NASM calls in the build + scripts; newer versions of NASM use optimisation by default, which + we don't want + + + +4.1.1 (20 January 2011) +----------------------- + +# source/features/screen.asm: os_list_dialog now scrollable for more + entries than can fit into the dialog box + +# source/features/cli.asm: dirlist expanded from 255 to 1024 bytes + +# source/features/screen.asm: os_file_selector: buffer expanded to + 1024 bytes + +# Build scripts now copy all .bas files in programs/ to the floppy + disk image (and not just example.bas) + +# source/features/misc.asm: os_pause rewritten by Paulo Valongo to work + with more BIOSes; now takes 110ms chunks in AX + +# source/features/disk.asm fixes from Mike Gonta: os_get_file_list now + checks for directory entries AND volume label; os_write_file routine + now properly zeroes out the .free_clusters list + +# source/features/keyboard.asm: os_check_for_key now returns 0 in AX + (and not just AL) when there's no key, as per the API docs + +# Documentation and comment fixes + + + +4.1 (17 January 2010) +--------------------- + +# BASIC variable assignment enhanced: can now take multiple values + and variables, eg "x = a + 2 * b + 3" (thanks Steve) + +# Two new system calls: os_port_byte_out and os_port_byte_in -- + send/receive bytes from ports (thanks Paulo) + +# os_serial_port_enable system call: now takes 0 in AX for normal + mode (9600 baud as before), or 1 for a new slow mode (1200 baud) + +# New SERIAL command in BASIC: "SERIAL ON 1200" or "SERIAL ON 9600" + to enable, "SERIAL SEND X" or "SERIAL SEND 50" to send a byte, + and "SERIAL REC X" to receive a byte into a variable + +# New PORT command in BASIC: "PORT OUT 1234 X" or "PORT OUT 1234 20" + to send byte to a port, and "PORT IN 1234 X" to receive a byte + +# source/features/serial.asm renamed to source/features/ports.asm + as it now contains new non-serial routines + +# os_get_random rewritten: now takes low and high values in AX and + BX, and returns random int between them (inclusive) in CX; also + has new os_seed_random routine used by the kernel (thanks Ian) + +# New RAND command in BASIC: generates a random number between two + values and stores the result in a variable + +# CLI command checking code simplified -- no need to point SI to + the input string each time (thanks Ian) + +# BASIC CURSORCHAR command is now CURSCHAR, so that it doesn't + look like a superset of the CURSOR command + +# API version bumped to 13 + +# Handbook updates and fixes + + + +4.0 (20 November 2009) +---------------------- + +# MikeOS BASIC included in the kernel; run EXAMPLE.BAS to try + it out, and see doc/handbook-appdev-basic.html for a guide + +# os_run_basic call accessible to use programs: takes AX as start + of code location, and BX as size of the code (in bytes) + +# App menu and CLI can now run .BAS programs as well as .BIN + +# EDIT.BIN can edit .BAS files; press F8 to run the + currently-being-edited code in the BASIC intepreter + +# EDIT.BIN: F5 deletes whole lines; Backspace key now functions, + although newlines still need to be removed with Delete; Esc + quits without saving -- press F2 to save (as per bottom bar) + +# If AUTORUN.BIN or AUTORUN.BAS exists on the disk, it will be + executed immediately after the kernel has loaded, before showing + the normal program launcher menu + +# EDIT.BIN now pops up an error dialog if it can't save a file + +# source/features/string.asm: os_string_strip rewritten -- shorter + and saves 256 bytes (thanks to Ian Seyler) + +# source/features/misc.asm: rewrote os_pause routine -- it now takes + AX = tenths of a second to wait (so eg AX = 30 = 3 seconds) + +# programs/hello.asm and programs/gfxdemo.asm removed (and their binaries + on the floppy) -- old and not useful now + +# os_dialog_box no longer raises a fatal error if strings are too long to + fit in the box + +# source/features/disk.asm: os_write_file no longer overwrites a file + if it already exists; instead it bails out (carry flag set) + +# API version bumped to 12 + +# source/features/disk.asm: filename checking and file writing bugfixes + +# doc/handbook-appdev.html renamed doc/handbook-appdev-asm.html + + + +3.3 (20 February 2009) +---------------------- + +# New program: EDIT.BIN -- a full-screen text editor (for Unix-formatted + text files) + +# README.TXT is no longer copied to the disk images; instead, + programs/sample.txt is added for use in EDIT.BIN + +# CLI now includes CAT command to display a file: 'CAT FOO.TXT' + +# Music keyboard (KEYBOARD.BIN) given new interface to show a + visual representation of a music keyboard + +# os_write_file now removes an older version of the specified file, + if it exists, before performing the write operation + +# CLI code (source/features/cli.asm) cleaned up -- split into sections + with fewer local labels + +# os_string_parse call is now accessible to external programs + +# Disk calls now convert a filename to uppercase automatically, so + there's no need for the calling code to do it + +# API version bumped to 11 + + + +3.2 (25 January 2009) +--------------------- + +# New system call: os_sint_to_string from Tslil -- converts a + signed integer to a string + +# os_int_to_string rewritten by Tslil; cleaner code, and no longer + needs to be passed BX for a string location (it returns a pointer + to an internal string via AX) + +# New system call: os_serial_port_enable -- initialises the port + +# Serial port is no longer initialised by the kernel, but by any + external programs that need it (eg in programs/serial.asm) + +# New system call: os_string_reverse (source/features/string.asm) + +# os_filename_convert removed; source/features/disk.asm now does + the conversion internally + +# API version bumped to 10 + +# Handbooks updated with API changes + +# build-openbsd.sh updated by Takayoshi + + + +3.1 (4 January 2009) +-------------------- + +# HANGMAN game added, in which the player works out names of cities + +# PCXVIEW program renamed to VIEWER, and can display text files + as well as images + +# FILEMAN program now has an option to show a file's size + +# New system call: os_string_charchange (source/features/string.asm), + switches all instances of a specified char to a different one + +# New system call: os_get_random (source/features/math.asm), generates + integer between 0 and 255 using the BIOS clock + +# API bumped to version 9 + +# os_draw_block routine (source/features/screen.asm) now available + to user programs + +# When a program is called from the app selector, there's no longer a + key press prompt after the program has finished + +# os_dialog_box uses coloured blocks to denote highlighted button instead + of '[=' characters + +# os_string_strip now uses its own buffer (not the OS disk buffer) + +# Keyboard codes (eg KEY_ESC) and more colours added to programs/mikedev.inc + +# os_get_file_size system call fixed + +# Registers AX, BX, CX, DX, SI, DI cleared to zero before program execution + to ease debugging + +# MONITOR program has better help text at the start + +# build-win.bat renamed buildwin.bat (more suitable in DOS) + +# Build scripts copy README.TXT to the floppy image, for reading + in the new VIEWER program + + + +3.0 (21 December 2008) +---------------------- + +# Memory map shuffled: first 24K is kernel code space; then 8K buffer for + kernel disk operations; then 32K for external programs + +# Major code simplification and cleanup: removed mouse support, + DOS support, STAKAN.BIN, testzone, CLI PROMPT command; many of these + features will continue to be developed in the TomOS project + +# Source code restructured: bootloader moved to source/bootload; + system calls now separated into multiple files in source/features/; + os_main.asm renamed kernel.asm; kernel file is now KERNEL.BIN + +# More code cleanup work: use 'mov ax, 0' instead of 'xor ax, ax' and + 'mov si, foo' instead of 'lea si, [foo]'; more comments; instances of + 8 spaces changed to tabs; hex notation now always uses 'h' suffix + (eg always '10h' and never '0x10') for consistency + +# Certain disk routines for manipulating the FAT and root directory have + been made internal to source/features/disk.asm, and not accessible to + user programs, to simplify the disk API + +# New system call: os_string_parse takes a string pointer in SI and + breaks it into zero-terminated smaller string pieces based on spaces; + eg SI = 'Foo bar baz stuff' returns AX = 'Foo', BX = 'bar', + CX = 'baz', DX = 'stuff' + +# New system call: os_string_to_int takes a decimal string (max '65535') + in SI and returns the numerical value in AX + +# File manager (FILEMAN.BIN) can now copy files (up to 28K in size), using + external program RAM -- first 4K is reserved for the file manager itself + +# os_get_file_list now returns sanitised comma-separated list of files + (eg "FOO.BIN,HELLO.TXT" instead of "FOO BIN,HELLO TXT" etc.) + +# dosbuild.bat renamed build-win.bat -- it now adds boot block and programs + to mikeos.flp using third-party tools + +# os_list_dialog rewritten: now shows selected option as a black bar, + rather than with ">>>>>" indicator + +# MONITOR.BIN updated for new memory map; now runs code ORGed at 36864 + +# When exiting a program that was launched from the menu-driven app selector, + the "Program finished" message now appears in a red bar at the bottom + +# Text with bright attributes should no longer blink on the screen + +# FILEMAN.BIN now refuses to rename a file to an existing filename + +# build-linux.sh script now creates disk_images/mikeos.flp if that + file cannot be found + +# Added README.TXT to disk/images directory; explains the purpose of each + file and how to recreate the floppy disk image + +# Removed os_get_int_handler and os_modify_int_handler system calls + +# Removed os_execute_program syscall; no longer needed + + + +2.0.0 (17 October 2008) +----------------------- + +# FAT12 write support implemented (limited to 64K files); includes system + calls to create an empty file, save data from RAM to a file, remove a + file, rename a file and more -- see source/fat12_write.asm + +# New file manager: programs/fileman.asm -- lets you delete and rename + files, and get information on the floppy fisk + +# Mouse driver from Tomasz Gorol, with system calls in + source/os_mouse_syscalls.asm and documentation in the doc/ directory; + also MOUSETST.BIN program to demonstrate it + +# New system call: os_filename_convert -- takes a normal filename such + as 'FOO.BIN' and converts it into the FAT12 equivalent of 'FOO BIN' + (first part padded out with spaces to 8 chars, no full-stop separator) + +# New system call: os_list_dialog -- takes a comma-separated and + zero-terminated string, and shows options in a list box + +# New system call: os_input_dialog -- pops up a small box with + a message, and prompts user to enter a string + +# New system call: os_string_strincmp, like os_string_compare but + limited to the number of characters passed in CL + +# os_input_string improved: can now enter and backspace through + strings spanning multiple lines + +# os_load_file now returns byte count in BX rather than sectors + +# Cursor is always restored when leaving os_file_selector + +# os_dump_registers now shows SI and DI along with AX, BX, CX, DX + +# os_int_to_string fixed -- previously it wouldn't return anything + if AX = 0; now it sets string as '0' + +# PCXVIEW.BIN refuses to display files without a .PCX extension + +# TEST.PCX is now in programs/ and copied to floppy disk when + build-linux.sh, build-openbsd.sh or build-osx.sh is run + +# os_draw_background doesn't clear screen at start, to cut down on flicker + +# At kernel start, don't try to set up a block cursor (it's not useful) + +# build-linux.sh now includes a method for blanking FAT12 floppies at the + top of the code, in the comments + +# In programs/mikedev.inc, os_string_uppercase and os_string_lowercase + were marked incorrectly as using SI rather than AX -- fixed + +# Added -w+orphan-labels to NASM calls in build-linux.sh, and fixed labels + without colons throughout OS and programs + +# Un-needed commented-out lines removed from programs/keyboard.asm + +# In source/bootload.asm, comments referred to first two bytes of FAT; + really means first two clusters -- now fixed + + + +1.4.2 (20 August 2008) +---------------------- + +# Users can now exit the minicom serial terminal program + (SERIAL.ASM) by pressing the F8 key + +# VOL command added to the CLI: displays volume label and + filesystem information for the current floppy disk + +# os_check_for_key now returns complete scancode in AX, + rather than just the key in AL + +# Various small documentation updates + + + +1.4.1 (20 July 2008) +-------------------- + +# New system call: os_dump_registers (displays the contents of + AX, BX, CX and DX in hexadecimal format) + +# System call vectors added for os_show_cursor and os_hide_cursor, + so that they're accessible to user programs + +# os_modify_int_handler now clears the interrupt flag on entry, + and sets it on exit + +# Some labels didn't have colons, triggering warnings with some + versions of NASM -- fixed + + + +1.4.0 (15 July 2008) +-------------------- + +# System call for debugging: os_dump_string, shows ASCII text and + hexadecimal dump + +# New system calls for converting numbers to text: os_print_digit, + os_print_1hex, os_print_2hex, os_print_4hex, os_long_int_to_string + +# New system calls: os_set_time_fmt and os_set_date_fmt to determine + output of os_get_time_string and os_get_date_string respectively + +# More system calls: os_get_int_handler, os_print_space, os_long_int_negate + +# Bootloader: Buffer now 8K from end of loader, removed unnecessary disk + reset calls, simplify FAT cluster calculation, FAT fixes + +# File selector now exits on Esc keypress (PCXVIEW.BIN updated accordingly) + +# New DOS function, 35h -- get interrupt vector + +# Updated FAT code in syscalls.asm as per bootloader fixes + +# Minor changes and comments to string functions + +# File selector limited to 14 names to avoid overflow down the screen + +# os_get_file_list should better handle floppies made on Windows + +# os_program_load will fail if program is too large + +# os_file_selector now shows cursor when finished + +# mikedev.inc's system call list now categorised + +# New system variables section in os_main.asm, currently holding + settings for time and date formatting + +# testzone.asm added in source directory -- a place for trying out quick + code snippets, accessible via 'TEST' in the CLI + +# LICENSE.TXT moved to doc/ directory + +# Lots of small tweaks, comment updates and cosmetic fixes + + + +1.3.1 (14 May 2008) +------------------- + +# OpenBSD build script added (build-openbsd.sh) + +# Simple PSP block moved from start of kernel to + os_execute_program routine + +# Handbook updates (links to OSes based on MikeOS, code samples + updated, Q for Mac OS X link fixed) + +# Various cosmetic code and comment cleanups + + + +1.3.0 (8 April 2008) +--------------------- + +# New 'minicom'-like serial terminal program, serial.asm in the + programs/ directory (replaces old serial.asm) + +# New pcxview.asm program to display 8-bit 320x200 PCX images, plus + test.pcx on disk images as a demo + +# os_program_load removed: new routine to load file is os_load_file, + where AX = filename and CX = location in RAM to load file; returns + BX = size of file loaded + +# New system call: os_execute_program: runs code located at 100h + +# New system call: os_get_cursor_pos -- returns DH = row of cursor + and DL = column + +# System call vectors at the start of os_main.asm cleaned up: now + they are simple jmp instructions rather than call/ret sequences + +# The CLI and program selector now refuse to execute MIKEKERN.BIN + +# os_file_selector now shows the cursor after a file is chosen + +# gfxdemo.asm now displays quit message in top-left corner + +# hardlist.asm removed from programs/ directory (and HARDLIST.BIN + removed from disk images) -- no real purpose for it + +# VLAK.BIN removed from disk image (didn't quit correctly); replaced + by STAKAN.BIN Tetris-like game + + + +1.2.0 (20 January 2008) +----------------------- + +# New monitor.asm program by Yutaka Saiko: enter machine code + instructions in hex format, followed by '$' + +# Information for new monitor.asm program added to Handbook + +# New system call: os_find_char_in_string -- locates and returns + the position of a character in a string + +# CLI now accepts complete executable names (eg 'hello.bin') + and not only short names ('hello') + +# doserror.asm removed from the programs/ directory + +# Handbook fixes + + + +1.1.1 (12 December 2007) +------------------------ + +# Mac OS X build script fixed + +# Project now hosted on BerliOS at http://mikeos.berlios.de + +# Handbook fixes + + + +1.1.0 (8 December 2007) +----------------------- + +# MikeOS API version incremented to 2 + +# New serial port support for native MikeOS programs (Ian Seyler); + os_send_via_serial and os_get_via_serial system calls, plus a + demo program (serial.asm) + +# New system call: os_get_date_string (Ian Seyler): returns + a string like '12/31/2007' + +# CLI updated with new 'TIME' and 'DATE' commands (Ian Seyler) + +# dosbuild.bat updated (Ian Seyler) + +# build-osx.sh script for OS X users added (Michael van Tellingen) + +# New Handbook information on building on Windows and Mac OS X + +# New Handbook section on the serial port + +# Handbook tweaks: mini TOC in 'Making an OS' section; new + 'Go further' links section; close
  • tags; 'Using MikeOS' + section now linked in left-hand bar; FAQ on 16-bit/asm + + + +1.0.0 (16 September 2007) +------------------------- + +# Restructured directory layout: bootloader (renamed bootload.asm) + and kernel now both in 'source' directory; new 'doc' directory + +# 'build' and 'make_disks' scripts merged into a single script + called 'build-linux.sh'; BUILD.BAT renamed DOSBUILD.BAT + +# New os_file_selector: pops up a dialog box for selecting a file; + result is a zero-terminated 11-char string pointed to by AX + +# New system call: os_string_truncate -- cuts string down to specified + number of characters from start + +# New system call: os_bcd_to_int -- converts binary coded decimal + numbers into integers + +# New system call: os_get_time_string -- generates a string with + the current time (eg '20:41') + +# os_string_chomp now strips leading spaces as well as trailing + +# os_print_blank_line renamed to os_print_newline + +# os_int_to_string updated -- now based on a public domain routine + that handles full 16-bit registers + +# CLI now strips spaces with os_string_chomp before checking for blank + lines -- stops it complaining that ' ' (space) is not a valid program + +# os_string_strip and show_files now use os_buffer as a temporary store, + rather than their own strings (reduces kernel size by 512 bytes) + +# os_input_string fixed so that backspaced chars are zeroed-out + +# os_int_reboot internal call added, which reboots the machine + via the keyboard controller + +# Removed 'API version' from start of os_main.asm; kernel code now + starts at 8000h (bootloader updated accordingly) + +# Added os_get_api_version which returns the current API version, + as defined at the top of os_main.asm, in AL + +# Removed CLI_VER from os_cli.asm -- it's not going to be updated + outside of MikeOS so a single global version number is simpler + +# Changed 'REBOOT' to 'EXIT' in os_cli.asm -- now it doesn't + reboot but exits cleanly with a 'ret' + +# CREDITS.TXT added to list people involved in the project + + + +0.40 (16th January 2007) +------------------------ + +CHANGES BY PETER NEMETH: + +# os_syscalls.asm renamed to syscalls.asm, to support the DOS 8.3 + filename character format (NASM could not find certain files) + +# BUILD.BAT added for DOS users + +# Divide by zero handling (int 0h) added + +# Drive descriptor fixed in bootsector and some features added; + now it will not hang the system if there is a boot failure + +# Before loading a DOS program, save and clean up registers + +# DOS exit call fixed: does not restart the OS, and programs + can exit with error codes + +# DOS 'get date' interrupt added; now returns the current date + +# Some rets replaced with irets + +# DOS Ctrl+Break handler added; not yet working (IRQ 9 doesn't + call int 1Bh) + +# DOS print character via printer added + +# Some helper routines added for DOS + +# DOS CP/M compatible routines added + +# DOS reset disk added + +# DOS set/get current drive added + +# DOS set date function added + +# DOS set/get time function added + +# DOS functions sorted by function number + +# DOS unimplemented interrupt call fixed; now only exits from + program and display message, not restart OS + +# DOS serial port and modem support interrupt added; + read and write from STDAUX (COM1) + +# DOS interrupt flush buffer and read fixed; now really flush the + buffer before read + + +CHANGES BY MIKE SAUNDERS: + +# gfxdemo.asm fixed to quit properly + +# DOS set vector routine added + +# Added mini Program Segment Prefix block to os_app_data in + os_main.asm -- needs to be done properly, but VisiCalc + now starts up + + + +0.30 (12th November 2006) +------------------------- + +# New command line interface mode, currently featuring DIR, HELP, + CLS, PROMPT, VER and EXIT inbuilt commands + +# os_alert_dialog renamed os_dialog_box due to new feature: multiple + button support. If DX = 1 when called, it presents two buttons + (OK and Cancel) with the selection returned in AX + +# New system call: os_string_compare -- takes two strings and sets + the carry flag if they're the same + +# New system call: os_string_chomp -- removes trailing spaces + at the end of a string + +# New system call: os_string_strip -- removes character specified + in AX from the string in SI + +# Kernel source split into multiple files for easier editing, based + around os_main.asm which includes the rest. These kernel files + are now in kernel/, with the bootloader in bootloader/ + +# os_program_load now sets carry flag if program not found, instead + of bailing out to os_fatal_error, and also returns from a call + +# os_program_load can clear the screen before loading a program if + BX = 1. Useful for the file selector dialog + +# Changed os_pause to use BIOS call + +# Fixed zero-termination bug in os_string_copy + +# MikeOS programs that include mikedev.inc can now access the + 8K scratchpad buffer via os_buffer + +# Moved DOSTEST.ASM, for testing DOS compatibility, into the + programs/ directory (so that it's automatically built) + +# Bootloader now has error messages, rather than just freezing + +# Split up the assemble and disk-image scripts to avoid loopback + mounting errors, and simplify editing + +# Various small cleanups and fixes + + + +0.25 (27th October 2006) +------------------------ + +# New system call: os_modify_int_handler + +# Removed DOS compatibility interrupt handlers from bootloader, + replaced with code in kernel using os_modify_int_handler + +# System call for os_get_file_list routine added + +# Music keyboard demo app no longer uses 100% CPU + + + +0.24 (25th October 2006) +------------------------ + +# Released on SourceForge + + +================================================================== + diff --git a/doc/CREDITS.TXT b/doc/CREDITS.TXT new file mode 100755 index 0000000..530cba5 --- /dev/null +++ b/doc/CREDITS.TXT @@ -0,0 +1,41 @@ +================================================================== +MikeOS -- Open source 16-bit operating system for x86 PCs +Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT +================================================================== + + +PROJECT ADMIN (MAIN CODE AND HANDBOOKS) + + * Mike Saunders -- okachi@gmail.com + + +DEVELOPMENT + + * E Dehling + * Ian Seyler + * John Endler + * Joshua Beck + * Justin Tokarchuk + * Mark M + * Matej Horvat + * Michael van Tellingen + * Mike Gonta + * Pablo Gonzales + * Peter Nemeth + * Paulo Valongo + * Takayoshi Sasano + * Tomasz Gorol + * Tslil Clingman + * Walt Nagel + * Yutaka Saiko + + +WEBSITE, DOCS AND ARTWORK + + * Nitin Reddy Katkam -- logo and site design + * Paul Sommers -- Handbook API reference + * Helen Ewart -- MikeOS cat mascot + + +================================================================== + diff --git a/doc/LICENSE.TXT b/doc/LICENSE.TXT new file mode 100755 index 0000000..6e786b1 --- /dev/null +++ b/doc/LICENSE.TXT @@ -0,0 +1,37 @@ +================================================================== +MikeOS -- License +================================================================== + + +Copyright (C) 2006 - 2022 MikeOS Developers -- http://mikeos.sourceforge.net + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name MikeOS nor the names of any MikeOS contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY MIKEOS DEVELOPERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL MIKEOS DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +================================================================== + diff --git a/doc/handbook-appdev-asm.html b/doc/handbook-appdev-asm.html new file mode 100755 index 0000000..3b05f39 --- /dev/null +++ b/doc/handbook-appdev-asm.html @@ -0,0 +1,1210 @@ + + + + + The MikeOS Assembly App Developer Handbook + + + + + + + + + + +
    +

    Navigate

    +

    Overview

    + +

    Example

    + +

    System calls

    + +

    Extra

    + +
    +

    The MikeOS Assembly App Developer Handbook

    +

    For version 4.7, 9 April 2022 - (C) MikeOS Developers

    +

    This documentation file explains how write software for + MikeOS in assembly language. It shows you the tools you + need, how MikeOS programs work, and how to use the system + calls included in the kernel. If you have any questions, + see the MikeOS + website for contact details and mailing list + information.

    +

    Click the links on the left to navigate around this + guide.

    +
    +
    +

    Overview

    + +

    Introduction

    +

    Many MikeOS programs are written in 16-bit, real mode + assembly language. (The OS also includes a BASIC + interpreter.) Because MikeOS and its programs live in a + single 64KiB memory segment, you do not need to concern + yourself with segment registers.

    +

    MikeOS programs are loaded at the 32K point + (32768) in the segment, and have a maximum size of 32KiB. + Consequently, your programs will need to begin with these + directives:

    +
    BITS 16
    +ORG 32768
    +
    +

    There are many system calls available in MikeOS for + controlling the screen, getting input, manipulating + strings, loading/saving files, and more. All parameters to + MikeOS system calls are passed in registers, and not on + the stack. To use them in your programs, you need this + line:

    +
    %INCLUDE "mikedev.inc"
    +
    +

    This doesn't include any code, but a list of equ + directives that point to system call vectors in the + kernel. So, by including this file you can call, for + instance, the MikeOS os_print_string + routine without having to know exactly where it is in the + kernel. mikedev.inc is included in the programs/ + directory of the MikeOS download -- it also provides a + quick reference to the system calls.

    +

    If a MikeOS program is run from the command line, and one + or more parameters was provided with the command, they are + passed to the program via the SI register as a + zero-terminated string.

    +
    + +

    Tools needed

    +

    To write MikeOS programs you need:

    +
      +
    • NASM -- A powerful, free and open + source assembler
    • +
    • mikedev.inc -- The system call + vectors described above
    • +
    • A way to add programs to the floppy disk
    • +
    +

    Let's clarify this: MikeOS uses NASM for its programs and + kernel source code, hence why we recommend it here. You + can, of course, use any other assembler that can output + plain binary files (i.e. with no header) and accept 16-bit + code. NASM is available in most Linux distro repositories, + or you can download the Windows version from + here (get the 'win32' file).

    +

    For the second point, copy programs/mikedev.inc + so that it's alongside your program's source code for + inclusion.

    +

    For the third point, if you've written MikeOS to a real + floppy disk, you can just copy your .BIN + programs onto that disk (root directory only!), boot + MikeOS and test them out. If you're working with the + virtual mikeos.flp disk image, see the Copying + + files section of the User Handbook.

    +
    +
    +

    Example

    + +

    Source code

    +

    Here is an example MikeOS program, in NASM format, which + prints a string to the screen and waits for the user to + press a key before finishing:

    +
    	BITS 16
    +	ORG 32768
    +	%INCLUDE 'mikedev.inc'
    +
    +start:
    +	mov si, mystring
    +	call os_print_string
    +
    +	call os_wait_for_key
    +
    +	ret
    +
    +	mystring db 'My first MikeOS program!', 0
    +
    +
    + +

    Building

    +

    Save the above code as testapp.asm, and + enter this command to assemble it (works on both Linux and + Windows):

    +
    nasm -f bin -o testapp.bin testapp.asm
    +
    +

    Using the '-f bin' option we tell NASM that we just want + a plain binary file: no header or sections. The resulting + executable file is testapp.bin that we + can copy to our floppy disk or add to the virtual disk + image as described in Copying files in the User + Handbook. Then we can boot MikeOS and run the program.

    +
    + +

    Explanation

    +

    This is a very short program, but we'll explain exactly + how it works for complete clarity. The first three lines + will not be assembled to machine code instructions, but + are just directives to tell NASM that we want to operate + in 16 bit mode, our code is written to be executed from + the 32KiB mark, and we want to use system calls from the + MikeOS API.

    +

    Next we have the 'start:' label, which is not essential + but good practice to make things clear. We put the + location of a zero-terminated string into the SI + register, then call the MikeOS os_print_string + routine which we can access via the vectors listed in mikedev.inc. + After that we pause program until a the user presses a + key.

    +

    All MikeOS programs must end with a ret + instruction, which passes control back to the OS. After + that instruction we have the data for our string. And + that's it!

    +
    +
    +

    System calls

    + +

    Introduction

    +

    The MikeOS kernel includes system calls for outputting to + the screen, taking keyboard input, manipulating strings, + producing PC speaker sounds, math operations and disk I/O. + You can get a quick reference to the registers that these + calls take and pass back by looking at mikedev.inc, + and see practical use of the calls in the programs/ + directory.

    +

    Here we have a detailed API explanation with examples. + You can see the full source code behind these system calls + in the source/features/ directory in + MikeOS. Each aspect of the API below is contained within + an assembly source file, so you can enhance the system + calls as per the MikeOS System Developer Handbook.

    +
    +
    +

    Disk

    +

    os_get_file_list

    +

    Generate comma-separated string of files on + floppy

    +
      +
    • IN/OUT: AX = location to store zero-terminated + filename string (the programmer must ensure the buffer + is large enough to hold the entire root directory)
      +
    • +
    +

    Example:

    +
    	mov ax, .filestring
    +	call os_get_file_list
    +
    +	; Now .filestring will contain something like
    +	; 'HELLO.BIN,FOO.BAR,THREE.TXT', 0
    +
    +	.filestring	times 256 db 0
    +
    +
    +

    os_load_file

    +

    Load file into RAM

    +
      +
    • IN: AX = location of zero-terminated filename string, + CX = location in RAM to load file
    • +
    • OUT: EBX = file size (in bytes: if < 64 KiB testing + BX is sufficient), carry set if file not found
    • +
    +

    Example:

    +
    	mov ax, filename
    +	mov cx, 36960		; 4KiB after where external program loads
    +	call os_load_file
    +
    +	...
    +
    +	filename db 'README.TXT', 0
    +
    +
    +

    os_write_file

    +

    Save (max 64KiB) file to disk

    +
      +
    • IN: AX = filename, BX = data location, CX = bytes to + write
    • +
    • OUT: Carry clear if OK, set if failure (if OK the last + write date and time, archive attribute and file size are + updated in the disk directory)
      +
    • +
    +

    Example:

    +
    	; For this example, there's some text stored in .data
    +
    +	mov ax, .filename
    +	mov bx, .data
    +	mov cx, 4192
    +	call os_write_file
    +
    +	.filename	db 'HELLO.TXT', 0
    +	.data		times 4192 db 0
    +
    +
    +

    os_file_exists

    +

    Check for presence of file on the floppy

    +
      +
    • IN: AX = filename location
    • +
    • OUT: carry clear if found, set if not
    • +
    +

    Example:

    +
    	mov ax, .filename
    +	call os_file_exists
    +	jc .not_found
    +
    +	...
    +
    +.not_found:
    +	; Print error message here
    +
    +	.filename	db 'HELLO.TXT', 0
    +
    +
    +

    os_create_file

    +

    Creates a new 0-byte file on the floppy disk

    +
      +
    • IN: AX = location of filename
    • +
    • OUT: Nothing (if the function is successful, a disk + directory entry is created with the current system date + and time, the archive attribute set and a file size of + 0)
      +
    • +
    +

    Example:

    +
    	mov ax, .filename
    +	call os_create_file
    +
    +	...
    +
    +	.filename	db 'HELLO.TXT', 0
    +
    +
    +

    os_remove_file

    +

    Deletes the specified file from the filesystem

    +
      +
    • IN: AX = location of filename to remove
    • +
    • OUT: Nothing
    • +
    +
    +

    os_rename_file

    +

    Change the name of a file on the disk

    +
      +
    • IN: AX = filename to change, BX = new filename + (zero-terminated strings)
    • +
    • OUT: carry set on error
    • +
    +

    Example:

    +
    	mov ax, .filename1
    +	mov bx, .filename2
    +	call os_rename_file
    +
    +	jc .error
    +
    +	...
    +
    +.error:
    +	; File couldn't be renamed (may already exist)
    +
    +	.filename1	db 'ORIG.TXT', 0
    +	.filename2	db 'NEW.TXT', 0
    +
    +
    +

    os_get_file_size

    +

    Get file size information for specified file

    +
      +
    • IN: AX = filename
    • +
    • OUT: EBX = file size in bytes (theoretically, up to 4 + GB) or carry set if file not found
    • +
    +
    +
    +

    Keyboard

    +

    os_wait_for_key

    +

    Waits for key press and returns key

    +
      +
    • IN: Nothing
    • +
    • OUT: AX = key pressed, other regs preserved
    • +
    +

    Example:

    +
    .loop:
    +	call os_wait_for_key
    +	cmp al, 'y'
    +	je .yes
    +	cmp al, 'n'
    +	je .no
    +	jmp .loop
    +
    +
    +

    os_check_for_key

    +

    Scans keyboard for input, but doesn't wait

    +
      +
    • IN: Nothing
    • +
    • OUT: AX = 0 if no key pressed, otherwise scan code
    • +
    +

    Example: see code above

    +
    +
    +

    Math

    +

    os_bcd_to_int

    +

    Converts binary coded decimal number to an + integer

    +
      +
    • IN: AL = BCD number
    • +
    • OUT: AX = integer value
    • +
    +

    Example:

    +
    	mov al, 00010110b	; 0001 0110 = 16 (decimal) or 10h in BCD
    +	call os_bcd_to_int 
    +     
    +	; AX now contains the 16 bit-integer 00000000 00010000b
    +
    +
    +

    os_long_int_negate

    +

    Multiply value in DX:AX by -1

    +
      +
    • IN: DX:AX = long integer
    • +
    • OUT: DX:AX = -(initial DX:AX)
    • +
    +

    Example:

    +
    	mov dx, 01h
    +	mov ax, 45h
    +	call os_long_int_negate
    +
    +	; DX now contains 0xFFFF
    +	; and AX 0xFEBB
    +
    +
    +

    os_get_random

    +

    Get a random integer between high and low values + (inclusive)

    +
      +
    • IN: AX = low integer, BX = high
    • +
    • OUT: CX = random number between AX and BX
    • +
    +
    +
    +

    Misc

    +

    os_get_api_version

    +

    Return current version of MikeOS API

    +
      +
    • IN: Nothing
    • +
    • OUT: AL = API version number
    • +
    +

    Example:

    +
    	call os_get_api_version
    +	; AL now contains version number (eg 8)
    +
    +
    +

    os_pause

    +

    Delay execution for specified 10ths of second

    +
      +
    • IN: AX = number of 10ths of second to wait
    • +
    • OUT: nothing
    • +
    +

    Example:

    +
    	; Halt execution for 3 secs
    +
    +	mov ax, 30
    +	call os_pause
    +
    +
    +

    os_fatal_error

    +

    Display error message and halt execution

    +
      +
    • IN: AX = error message string location
    • +
    • OUT: nothing
    • +
    +

    Example:

    +
    	mov ax, .error_msg
    +	call os_fatal_error
    +
    +	.error_msg	db 'Massive error!', 0
    +
    +
    +
    +

    Ports

    +

    os_port_byte_out

    +

    Sends a byte to the specified port

    +
      +
    • IN: DX = port address, AL = byte
    • +
    • OUT: Nothing
    • +
    +
    +

    os_port_byte_in

    +

    Retrieves a byte from the specified port

    +
      +
    • IN: DX = port address
    • +
    • OUT: AL = byte
    • +
    +
    +

    os_serial_port_enable

    +

    Turn on the first serial port

    +
      +
    • IN: AX = 0 for normal mode (9600 baud), or 1 for slow + mode (1200 baud)
    • +
    • OUT: AH = bit 7 clear on success (AH is line status + and AL is modem status)
      +
    • +
    +
    +

    os_send_via_serial

    +

    Send a byte via the serial port

    +
      +
    • IN: AL = byte to send via serial
    • +
    • OUT: AH = bit 7 clear on success
    • +
    +

    Example:

    +
    	mov al, 'a'			; Place char to transmit in AL
    +	call os_send_via_serial
    +	cmp ah, 128			; If bit 7 is set, there's an error
    +	jnz all_ok			; Otherwise it's all OK
    +	jmp oops_error			; Deal with the error
    +
    +
    +

    os_get_via_serial

    +

    Get a byte from the serial port

    +
      +
    • IN: nothing
    • +
    • OUT: AL = byte that was received; OUT: AH = bit 7 + clear on success
    • +
    +

    Example:

    +
    	call os_get_via_serial
    +	cmp ah, 128		; If bit 7 is set, there's an error.
    +	jnz all_ok		; Otherwise it's all OK
    +	jmp oops_error		; Deal with the error
    +
    +all_ok:           
    +	mov [rx_byte], al	; Store byte we retrieved
    +
    +
    +
    +

    Screen

    +

    os_print_string

    +

    Displays text

    +
      +
    • IN: SI = message location (zero-terminated string)
    • +
    • OUT: Nothing (registers preserved)
    • +
    +

    Example:

    +
    	mov si, .message
    +	call os_print_string
    +
    +	...
    +
    +	.message	db 'Hello, world', 0
    +
    +
    +

    os_clear_screen

    +

    Clears the screen to background

    +
      +
    • IN/OUT: Nothing (registers preserved)
    • +
    +
    +

    os_move_cursor

    +

    Moves cursor in text mode

    +
      +
    • IN: DH, DL = row, column
    • +
    • OUT: Nothing (registers preserved)
    • +
    +

    Example:

    +
    	; Move to middle of screen
    +
    +	mov dh, 12
    +	mov dl, 40
    +	call os_move_cursor
    +
    +
    +

    os_get_cursor_pos

    +

    Return position of text cursor

    +
      +
    • OUT: DH, DL = row, column
    • +
    +
    +

    os_print_horiz_line

    +

    Draw a horizontal line on the screen

    +
      +
    • IN: AX = line type (1 for double, otherwise single)
    • +
    • OUT: Nothing (registers preserved)
    • +
    +
    +

    os_show_cursor

    +

    Turns on cursor in text mode

    +
      +
    • IN/OUT: Nothing
    • +
    +
    +

    os_hide_cursor

    +

    Turns off cursor in text mode

    +
      +
    • IN/OUT: Nothing
    • +
    +
    +

    os_draw_block

    +

    Render block of specified colour

    +
      +
    • IN: BL/DL/DH/SI/DI = colour/start X pos/start Y + pos/width/finish Y pos
    • +
    • OUT: Nothing
    • +
    +

    Example:

    +
    	mov bl, 0100111b	; White on red
    +	mov dl, 20		; Start X position
    +	mov dh, 2		; Start Y position
    +	mov si, 40		; Width
    +	mov di, 23		; Finish Y position
    +	call os_draw_block
    +
    +
    +

    os_file_selector

    +

    Show a file selection dialog

    +
      +
    • IN: Nothing
    • +
    • OUT: AX = location of filename string (or carry set if + Esc pressed)
    • +
    +

    Example:

    +
    	call os_file_selector
    +	jc .esc_pressed
    +
    +	; Now AX points to the chosen filename
    +	...
    +
    +.esc_pressed:
    +	...
    +
    +
    +

    os_list_dialog

    +

    Show a dialog with a list of options

    +
      +
    • IN: AX = comma-separated list of strings to show + (zero-terminated),
    • +
    •  BX = first help string, CX = second help string
    • +
    • OUT: AX = number (starts from 1) of entry selected + carry set if Esc pressed
    • +
    +

    Example:

    +
    	mov ax, .list
    +	mov bx, .msg1
    +	mov cx, .msg2
    +	call os_list_dialog
    +	jc .esc_pressed
    +
    +	; Now AX = number (from 1) of option chosen
    +	...
    +
    +.esc_pressed:
    +	...
    +
    +	.list	db 'Open,Close,Reboot', 0
    +	.msg1	db 'Choose an option', 0
    +	.msg2	db 'Or press Esc to quit', 0
    +
    +
    +

    os_draw_background

    +

    Clear screen with white top and bottom bars, + containing text, and a coloured middle section

    +
      +
    • IN: AX/BX = top/bottom string locations, CX = colour
    • +
    • OUT: Nothing
    • +
    +

    Example:

    +
    	mov ax, .title_msg
    +	mov bx, .footer_msg
    +	mov cx, 00100000b	; Colour
    +	call os_draw_background
    +
    +	...
    +
    +	.title_msg	db 'File manager', 0
    +	.footer_msg	db 'Choose an option...', 0
    +
    +
    +

    os_print_newline

    +

    Reset cursor to start of next line

    +
      +
    • IN/OUT: Nothing (registers preserved)
    • +
    +
    +

    os_dump_registers

    +

    Displays register contents in hex on the screen

    +
      +
    • IN/OUT: AX/BX/CX/DX/SI/DI/BP = registers to show
    • +
    +
    +

    os_input_dialog

    +

    Get text string from user via a dialog box

    +
      +
    • IN: AX = string location, BX = message to show
    • +
    • OUT: AX = string location
    • +
    +

    Example:

    +
    	mov bx, .filename_msg
    +	mov ax, .filename_input
    +	call os_input_dialog
    +
    +	...
    +
    +	.filename_msg	'Please enter a filename:', 0
    +	.filename_input	times 12 db 0
    +
    +
    +

    os_dialog_box

    +

    Print dialog box in middle of screen, with + button(s)

    +
      +
    • IN: AX, BX, CX = string locations (set registers to 0 + for no display),
    • +
    •  DX = 0 for single 'OK' dialog, 1 for two-button + 'OK' and 'Cancel'
    • +
    • OUT: If two-button mode, AX = 0 for OK and 1 for + cancel
    • +
    • NOTE: Each string is limited to 40 characters
    • +
    +

    Example:

    +
    	mov ax, .string1
    +	mov bx, .string2
    +	mov cx, .string3
    +	mov dx, 1
    +	call os_dialog_box
    +
    +	cmp ax, 1
    +	je .first_option_chosen
    +
    +	; Otherwise second was chosen
    +	...
    +
    +.first_option_chosen:
    +	...
    +
    +	.string1	db 'Welcome to my program!', 0
    +	.string2	db 'Please choose to destroy the world,', 0
    +	.string3	db 'or play with fluffy kittens.', 0
    +
    +
    +

    os_print_space

    +

    Print a space to the screen

    +
      +
    • IN/OUT: nothing
    • +
    +
    +

    os_dump_string

    +

    Dump string as hex bytes and printable characters

    +
      +
    • IN: SI = points to string to dump
    • +
    • OUT: Nothing
    • +
    +
    +

    os_print_digit

    +

    Displays contents of AX as a single digit (works + up to base 37, ie digits 0-Z)

    +
      +
    • IN: AX = "digit" to format and print
    • +
    • OUT: Nothing
    • +
    +
    +

    os_print_1hex

    +

    Displays low nibble of AL in hex format

    +
      +
    • IN: AL = number to format and print
    • +
    • OUT: Nothing
    • +
    +
    +

    os_print_2hex

    +

    Displays AL in hex format

    +
      +
    • IN: AL = number to format and print
    • +
    • OUT: Nothing
    • +
    +
    +

    os_print_4hex

    +

    Displays AX in hex format

    +
      +
    • IN: AX = number to format and print
    • +
    • OUT: Nothing
    • +
    +
    +

    os_input_string

    +

    Take string from keyboard entry

    +
      +
    • IN/OUT: AX = location of string, BX = maximum number + of characters
    • +
    • (Location will contain up to 255 characters, + zero-terminated)
    • +
    +

    Example:

    +
    	mov ax, .string
    +	call os_input_string
    +
    +	...
    +
    +	.string		times 256 db 0
    +
    +
    +
    +

    String

    +

    os_string_length

    +

    Return length of a string

    +
      +
    • IN: AX = string location
    • +
    • OUT AX = length (other regs preserved)
    • +
    +

    Example:

    +
    	jmp Get_Len
    +
    +	Test_String db 'This string has 46 characters including spaces', 0
    +
    +Get_Len:
    +	mov ax, Test_String
    +	call os_string_length
    +	; AX now contains the number 46
    +
    +
    +

    os_find_char_in_string

    +

    Get the position of a character in a string

    +
      +
    • IN: SI = string location, AL = character to find
    • +
    • OUT: AX = location in string, or 0 if char not present
    • +
    +

    Example:

    +
    jmp Search_Str
    +
    +     Test_String db 'This is the test string', 0
    +     message_1   db 'Character not found', 0
    +     message_2   db 'Character found at position', 0
    +     message_3   db '  ', 0
    +     str_len     dw  0
    +
    +Search_Str:
    +
    +     mov ax, Test_String           ; string to search
    +     mov si, ax
    +     xor ax, ax                    ; clear ax
    +
    +     mov al, 'x'                   ; x is the character to find
    +     call os_find_char_in_string
    +
    +     mov [str_len], ax             ; store result
    +     cmp ax, 0                  
    +     jz Char_Not_Found 
    +     jmp Char_Found
    +
    +Char_Not_Found:
    +
    +     mov si, message_1
    +     call os_print_string     
    +     jmp Main_Pgm
    +
    +Char_Found:
    +
    +     mov ax, [str_len]             ; convert result into string first
    +     mov bx, message_3
    +     call os_int_to_string
    +
    +     mov si, message_2
    +     call os_print_string          ; print message_2
    +     call os_print_space           ; print a space
    +
    +     mov si, message_3
    +     call os_print_string          ; print the position at which x was found     
    +
    +
    +

    os_string_reverse

    +

    Swar order of characters in a string

    +
      +
    • IN: SI = location of zero-terminated string
    • +
    +

    Example:

    +
    	mov si, mystring
    +	call os_string_reverse
    +
    +	; Now mystring contains 'olleH'
    +
    +	mystring db 'Hello', 0
    +
    +
    +

    os_string_charchange

    +

    Change instances of character in a string

    +
      +
    • IN: SI = string location, AL = char to find, BL = char + to replace with
    • +
    +
    +

    os_string_uppercase

    +

    Convert zero-terminated string to upper case

    +
      +
    • IN/OUT: AX = string location
    • +
    +
    +

    os_string_lowercase

    +

    Convert zero-terminated string to lower case

    +
      +
    • IN/OUT: AX = string location
    • +
    +
    +

    os_string_copy

    +

    Copy one string into another

    +
      +
    • IN/OUT: SI = source, DI = destination (programmer + ensure sufficient room)
    • +
    +

    Example:

    +
    	mov si, .old_string
    +	mov di, .new_string
    +	call os_string_copy
    +
    +	...
    +
    +	.old_string	db 'Hello', 0
    +	.new_string	times 16 db 0
    +
    +
    +

    os_string_truncate

    +

    Chop string down to specified number of + characters

    +
      +
    • IN: SI = string location, AX = number of characters
    • +
    • OUT: string modified, registers preserved
    • +
    +

    Example:

    +
    	mov si, .string
    +	mov ax, 3
    +	call os_string_truncate
    +
    +	; .string now contains 'HEL', 0
    +
    +	.string		db 'HELLO', 0
    +
    +
    +

    os_string_join

    +

    Join two strings into a third string

    +
      +
    • IN/OUT: AX = string one, BX = string two, CX = + destination string
    • +
    +

    Example:

    +
    	mov ax, .string1
    +	mov bx, .string2
    +	mov cx, .string3
    +	call os_string_join
    +
    +	; CX now points to 'HELLOYOU', 0
    +
    +	.string1	db 'HELLO', 0
    +	.string2	db 'YOU', 0
    +	.string3	times 50 db 0
    +
    +
    +

    os_string_chomp

    +

    Strip leading and trailing spaces from a string

    +
      +
    • IN: AX = string location
    • +
    • OUT: nothing
    • +
    +

    Example:

    +
    	mov ax, .string
    +	call os_string_chomp
    +
    +	; AX now points to 'KITTEN', 0
    +
    +	.string		db '  KITTEN  ', 0
    +
    +
    +

    os_string_strip

    +

    Removes specified character from a string

    +
      +
    • IN: SI = string location, AL = character to remove
    • +
    • OUT: nothing
    • +
    +

    Example:

    +
    	mov si, .string
    +	mov al, 'U'
    +	call os_string_strip
    +
    +	; .string now contains 'MOSE', 0
    +
    +	.string		db 'MOUSE', 0
    +
    +
    +

    os_string_compare

    +

    See if two strings match

    +
      +
    • IN: SI = string one, DI = string two
    • +
    • OUT: carry set if same, clear if different
    • +
    +

    Example:

    +
    	mov si, .string1
    +	mov di, .string2
    +	call os_string_compare
    +	jc .same
    +
    +	; Strings are different
    +
    +	...
    +
    +.same:
    +	; Strings are the same
    +
    +	.string1	db 'ONE', 0
    +	.string2	db 'TWO', 0
    +
    +
    +

    os_string_strincmp

    +

    See if two strings match up to set number of + chars

    +
      +
    • IN: SI = string one, DI = string two, CL = chars to + check
    • +
    • OUT: carry set if same, clear if different
    • +
    +

    Example: like above, but with CL = number of characters + to check

    +
    +

    os_string_parse

    +

    Take string (eg "run foo bar baz") and return + pointers to zero-terminated strings (eg AX = "run", BX = + "foo" etc.)

    +
      +
    • IN: SI = string
    • +
    • OUT: AX, BX, CX, DX = individual strings
    • +
    +

    Example:

    +
    	mov si, .string
    +	call os_string_parse
    +
    +	; Now AX points to 'This',
    +	; BX to 'is',
    +	; CX to 'a',
    +	; and DX to 'test'
    +
    +	.string		db 'This is a test', 0
    +
    +
    +

    os_string_to_int

    +

    Convert decimal string to integer value

    +
      +
    • IN: SI = string location (max 5 chars, up to '65536')
    • +
    • OUT: AX = number
    • +
    +

    Example:

    +
    	mov si, .string
    +	call os_string_to_int
    +
    +	; Now AX contains the number 1234
    +
    +	.string		db '1234', 0
    +
    +
    +

    os_int_to_string

    +

    Convert unsigned value in AX to string

    +
      +
    • IN: AX = unsigned integer
    • +
    • OUT: AX = location of internal string buffer with + result
    • +
    +

    Example:

    +
    	mov ax, 1234
    +	call os_int_to_string
    +
    +	; Now AX points to '1234', 0
    +
    +
    +

    os_sint_to_string

    +

    Convert signed value in AX to string

    +
      +
    • IN: AX = signed integer
    • +
    • OUT: AX = location of internal string buffer with + result
    • +
    +

    Example:

    +
    	mov ax, -1234
    +	call os_int_to_string
    +
    +	; Now AX points to '-1234', 0
    +
    +
    +

    os_long_int_to_string

    +

    Convert value in DX:AX to string

    +
      +
    • IN: DX:AX = long unsigned integer, BX = number base, + DI = string location
    • +
    • OUT: DI = location of converted string
    • +
    +
    +

    os_string_to_long_int

    +

    Convert a decimal string to a long integer value
    +

    +
      +
    • IN: SI = string location (up to 10 digits, value of + '4294967295')
      +
    • +
    • OUT: EAX = long unsigned integer
      +
    • +
    +
    +

    os_set_time_fmt

    +

    Set time reporting format (eg '10:25 AM' or '2300 + hours')

    +
      +
    • IN: AL = format flag, 0 = 12-hr format
    • +
    • OUT: nothing
    • +
    +
    +

    os_get_time_string

    +

    Get current time in a string (eg '10:25')

    +
      +
    • IN/OUT: BX = string location
    • +
    +
    +

    os_set_date_fmt

    +

    Set date reporting format (M/D/Y, D/M/Y or Y/M/D + - 0, 1, 2)

    +
      +
    • IN: AX = format flag, 0-2
    • +
    •  If AX bit 7 = 1 = use name for months
    • +
    •  If AX bit 7 = 0, high byte = separator character
    • +
    • OUT: nothing
    • +
    +
    +

    os_get_date_string

    +

    Get current date in a string (eg '12/31/2007')

    +
      +
    • IN/OUT: BX = string location
    • +
    +
    +
    +

    Sound

    +

    os_speaker_tone

    +

    Generate PC speaker tone (call os_speaker_off to + turn off)

    +
      +
    • IN: AX = note frequency
    • +
    • OUT: Nothing (registers preserved)
    • +
    +

    Example: see code below

    +
    +

    os_speaker_off

    +

    Turn off PC speaker

    +
      +
    • IN/OUT: Nothing (registers preserved)
    • +
    +

    Example:

    +
    ; Generate "middle C" 261.626 Hz (263 Hz close enough) for 2 secs
    +; 2 secs = 2,000,000 uS which is 1E8480h
    +
    +	jmp Play_It
    +
    +	music_note  dw  263
    +
    +Play_It:
    +	mov ax, [music_note]
    +	call os_speaker_tone
    +
    +	mov cx, 1Eh
    +	mov dx, 8480h
    +	call os_pause
    +
    +	call os_speaker_off         
    +
    +
    +
    +

    BASIC

    +

    os_run_basic

    +

    Runs kernel BASIC interpreter at the specified + point

    +
      +
    • IN: AX = location of BASIC code, BX = size of code (in + bytes)
    • +
    +
    +
    +

    Extra

    + +

    Help

    +

    If you have any questions about MikeOS, or you're + developing a similar OS and want to share code and ideas, + go to the MikeOS + website and join the mailing list as described.

    +
    + +

    License

    +

    MikeOS is open source and released under a BSD-like + license (see doc/LICENSE.TXT in the + MikeOS .zip file). Essentially, it means + you can do anything you like with the code, including + basing your own project on it, providing you retain the + license file and give credit to the MikeOS developers for + their work.

    +
    +
    + + diff --git a/doc/handbook-appdev-basic.html b/doc/handbook-appdev-basic.html new file mode 100755 index 0000000..96f2eb8 --- /dev/null +++ b/doc/handbook-appdev-basic.html @@ -0,0 +1,1537 @@ + + + + + + +The MikeOS BASIC App Developer Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    Navigate

    + +

    Overview

    + + +

    Instructions

    + + +

    Samples

    + + +

    Extra

    + + +
    + +

    The MikeOS BASIC App Developer Handbook

    + +

    For version 4.7, 9 April 2022 - (C) MikeOS Developers

    + +

    This documentation file explains how to write software for MikeOS using the BASIC interpreter +built into the operating system. If you have any questions, see the MikeOS website +for contact details and mailing list information.

    + +

    Click the links on the left to navigate around this guide.

    + +
    + + +
    + + +

    Overview

    + + +

    Features

    + +

    The MikeOS BASIC interpreter runs a simple dialect of the BASIC programming language. There +are commands for taking input, handling the screen, performing nested loops, loading/saving files, +and so forth. You will find a full list of the included instructions later in this document. Here +are the essentials you need to know.

    + +
      +
    • Numeric variables -- These are A to Z, each storing +one positive integer word (ie 0 to 65535). The R and S variables have +special roles with LOAD and SAVE commands, as explained in the instruction +list below.
    • +
    • String variables -- These are $1 to $8, each 128 bytes +long.
    • +
    • Arrays -- You can use string variables as arrays via the PEEK and POKE commands. +For instance, X = & $1 places the memory location of the $1 string variable into X. You can then put data into it with eg POKE 77 X (put 77 into the memory location pointed to by X).
    • +
    • Labels -- Such as box_loop: etc. Used by GOTO and GOSUB, they must have a trailing colon and be at the start of a line.
    • +
    • Ending -- Programs must finish with an END statement.
    • +
    + +

    GOSUB calls can be nested up to ten times. FOR loops can be nested using different variables (eg you +can have a FOR X = 1 TO 10 ... NEXT X loop surrounding a FOR Y = 30 TO 50 loop). You can enter code in uppercase or lowercase -- the interpreter doesn't mind either way. However, labels are case-sensitive.

    + +

    If a MikeOS BASIC program is run from the command line, and one or more parameters was provided with the command, +they are copied into the $1 string when the program starts.

    + + +
    + + + +

    Example

    + +

    Here's a small example program demonstrating various common features:

    + +
    rem *** MikeOS BASIC example program ***
    +
    +alert "Welcome to the example!"
    +cls
    +
    +print "Let's skip the next 'print' line..."
    +goto jump
    +
    +print "This line will never be printed :-("
    +
    +jump:
    +print "Righto, now enter a number:"
    +input x
    +
    +if x > 10 then print "X is bigger than 10! Wow!"
    +if x < 10 then print "X is quite small actually."
    +if x = 10 then gosub equalsroutine
    +
    +a = 7
    +b = a / 2
    +print "Variable A is seven here. Divided by two you get:"
    +print b
    +print "And the remainder of that is:"
    +b = a % 2
    +print b
    +
    +print "A quick loop here..."
    +for c = 1 to 10
    +  print c
    +next c
    +
    +print "Righto, that's the end! Bye!"
    +end
    +
    +equalsroutine:
    +  print "Awesome, a perfect 10! Give me your name so I can high-five you!"
    +  input $1
    +  print "Top work, " ;
    +  print $1
    +return
    +
    + + +

    This example should be mostly self-explanatory. You can see that the subroutine is indented with spaces, +but that's not necessary if you don't want it. You can follow IF ... THEN with any other +instruction. Regarding this part:

    + +
    +  print "Top work, " ;
    +  print $1
    +
    + +

    The space and semi-colon character (;) after the quoted string tells the interpreter not to print a newline +after the string. So here, we print the user's name on the same line. You can do this with numerical variables +as well, eg PRINT X ; etc.

    + +

    See the Samples section at the end for more demonstration programs.

    + + + +
    + + + +

    Assignment

    + + +

    The following are valid ways to assign numeric variables in MikeOS BASIC:

    + +
    +a = 10
    +a = b
    +a = b + 10
    +a = b + c
    +a = b - 10
    +a = b - c
    +a = b * 10
    +a = b * c
    +a = b / 10
    +a = b / c
    +a = b % 10
    +a = b % c
    +
    + +

    So you can use combinations of numbers and variables. Note that you can perform multiple +operations in the same line:

    + +
    a = b + c * 2 / 3
    + +

    But note that there is no operator precedence; the calculation is simply worked out one step +at a time from left to right. For string variables:

    + +
    +$1 = "Hello"
    +$2 = $1
    +
    + +

    You can get the location of a string variable to use as an array:

    + +
    +x = & $3
    +
    + +

    You can get variables from the user with INPUT like this:

    + +
    +input x
    +input $1
    +
    + + + +
    + + + +

    Memory

    + +

    MikeOS and its programs exist in a single 64KiB memory segment. The first +32KiB is occupied by the kernel and disk cache. Your BASIC program may be loaded at the start of the second 32KiB, +ie 32768, if it is run directly from the program menu or CLI. However, if it is run from a standalone program +such as the EDIT.BIN editor, its starting point will be elsewhere. Use PROGSTART and +RAMSTART to find out what memory you can use:

    + +
    +x = PROGSTART
    +
    + +

    This assigns to the X variable the location at which the BASIC program was loaded. In other words, this is where +the execution of the BASIC program by the interpreter starts. We also have:

    + +
    +x = RAMSTART
    +
    + +

    This is one byte on from the end of the BASIC code. Therefore this is empty memory which you can use, up until the 65536 mark. +You can LOAD and SAVE files in here, PEEK and POKE around, and do what you want without it impacting the operating system or BASIC program.

    + +

    To retrieve the location in RAM where the MikeOS BASIC variables are stored, use this:

    + +
    +x = VARIABLES
    +
    + + +
    + + + +

    Keywords

    + + +

    You can do this to get the MikeOS API version number:

    + +
    +x = VERSION
    +
    + +

    Or you can retrieve the lower word of the system clock like this:

    + +
    +x = TIMER
    +
    + +

    To get the current ink colour, use:

    + +
    +x = INK
    +
    + + + + +
    + + + +

    The editor

    + +

    You can run your .BAS programs by selecting them from the program menu or typing them into the +command line interface -- eg entering example will run EXAMPLE.BAS. +Use the MikeOS file manager, FILEMAN.BIN, to make backup copies of your work and +delete old files.

    + +

    MikeOS includes a text editor, EDIT.BIN Which you can use to edit your BASIC programs. +It lets you run your code straight from inside the editor by pressing the F8 key. Note +that if your program has an infinite loop or major bug, it may hang execution -- so it's worth hitting +F2 before running your code to save it to the disk. Hit F5 to delete whole +lines quickly, and Esc to exit (you'll see a reminder of these keybindings in the bottom +bar of the editor).

    + +

    The MikeOS text editor only handles Unix-style text files, and curently does not support horizontal scrolling +of lines, so keep them less than 80 characters! You can use the Delete and Backspace keys to erase characters, +but note that only Delete can be used to remove newlines.

    + + +
    + + +
    + + + +

    Instructions

    + + + + + +

    ALERT

    +

    Show a dialog box on the screen with a string, and an OK button triggered by the Enter key. Example:

    + +
    +alert "File saved correctly."
    +
    +$1 = "Welcome to my program"
    +alert $1
    +
    + + + +
    + + +

    ASKFILE

    +

    Show a dialog box on the screen with a string with a list of files on the disk, and store the selected file in the specified variable. Example:

    + +
    +askfile $1
    +
    + + + +
    + + +

    BREAK

    +

    Halts execution of the BASIC program and prints the line number in the BASIC file. Useful for debugging.

    + + + +
    + + +

    CALL

    +

    Moves machine code execution to the specified point in RAM (using the x86 call instruction). The code +must be terminated with a ret (C3 hex, 195 decimal) instruction. In this example, we simply +add a ret instruction into RAM location 40000 and call it, which returns control straight back to the BASIC +interpreter:

    + +
    +poke 195 40000
    +call 40000
    +
    + + + + +
    + + +

    CASE

    +

    Changes the contents of a string to all upper-case or lower-case.

    + +
    +case lower $1
    +case upper $2
    +
    + + + +
    + + +

    CLS

    +

    Clears the screen and returns the cursor to the top-left corner of the screen. Example:

    + +
    +cls
    +
    + + + + +
    + + +

    CURSOR

    +

    Determines whether to show the text cursor or not. Example:

    + +
    +cursor off
    +print "The cursor is off for five seconds!"
    +pause 50
    +cursor on
    +print "And now it's back on."
    +
    + + + + +
    + + +

    CURSCHAR

    +

    Stores the character underneath the cursor location into the specified variable. Example:

    + +
    +move 0 0
    +print "Hello world"
    +
    +move 0 0
    +curschar x
    +
    +rem *** The next command will print 'H' ***
    +print chr x
    +
    +move 1 0
    +curschar x
    +
    +rem *** The next command will print 'e' ***
    +print chr x
    +
    + + + + +
    + + +

    CURSCOL

    +

    Get the colour of the character under the cursor. Example:

    + +
    +move 20 15
    +curscol x
    +
    + + + + +
    + + +

    CURSPOS

    +

    Get the position of the cursor. Example:

    + +
    +rem *** First is column, then row ***
    +curspos a b
    +
    + + + + +
    + + +

    DELETE

    +

    Removes a file from the disk. Returns 0 in the R variable if the operation was a success, 1 if the delete +operation couldn't be completed, or 2 if the file doesn't exist. Example:

    + +
    +delete "myfile.txt"
    +
    + + + + +
    + + +

    DO

    +

    Perform a loop until a condition is met (UNTIL or WHILE). You can also set up an infinite loop with LOOP ENDLESS at the end. Example:

    + +
    +do
    +  rem *** Code goes here ***
    +loop until x = 10
    +
    + + + + +
    + + +

    ELSE

    +

    Executes code if the previous IF condition didn't match. Example:

    + +
    +x = 1
    +if x = 1 then print "Hello"
    +else print "Goodbye"
    +
    + + + + +
    + + +

    END

    +

    Terminates execution of the BASIC program and hands control back to the operating system.

    + + + + +
    + + +

    FILES

    +

    Prints a list of files that are on the disk on the screen.

    + + + + +
    + + +

    FOR

    +

    Begins a loop, counting upwards using a variable. The loop must be finished with a NEXT instruction +and the relevant variable. Example:

    + +
    +for x = 1 to 10
    +  print "In a loop! X is " ;
    +  print x
    +next x
    +
    + + + + +
    + + +

    GETKEY

    +

    Checks the keyboard buffer for a key, and if one has been pressed, places it into the +specified variable.

    + +
    +loop:
    +  print "Infinite loop until m or Esc is pressed..." ;
    +  getkey x
    +  if x = 'm' then goto done
    +  goto loop
    +
    +done:
    +  print "Finished loop!"
    +
    + + + + +
    + + +

    GOSUB

    +

    Takes a label. It executes a subroutine, which must be finished with a RETURN instruction. You can +nest GOSUB routines up to 10 times. Example:

    + +
    +print "About to go into a subroutine..."
    +gosub mylabel
    +print "Subroutine done!"
    +end
    +
    +mylabel:
    +  print "Inside a GOSUB here!"
    +return
    +
    + + + + +
    + + +

    GOTO

    +

    Takes a label, and jumps to that label in the code. Example:

    + +
    +print "Going to miss the next 'PRINT' line of code..."
    +goto skippy
    +
    +print "This'll never be printed."
    +
    +skippy:
    +print "And now we're back home"
    +
    + + + + +
    + + +

    IF

    +

    Executes a command depending on a condition (or multiple conditions with AND). After stating the condition (eg whether one number +is bigger than another, or whether two strings match) you must use THEN and follow with another +instruction. Examples:

    + +
    +if x = 10 then print "X is 10! Woohoo"
    +
    + +
    +if x = y then print "X is the same as Y"
    +
    + +
    +if x = 'm' then print "X contains the letter m"
    +
    + +
    +if x < y then print "Now X is less than Y"
    +
    + +
    +if x > y then goto xbiggerthany
    +
    + +
    +if $1 = "quit" then end
    +
    + +
    +if $1 = $2 then gosub stringsmatch
    +
    + + + + +
    + + +

    INCLUDE

    +

    Appends another BASIC file onto the end of the current one, so that you can call routines in it. RAMSTART +is updated accordingly. Example:

    + +
    +include "mbpp.bas"
    +
    + + + + + +
    + + +

    INK

    +

    Changes the colour of printed text, using a number or variable. Example:

    + +
    +ink 2
    +print "This text is green"
    +
    + + + + + +
    + + +

    INPUT

    +

    Gets input from the user and stores the result into a numeric or string variable. Examples:

    + +
    +input x
    +input $1
    +
    + + + + +
    + + +

    LEN

    +

    Stores the length of a string variable in a numeric variable. Example:

    + +
    +$1 = "Hello world"
    +len $1 x
    +
    + + + + +
    + + +

    LISTBOX

    +

    Displays an dialog box containing a list of options, specified by a comma-separated list in the first string. The second +and third strings provide help text, and the chosen option (from 1) is stored in the specified variable (or zero if the Esc +key is pressed). Example:

    + +
    +cls
    +
    +$1 = "Hex dumper,MikeTron"
    +$2 = "Choose a program to run,"
    +$3 = "Or press Esc to exit"
    +
    +listbox $1 $2 $3 a
    +
    +if a = 1 then goto runhex
    +if a = 2 then goto runmiketron
    +
    +rem *** The following will be executed if Esc was pressed ***
    +end
    +
    + + + + +
    + + +

    LOAD

    +

    Loads the specified file into RAM at the specified point. The first argument is the filename, +and the second the location into which it should be loaded. If the file cannot be found or loaded, +the R variable contains 1 after the instruction; otherwise it contains 0 and the S variable +contains the file size. Examples:

    + +
    +load "example.txt" 40000
    +if r = 1 then goto fail
    +print "File size is:"
    +print s
    +end
    +
    +fail:
    +print "File couldn't be loaded"
    +end
    +
    + +
    +$1 = "example.txt"
    +x = 40000
    +
    +load $1 x
    +if r = 1 then goto fail
    +print "File size is:"
    +print s
    +end
    +
    +fail:
    +print "File couldn't be loaded"
    +end
    +
    + + + + +
    + + +

    MOVE

    +

    Moves the cursor position on the screen. Examples:

    + +
    +move 20 15
    +
    + +
    +x = 20
    +y = 15
    +move x y
    +
    + + + + +
    + + +

    NEXT

    +

    Continues the FOR loop specified previously, and must be followed by a variable. See FOR above. Example:

    + +
    +next x
    +
    + + + + +
    + + +

    NUMBER

    +

    Converts strings to numbers and vice versa. Examples:

    + +
    +number $1 a
    +
    + +
    +number a $1
    +
    + + + + +
    + + +

    PAUSE

    +

    Delays execution of the program by the specified 10ths of a second. This ultimately results in a BIOS +call and may be slower or faster in some PC emulators. Try it on real hardware to be sure. Example:

    + +
    +print "Now let's wait for three seconds..."
    +pause 30
    +
    +print "Hey, and one more, this time with a variable..."
    +x = 10
    +pause x
    +
    + + + + +
    + + +

    PAGE

    +

    Switch between working and active (display) pages. Example:

    + +
    +page 1 0
    +
    + + + + +
    + + +

    PEEK

    +

    Retrieve the byte stored in the specifed location in RAM. Examples:

    + +
    +peek a 40000
    +print "The number stored in memory location 40000 is..."
    +print a
    +
    + +
    +x = 32768
    +peek a x
    +
    + +

    Note: you can use PEEKINT to work with words instead of bytes (up to 65536).

    + + + +
    + + +

    POKE

    +

    Insert the byte (0 to 255) value into the specified location in RAM. Example:

    + +
    +print "Putting the number 126 into location 40000 in memory..."
    +poke 126 40000
    +
    +print "Now doing the same, but using variables..."
    +x = 126
    +y = 40000
    +poke x y
    +
    + +

    Note: you can use POKEINT to work with words instead of bytes (up to 65536).

    + + + +
    + + +

    PORT

    +

    Sends and receives bytes from the specified port. Examples:

    + +
    +x = 1
    +port out 1234 x
    +port out 1234 15
    +port in 1234 x
    +
    + + + + + +
    + + +

    PRINT

    +

    Displays text or the contents of a variable onto the screen. This will also move the cursor onto a +new line after printing, unless the command is followed by a space and semi-colon. Example:

    + +
    +print "Hello, world!"
    +
    +$1 = "Some text"
    +print $1
    +
    +x = 123
    +print x
    +
    +$2 = "Mike"
    +print "No newlines here, " ;
    +print $2
    +
    + +

    Note that for numerical variables, the PRINT command also supports two extra keywords:

    + +
    +x = 109
    +print x
    +print chr x
    +print hex x
    +
    + +

    In the first print command, the output is 109. In the second, the output is the ASCII character +for 109 -- that is, 'm'. And in the third command, it shows the hexadecimal equivalent of 109.

    + + + + +
    + + +

    RAND

    +

    Generate a random integer number between two values (inclusive) and store it +in a variable. Example:

    + +
    +rem *** Make X a random number between 50 and 2000 ***
    +
    +rand x 50 2000
    +
    + + + + + +
    + + +

    READ

    +

    Read data bytes from a label, first specifying the offset and a variable into which to read. For instance, +in the following example we read a small program and poke it into memory locations 50000 to 50012. We then +call that location to run the program:

    + +
    +y = 1
    +
    +for x = 50000 to 50012
    +  read mydata y a
    +  poke a x
    +  y = y + 1
    +next x
    +
    +call 50000
    +
    +waitkey x
    +end
    +
    +mydata:
    +190 87 195 232 173 60 195 89 111 33 13 10 0
    +
    + + + + + +
    + + +

    REM

    +

    A remark -- ie a comment that the BASIC interpreter ignores. Example:

    + +
    +rem *** This routine calculates the cuteness of kittens ***
    +
    + + + + + +
    + + +

    RENAME

    +

    Renames one file to another. Literal strings and string variables are allowed. Afterwards, R contains 0 if the +operation was a success, 1 if the file was not found, 2 if the write operation failed, or 3 if the target file +already exists. Example:

    + +
    +$1 = "myfile.dat"
    +rename "oldfile.txt" $1
    +
    + + + + + +
    + + +

    RETURN

    +

    Switches execution back to the position of the prior GOSUB statement. See GOSUB above for +more information. Example:

    + +
    +return
    +
    + + + + + +
    + + +

    SAVE

    +

    Saves data from memory to a file on the disk. The first parameter is the filename, the second +the location in RAM where the data starts, and the third the number (in bytes) the amount of data to save. After +execution, the R variable contains 1 if the file save operation failed (eg if it's +a write-only medium), 2 if the file already exists, or 0 if it was successful. Examples:

    + +
    +save "myfile.txt" 40000 256
    +
    + +
    +$1 = "myfile.txt"
    +x = 40000
    +y = 256
    +save $1 x y
    +
    + + + + +
    + + +

    SERIAL

    +

    Turns on serial port 1, sends a byte, or receives a byte depending on the following command. There +are two modes: 1200 baud and 9600 baud. Examples:

    + +
    +print "Enabling the serial port at 1200 baud..."
    +serial on 1200
    +
    + +
    +print "Enabling the serial port at 9600 baud..."
    +serial on 9600
    +
    + +
    +print "Sending the number 20 to the serial port, then 50..."
    +x = 20
    +serial send x
    +serial send 50
    +
    + +
    +print "Receiving a byte from the serial port..."
    +serial rec x
    +
    + + + +
    + + +

    SIZE

    +

    Stores the size of the specified file in the S variable and sets R to 0, or sets R to 1 if the +file doesn't exist. Example:

    + +
    +size "kernel.bin"
    +print s
    +
    + + + + +
    + + +

    SOUND

    +

    Generate a note from the PC speaker at the specified frequency, for the specified length of time +in 10ths of a second. Example:

    + +
    +print "Playing a low-middle-ish C for two seconds..."
    +sound 4000 20
    +
    + +

    Note: some quick frequencies. 4000 = C. 3600 = D. 3200 = E. 3000 = F. 2700 = G. 2400 = A. 2100 = B.

    + + + +
    + + +

    STRING

    +

    Get or set bytes in a string variable, specified by an offset. Examples:

    + +
    +$1 = "Hello world"
    +
    +rem *** 121 = ASCII for "y" character ***
    +b = 121
    +
    +string set $1 5 b
    +
    +rem *** Now $1 contains "Helly world" ***
    +print $1
    +
    + + + + +
    + + + + + +

    WAITKEY

    +

    Pauses program execution, awaiting a keypress, and stores the key in the specified +variable. Note some special values: 1 for the Up cursor key; 2 for Down; 3 for Left; +4 for Right; 13 for Enter; 27 for Esc.

    + +
    +waitkey x
    +if x = 'm' then print "m was pressed"
    +if x = 4 then print "You hit the Right cursor key"
    +
    + + + + +
    + +
    + + +

    Samples

    + + +

    Hex dumper

    + +

    Asks for a filename, loads the file data into the start of empty RAM, then loops over it, printing the value +of each byte in hexadecimal format. Note that the S variable is filled with the file size +after the LOAD instruction, so we use it as a counter (counting down) to find out when +we've finished the file.

    + +
    +rem *** Hex dumper ***
    +
    +print "Enter a filename:"
    +input $1
    +
    +x = RAMSTART
    +
    +load $1 x
    +if r = 1 then goto error
    +
    +loop:
    +  peek a x
    +  print hex a ;
    +  print "  " ;
    +  x = x + 1
    +  s = s - 1
    +  if s = 0 then goto finish
    +  goto loop
    +
    +finish:
    +print ""
    +end
    +
    +error:
    +print "Could not load file!"
    +end
    +
    + +
    + + + + +

    MikeTron

    + +

    A one-player version of the classic Tron game -- see the game help text below...

    + +
    +rem *** MikeTron ***
    +
    +cls
    +
    +print "You control a vehicle leaving a trail behind it."
    +print ""
    +print "It is always moving, and if it crosses any part"
    +print "of the trail or border (+ characters), the game"
    +print "is over. Use the Q and A keys to change the direction"
    +print "to up and down, and O and P for left and right."
    +print "See how long you can survive! Score at the end."
    +print ""
    +print "NOTE: May run at incorrect speed in emulators!"
    +print ""
    +print "Hit a key to begin..."
    +
    +waitkey x
    +
    +
    +cls
    +cursor off
    +
    +
    +rem *** Draw border around screen ***
    +
    +gosub setupscreen
    +
    +
    +rem *** Start in the middle of the screen ***
    +
    +x = 40
    +y = 12
    +
    +move x y
    +
    +
    +rem *** Movement directions: 1 - 4 = up, down, left, right ***
    +rem *** We start the game moving right ***
    +
    +d = 4
    +
    +
    +rem *** S = score variable ***
    +
    +s = 0
    +
    +
    +mainloop:
    +  print "+" ;
    +
    +  pause 1
    +
    +  getkey k
    +
    +  if k = 'q' then d = 1
    +  if k = 'a' then d = 2
    +  if k = 'o' then d = 3
    +  if k = 'p' then d = 4
    +
    +  if d = 1 then y = y - 1
    +  if d = 2 then y = y + 1
    +  if d = 3 then x = x - 1
    +  if d = 4 then x = x + 1
    +
    +  move x y
    +
    +  curschar c
    +  if c = '+' then goto finish
    +
    +  s = s + 1
    +  goto mainloop
    +
    +
    +finish:
    +cursor on
    +cls
    +
    +print "Your score was: " ;
    +print s
    +print "Press Esc to finish"
    +
    +escloop:
    +  waitkey x
    +  if x = 27 then end
    +  goto escloop
    +
    +
    +setupscreen:
    +  move 0 0
    +  for x = 0 to 78
    +    print "+" ;
    +  next x
    +
    +  move 0 24
    +  for x = 0 to 78
    +    print "+" ;
    +  next x
    +
    +  move 0 0
    +  for y = 0 to 24
    +    move 0 y
    +    print "+" ;
    +  next y
    +
    +  move 78 0
    +  for y = 0 to 24
    +    move 78 y
    +    print "+" ;
    +  next y
    +
    +  return
    +
    + + +
    + + + + +

    File uppercaser

    + +

    Asks for a filename, loads the file data, converts all the lowercase characters to uppercase, +asks for a new filename, and saves the changed data to that new file. Note that the S +variable is filled with the file size after the LOAD instruction; we save that until +the SAVE operation later so that we save the correct number of bytes. However, we make +a copy of it into the C variable to use as a counter as we move through the file.

    + +
    +rem *** Text file uppercaser ***
    +
    +print "Enter a filename:"
    +input $1
    +
    +x = RAMSTART
    +
    +load $1 x
    +if r = 1 then goto error
    +
    +c = s
    +
    +loop:
    +  peek a x
    +
    +  if a < 97 then goto skip
    +  if a > 122 then goto skip
    +
    +  a = a - 32
    +  poke a x
    +
    +skip:
    +  x = x + 1
    +  c = c - 1
    +
    +  if c = 0 then goto finish
    +  goto loop
    +
    +
    +finish:
    +print "Enter filename to save to:"
    +input $2
    +
    +x = RAMSTART
    +
    +save $2 x s
    +if r = 1 then goto error
    +print "File uppercased and saved!"
    +end
    +
    +error:
    +print "File error!"
    +end
    +
    + + + + +
    + +
    + + +

    Extra

    + + +

    Help

    + + +

    If you have any questions about MikeOS, or you're developing a similar OS and want +to share code and ideas, go to the MikeOS website +and join the mailing list as described.

    + + +
    + + + +

    License

    + +

    MikeOS is open source and released under a BSD-like license (see doc/LICENSE.TXT +in the MikeOS .zip file). Essentially, it means you can do anything you like with the +code, including basing your own project on it, providing you retain the license file and give credit +to the MikeOS developers for their work.

    + + +
    + + +
    + + +
    + + + + diff --git a/doc/handbook-forth.html b/doc/handbook-forth.html new file mode 100755 index 0000000..d989908 --- /dev/null +++ b/doc/handbook-forth.html @@ -0,0 +1,7277 @@ + + + + + MikeOS Forth Handbook + + + + + + + + + + + + +
    +

    Navigate

    +

    Overview

    + +

    Vocabulary

    + + +

    Getting Started

    + +

    Technical

    + +

    Extra

    + + +
    +

    MikeOS Forth Handbook
    +

    +

    For kernel version 4.4, 20 March 2014, or newer - (C) + MikeOS Developers

    +

    Forth version 1.5.3

    +

    If you have any questions, see the MikeOS website + for contact details and mailing list information.
    +

    +

    Click the links on the left to navigate around this + guide.
    +

    +


    +

    +
    +

    Introduction

    + +

    In the early 1960s a computer programmer named Charles + Moore developed what he considered to be a 4th + generation programming language (4GL), Forth. Forth can be + considered to be an application, compiler, language or + operating system depending upon how the program is being + used at any particular time.

    +

    A Forth system consists of a dictionary of words that can + be compiled or executed depending on the machine's current + operating state. The dictionary is further divided into + vocabularies. The same word may be present in more than + one vocabulary and perform differently in each one. The + machine's current context determines which definition is + used. The primary vocabulary where most words are linked + is FORTH.

    +

    Forth is modeled as a two stack virtual machine: one + stack for passing parameters and one to follow the + execution of a program (list of pointers to currently + executing 'words'). It is tempting to think of each word + as a computer subroutine and a program as a collection of + subroutines, however, Forth is defined as a direct + threaded language. Languages that are subroutine threaded + may be considered to be Forth-like, but not true Forth.

    +

    Over the years several standards have been developed that + describe the meaning of the words that comprise the kernel + of a Forth system. This document will rely heavily on + three of these standards: Forth-79, Forth Interest Group + (FIG) and Forth-83. In 1994 a national standards group + developed an all-encompassing standards document; it will + be referenced occasionally. The standards are very + similar, but there are significant differences, in spots, + among them. The Forth-79 standard will be used + preferentially to resolve most conflicts.

    +

    Forth has the reputation of being 'write-once' code, i.e. + it is not possible to understand, change and debug an + existing program. This is the original programmer's + problem and not inherent in the language. If the code is + laid out well and documented using the built-in tools, it + will be no harder to change than any other well-written + code.

    +

    This document is a brief description of a Forth + system that has been developed to work with MikeOS and is + not meant to 'stand alone.' Much information concerning + Forth is available on line. Two books that are very + helpful are Starting Forth by Leo Brodie (a + tutorial that takes one from basic concepts to advanced + use of the language) and FORTH: A Text and Reference + by Mahlon Kelly and Nicholas Spies (a text book in a + tutorial style with an exceptional glossary of most common + Forth words).

    +


    +

    +
    +

    Features

    + +
      +
    • Based on a 16-bit virtual architecture.
    • +
    +
      +
    • Two stacks: parameter stack, S, and return stack, R.
    • +
    +
      +
    • Data is divided into bytes (8 bits), cells (16 bits) + and double words (32 bits).
    • +
    +
      +
    • This implementation is limited to 16-bit CPU + operations and one 64k Intel segment.
    • +
    +
      +
    • Self-contained: a program is built by extending the + Forth system with new words.
    • +
    +
      +
    • Fixed point math. (Words that manipulate floating + point numbers may be defined, but this kernel only + supports fixed point.)
    • +
    +

    This version of Forth is set up to use 7-bit ASCII + characters for input and output.

    +

    Although strings are input as null terminated (ASCII-Z), + strings are stored in the dictionary as 'counted:' one + byte count followed by the (counted) number of characters. + The maximum size counted string is 255 characters. We + further limit this to 32 characters for a name to keep the + word list from becoming unwieldy.

    +

    Logic values: false is numerically equal to zero. Any + non-zero value tests as true. Logic functions return 1 for + true in Forth-79.

    +

    Forth uses post-fix (sometimes called 'reverse Polish') + notation, e.g. 2 3 * = 6. Note that the operation + comes after the variables, not before or between.
    +

    +

    The primary vocabulary is called FORTH. This is usually + where a program is developed, however other vocabularies, + including custom ones, are possible. Other common + vocabularies are ASSEMBLER and EDITOR. Because the host OS + normally handles these functions they are not included in + this implementation.

    +

    [Custom] Forth usually divides a disk into logical + blocks of 1k bytes; except at the driver level, the + hardware disk structure is ignored. This implementation + uses the host built-in file functions to access + information from the host file system rather than + read/write raw disk data.

    +

    [Custom] For faster searching during compilation + the dictionary is split into 16 hash chains. The current + vocabulary modifies the hash function so that only words + in the vocabulary(ies) of interest are found. Typically, a + dictionary search starts in the current vocabulary and + continues in the FORTH vocabulary if the word is not found + in the current one.

    +


    +

    +
    +

    Dictionary

    + +

    Traditionally, Forth words are documented by showing the + before and after parameter stack condition inside a + comment. In-line comments start with '(' and end + with ')'; before and after are separated by two + dashes. E.g. addition could be documented as '( n1 n2 -- + n3 )'. 'n' represents a signed 16-bit value, 'd' a 32-bit + value, 'c' an 8-bit character or byte value, 'u' unsigned + value, 'a' a 16-bit address and 'f' a logic flag. + Additional information may be placed after the final stack + value to describe the operation in more detail. The format + of the additional information is highly dependent on the + actual programmer. Consult the recommended references and + the included source code for details of the behavior of + individual words.

    +

    Note: the author's grouping of words is somewhat + different than either the standards or the text books + mentioned above.

    +


    +

    +
    +

    Forth Vocabulary

    + +

    Math functions

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    *

    +
    +

    Forth-79

    +
    +

    'times'

    +
    +

    */

    +
    +

    Forth-79

    +
    +

    'times + divide'

    +
    +

    */MOD

    +
    +

    Forth-79

    +
    +

    (star + slant) 'times divide mod'

    +
    +

    +

    +
    +

    Forth-79

    +
    +

    plus

    +
    +

    +!

    +
    +

    Forth-79

    +
    +

    'plus + store'

    +
    +

    -

    +
    +

    Forth-79

    +
    +

    minus

    +
    +

    /

    +
    +

    Forth-79

    +
    +

    'divide'

    +
    +

    /MOD

    +
    +

    Forth-79

    +
    +

    (slant) + 'divide mod'

    +
    +

    1+

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    1+!

    +
    +

    79 + uncontrolled

    +
    +

    Inc + memory contents

    +
    +

    1-

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    1-!

    +
    +

    79 + uncontrolled

    +
    +

    Dec + memory contents

    +
    +

    2*

    +
    +

    79 + reserved

    +
    +

    'two + times'

    +
    +

    2**

    +
    +

    Custom

    +
    +

    2^n

    +
    +

    2+

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    2-

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    2/

    +
    +

    Forth-83

    +
    +


    +

    +
    +

    4*

    +
    +

    Custom

    +
    +


    +

    +
    +

    4/

    +
    +

    Custom

    +
    +


    +

    +
    +

    @+

    +
    +

    Custom

    +
    +

    ( n1 a -- + n )

    +
    +

    @-

    +
    +

    Custom

    +
    +

    ( n1 a -- + n )

    +
    +

    ABS

    +
    +

    Forth-79

    +
    +

    (absolute)

    +
    +

    AND

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    C+!

    +
    +

    Custom

    +
    +

    ( c a -- + )

    +
    +

    COM

    +
    +

    79 + uncontrolled

    +
    +

    One's + complement

    +
    +

    D+

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    D+!

    +
    +

    Custom

    +
    +

    ( d a -- + )

    +
    +

    D-

    +
    +

    79 double

    +
    +


    +

    +
    +

    DABS

    +
    +

    79 double

    +
    +

    'd-abs'

    +
    +

    DMAX

    +
    +

    79 double

    +
    +


    +

    +
    +

    DMIN

    +
    +

    79 double

    +
    +


    +

    +
    +

    DNEGAGE

    +
    +

    Forth-79

    +
    +

    Two's + complement

    +
    +

    LSHIFT

    +
    +

    Forth-94

    +
    +

    ( n c -- + n<<c )

    +
    +

    M*

    +
    +

    Forth-94

    +
    +

    ( n1 n2 + -- d )

    +
    +

    M*/

    +
    +

    94 double

    +
    +

    ( d1 n1 + n2 -- d )

    +
    +

    M+

    +
    +

    94 double

    +
    +

    ( d1 n -- + d )

    +
    +

    M/

    +
    +

    Custom

    +
    +

    ( d n1 -- + n )

    +
    +

    MAX

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    MIN

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    MOD

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    NEGATE

    +
    +

    Forth-79

    +
    +

    Two's + complement

    +
    +

    OR

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    RSHIFT

    +
    +

    Forth-94

    +
    +

    ( n c -- + n>>c )

    +
    +

    S>D

    +
    +

    Forth-94

    +
    +

    's to d' + ( n -- d ) sign extend

    +
    +

    SQRT

    +
    +

    Custom

    +
    +

    ( d -- n + )

    +
    +

    T*

    +
    +

    Custom

    +
    +

    ( d n -- + t )

    +
    +

    T/

    +
    +

    Custom

    +
    +

    ( t n -- + d )

    +
    +

    U*

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    U/MOD

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    XOR

    +
    +

    Forth-79

    +
    +


    +

    +
    +
    +
    +

    Use U* and U/MOD in place of + Forth-83 UM* and UM/MOD.

    +

    Data and stack manipulation functions

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    !

    +
    +

    Forth-79

    +
    +

    'store'

    +
    +

    +@

    +
    +

    Custom

    +
    +

    ( a1 a2 + -- n ) 'a' may be offset

    +
    +

    -LEADING

    +
    +

    Custom

    +
    +

    ( addr + cnt -- addr' cnt' )

    +
    +

    -ROT

    +
    +

    Custom

    +
    +

    ( n1 n2 + n3 -- n3 n1 n2 )

    +
    +

    -TEXT

    +
    +

    79 + uncontrolled

    +
    +

    ( a1 n a2 + -- f,t=different )

    +
    +

    -TRAILING

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    2!

    +
    +

    79 double

    +
    +

    'two + store'

    +
    +

    2@

    +
    +

    79 double

    +
    +

    'two + fetch'

    +
    +

    2>R

    +
    +

    Forth-94

    +
    +

    'two to + r'

    +
    +

    2DROP

    +
    +

    79 double

    +
    +

    'two + drop'

    +
    +

    2DUP

    +
    +

    79 double

    +
    +

    'two dup' + (duplicate)

    +
    +

    2OVER

    +
    +

    79 double

    +
    +

    'two + over'

    +
    +

    2R>

    +
    +

    Forth-94

    +
    +

    'two r + from'

    +
    +

    2SWAP

    +
    +

    79 double

    +
    +

    'two + swap'

    +
    +

    3DUP

    +
    +

    Custom

    +
    +

    ( n1 n2 + n3 -- n1 n2 n3 n1 n2 n3 )

    +
    +

    <CMOVE

    +
    +

    79 + reserved

    +
    +

    (backwards) + + + + + + + 'reverse c-move'

    +
    +

    ><

    +
    +

    79 + uncontrolled

    +
    +

    'interchange + + + + + + + bytes'

    +
    +

    >R

    +
    +

    Forth-79

    +
    +

    'to r'

    +
    +

    ?DUP

    +
    +

    Forth-79

    +
    +

    'question + dup'

    +
    +

    @

    +
    +

    Forth-79

    +
    +

    'fetch'

    +
    +

    BLANK

    +
    +

    79 + reserved

    +
    +


    +

    +
    +

    C!

    +
    +

    Forth-79

    +
    +

    (byte) + 'c-store'

    +
    +

    C@

    +
    +

    Forth-79

    +
    +

    'c-fetch'

    +
    +

    CMOVE

    +
    +

    Forth-79

    +
    +

    'c-move'

    +
    +

    COUNT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    DEPTH

    +
    +

    Forth-79

    +
    +

    Parameter + stack depth

    +
    +

    DROP

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    DUP

    +
    +

    Forth-79

    +
    +

    (duplicate)

    +
    +

    ERASE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    FILL

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    L!

    +
    +

    Custom

    +
    +

    ( n seg + off -- ) long, intersegment

    +
    +

    L@

    +
    +

    Custom

    +
    +

    ( seg off + -- n )

    +
    +

    LC!

    +
    +

    Custom

    +
    +

    ( c seg + off -- )

    +
    +

    LC@

    +
    +

    Custom

    +
    +

    ( seg off + -- c >> zero extended byte )

    +
    +

    LOWER>UPPER

    +
    +

    Custom

    +
    +

    ( c -- c' + )

    +
    +

    OVER

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    PICK

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    R>

    +
    +

    Forth-79

    +
    +

    'r from'

    +
    +

    ROLL

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ROT

    +
    +

    Forth-79

    +
    +

    (rotate)

    +
    +

    S0

    +
    +

    79 + uncontrolled

    +
    +

    Report + TOS

    +
    +

    SEGMOVE

    +
    +

    Custom

    +
    +

    ( fs fa + ts ta #byte -- )

    +
    +

    SP@

    +
    +

    79 + reserved

    +
    +


    +

    +
    +

    SWAP

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    XFER

    +
    +

    Custom

    +
    +

    ( a1 a2 + -- >> transfers contents of 1 to 2 )

    +
    +
    +
    +

    2ROT, MOVE (use CMOVE) and R@ + (use I) are not included in this implementation.

    +

    Keyboard input and CRT output

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    #

    +
    +

    Forth-79

    +
    +

    'sharp'

    +
    +

    #>

    +
    +

    Forth-79

    +
    +

    End + number conversion

    +
    +

    #S

    +
    +

    Forth-79

    +
    +

    Convert + numbers

    +
    +

    #TIB

    +
    +

    Forth-83

    +
    +

    System + variable => characters left in current + input stream

    +
    +

    $

    +
    +

    Custom

    +
    +

    Temporary + (next number input only) base 16

    +
    +

    %

    +
    +

    Custom

    +
    +

    Temporary + base 2

    +
    +

    (D.)

    +
    +

    Custom

    +
    +

    Format a + signed double

    +
    +

    .

    +
    +

    Forth-79

    +
    +

    'dot'

    +
    +

    .BASE

    +
    +

    Custom

    +
    +

    'dot + base' = BASE @ .

    +
    +

    .R

    +
    +

    79 + reserved

    +
    +

    Right-justified + + + + + + + number

    +
    +

    .S

    +
    +

    Forth-94

    +
    +

    Show + parameter stack

    +
    +

    0

    +
    +

    Custom

    +
    +

    System + constant for speed and size

    +
    +

    0.

    +
    +

    Custom

    +
    +

    System + constant

    +
    +

    1

    +
    +

    Custom

    +
    +

    System + constant

    +
    +

    1.

    +
    +

    Custom

    +
    +

    System + constant

    +
    +

    2

    +
    +

    Custom

    +
    +

    System + constant

    +
    +

    <#

    +
    +

    Forth-79

    +
    +

    Begin + number conversion

    +
    +

    >IN

    +
    +

    Forth-79

    +
    +

    System + variable => offset into input stream

    +
    +

    ?

    +
    +

    Forth-79

    +
    +

    'question' + + + + + + = @ .

    +
    +

    BASE

    +
    +

    Forth-79

    +
    +

    System + variable

    +
    +

    BASE!

    +
    +

    Custom

    +
    +

    'base + store'

    +
    +

    BINARY

    +
    +

    Custom

    +
    +


    +

    +
    +

    BELL

    +
    +

    79 + uncontrolled

    +
    +


    +

    +
    +

    BL

    +
    +

    79 + reserved

    +
    +

    System + constant = space = 32

    +
    +

    CONVERT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    CR

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    D.

    +
    +

    79 double

    +
    +

    'd-dot'

    +
    +

    D.R

    +
    +

    79 double

    +
    +

    'd dot r'

    +
    +

    DECIMAL

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    EMIT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    EXPECT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    HEX

    +
    +

    79 + reserved

    +
    +


    +

    +
    +

    HLD

    +
    +

    Custom

    +
    +

    System + variable; address for HOLD

    +
    +

    HOLD

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    KEY

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    NUMBER

    +
    +

    79 + reserved

    +
    +

    Counted + string to double

    +
    +

    OCTAL

    +
    +

    79 + reserved

    +
    +


    +

    +
    +

    OK

    +
    +

    Custom

    +
    +

    Say 'ok'

    +
    +

    Q

    +
    +

    Custom

    +
    +

    Temporary + base 8

    +
    +

    SIGN

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    SPACE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    SPACES

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    SPAN

    +
    +

    Forth-83

    +
    +

    System + variable

    +
    +

    TIB

    +
    +

    Forth-83

    +
    +

    Returns + address of input buffer (text or disk)

    +
    +

    TYPE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    U.

    +
    +

    Forth-79

    +
    +

    (unsigned) + + + + + + 'u dot'

    +
    +

    U.R

    +
    +

    79 + reserved

    +
    +

    'u dot r'

    +
    +
    +
    +

    Conditional structures

    + +

    IF ... ELSE ... THEN

    +

    C@SWITCH ... ENDSWITCH

    +

    SWITCH ... ENDSWITCH

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    0<

    +
    +

    Forth-79

    +
    +

    'zero + less than'

    +
    +

    0=

    +
    +

    Forth-79

    +
    +

    'zero + equal'

    +
    +

    0>

    +
    +

    Forth-79

    +
    +

    'zero + greater than'

    +
    +

    <

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    =

    +
    +

    Forth-79

    +
    +

    'equal'

    +
    +

    >

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ?CELL

    +
    +

    Custom

    +
    +

    ( n -- n + f,t=word )

    +
    +

    ?PRINTABLE

    +
    +

    Custom

    +
    +

    ( c -- + f,t=printable )

    +
    +

    D0=

    +
    +

    79 double

    +
    +


    +

    +
    +

    D<

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    D=

    +
    +

    79 double

    +
    +


    +

    +
    +

    DU<

    +
    +

    79 double

    +
    +

    'd u less + than'

    +
    +

    FALSE

    +
    +

    Forth-94

    +
    +

    ( -- 0 )

    +
    +

    FALSE!

    +
    +

    Custom

    +
    +

    ( a -- + >> stores 0 in address )

    +
    +

    NOT

    +
    +

    Forth-79

    +
    +

    Alias for + 0=

    +
    +

    STAY

    +
    +

    Custom

    +
    +

    ( f -- + >> exit if false )

    +
    +

    TRUE

    +
    +

    Forth-94

    +
    +

    ( -- t )

    +
    +

    U<

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    WITHIN

    +
    +

    Forth-94

    +
    +

    ( n n2 n3 + -- f >> true if n2 <= n < n3 )

    +
    +

    {

    +
    +

    Custom

    +
    +

    Start + option compile

    +
    +

    }

    +
    +

    Custom

    +
    +

    End + option compile

    +
    +
    +
    +

    NOT may also be used for 0= .

    +

    Loop structures

    + +

    BEGIN ... AGAIN [Custom] + Only an abort terminates the loop.

    +

    BEGIN ... UNTIL

    +

    BEGIN ... WHILE ... REPEAT

    +

    DO ... LOOP

    +

    DO ... +LOOP

    +

    DO ... /LOOP [Custom] + Unsigned limit test.

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    2LEAVE-EXIT

    +
    +

    Custom

    +
    +

    Leave 2 + loops and exit word

    +
    +

    I

    +
    +

    Forth-79

    +
    +

    'eye'

    +
    +

    I'

    +
    +

    79 + reserved

    +
    +

    'I-prime'

    +
    +

    J

    +
    +

    Forth-79

    +
    +

    'jay'

    +
    +

    J'

    +
    +

    Custom

    +
    +

    'j-prime'

    +
    +

    K

    +
    +

    79 + reserved

    +
    +

    'kay'

    +
    +

    LEAVE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    LEAVE-EXIT

    +
    +

    Custom

    +
    +

    Leave + loop and exit word

    +
    +
    +
    +

    Defining (dictionary) words

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +

    '

    +
    +

    Modified + 79

    +
    +

    'tick'; + returns CFA, state smart

    +
    +

    (

    +
    +

    Forth-79

    +
    +

    Start + comment

    +
    +

    )

    +
    +

    Not + actual word

    +
    +

    End + comment

    +
    +

    ,

    +
    +

    Forth-79

    +
    +

    'comma'

    +
    +
    +
    + + + + + + + + +
    +

    ."

    +
    +

    Modified + 79

    +
    +

    'dot + quote', state smart

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    2CONSTANT

    +
    +

    79 double

    +
    +


    +

    +
    +

    2VARIABLE

    +
    +

    79 double

    +
    +


    +

    +
    +

    :

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ;

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ;CODE

    +
    +

    79 + assembler

    +
    +


    +

    +
    +

    ;code

    +
    +

    Forth-94

    +
    +

    Run-time + header for development

    +
    +

    >BODY

    +
    +

    Forth-83

    +
    +

    CFA → PFA

    +
    +

    ABORT"

    +
    +

    Forth-83

    +
    +

    'abort + quote', state smart

    +
    +

    ALLOT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ARRAY

    +
    +

    Custom

    +
    +

    Array of + bytes

    +
    +

    ASSEMBLER

    +
    +

    79 + assembler

    +
    +

    vocabulary

    +
    +

    C,

    +
    +

    79 + reserved

    +
    +

    'c comma' + (compile)

    +
    +

    CFA

    +
    +

    FIG

    +
    +

    PFA → CFA

    +
    +

    CVARIABLE

    +
    +

    Custom

    +
    +

    Byte + variable

    +
    +

    COMPILE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    CONSTANT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    CONTEXT

    +
    +

    Forth-79

    +
    +

    System + [double] variable

    +
    +

    CREATE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    CURRENT

    +
    +

    Forth-79

    +
    +

    System + [double] variable

    +
    +

    DCLIT

    +
    +

    Custom

    +
    +

    ( c1 c2 + -- )

    +
    +

    DEFINITIONS

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    DOES>

    +
    +

    Forth-79

    +
    +

    'does'

    +
    +

    EDITOR

    +
    +

    79 + reserved

    +
    +

    vocabulary

    +
    +

    EMPTY

    +
    +

    Custom

    +
    +

    Go back + to last protected dictionary

    +
    +

    FENCE

    +
    +

    Custom

    +
    +

    System + variable

    +
    +

    FORGET

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    FORTH

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    H

    +
    +

    Custom

    +
    +

    System + variable contains 'here'

    +
    +

    H-LIST

    +
    +

    Custom

    +
    +

    Print + dictionary hash chain

    +
    +

    HEADS

    +
    +

    Custom

    +
    +

    System + array of hash pointers

    +
    +

    HERE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    ID.

    +
    +

    Custom

    +
    +

    ( lfa -- + >> prints name of word at link addr + )

    +
    +

    IMMEDIATE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    L>CFA

    +
    +

    Custom

    +
    +

    LFA → CFA

    +
    +

    L>NFA

    +
    +

    Custom

    +
    +

    LFA → NFA

    +
    +

    L>PFA

    +
    +

    Custom

    +
    +

    LFA → PFA

    +
    +

    LAST

    +
    +

    79 + uncontrolled

    +
    +

    System + variable = last word created

    +
    +

    LITERAL

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    PAD

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    PROTECT

    +
    +

    Custom

    +
    +


    +

    +
    +

    SMUDGE

    +
    +

    FIG

    +
    +


    +

    +
    +

    STATE

    +
    +

    Forth-79

    +
    +

    System + variable

    +
    +

    UNSMUDGE

    +
    +

    FIG

    +
    +


    +

    +
    +

    VARIABLE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    VLIST

    +
    +

    FIG

    +
    +

    (vocabulary) + + + + + + 'v list'

    +
    +

    VOCABULARY

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    [

    +
    +

    Forth-79

    +
    +

    'left + bracket' stop compiling
    +

    +
    +

    ]

    +
    +

    Forth-79

    +
    +

    'right + bracket' restart compiling
    +

    +
    +
    +
    +

    Since ' and ." are state + smart, ['] and .( are not needed.

    +

    VLIST replaces Forth-83 + WORDS.

    +

    Execution control words

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    'ABORT

    +
    +

    Custom

    +
    +

    Vectored + abort address

    +
    +

    @EXECUTE

    +
    +

    Custom

    +
    +

    For + vectored execute

    +
    +

    ABORT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    EXECUTE

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    EXIT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    INTERPRET

    +
    +

    79 + uncontrolled

    +
    +


    +

    +
    +

    QUERY

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    QUIT

    +
    +

    Forth-79

    +
    +


    +

    +
    +

    WORD

    +
    +

    Forth-79

    +
    +


    +

    +
    +
    +
    +

    Miscellaneous

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    !CURSOR

    +
    +

    Custom

    +
    +

    (set) + 'store cursor'

    +
    +

    .AZ

    +
    +

    Custom

    +
    +

    Print a + null terminated string (ASCII-Z)

    +
    +

    /0

    +
    +

    Custom

    +
    +

    Divide 0 + interrupt

    +
    +

    ?MEM

    +
    +

    Custom

    +
    +

    Amount of + memory left for new dictionary entries

    +
    +

    @CURSOR

    +
    +

    Custom

    +
    +

    (get) + 'fetch cursor'

    +
    +

    ASCII

    +
    +

    79 + uncontrolled

    +
    +

    Numerical + value of next word; state smart

    +
    +

    CLS

    +
    +

    Custom

    +
    +

    Clear + screen

    +
    +

    FNAME

    +
    +

    Custom

    +
    +

    System + byte array: the file name used for file + access

    +
    +

    FORTHSEG

    +
    +

    Custom

    +
    +

    ( -- seg + ), Intel segment system currently resides + in

    +
    +

    FIRSTSEG

    +
    +

    Custom

    +
    +

    ( -- seg + ), first available full segment

    +
    +

    ROWS

    +
    +

    Custom

    +
    +

    Rows + available in display

    +
    +

    SYSTEM

    +
    +

    Custom

    +
    +

    Return to + host system

    +
    +

    VERSION

    +
    +

    Custom

    +
    +

    Print + version string

    +
    +

    \

    +
    +

    Custom

    +
    +

    Comment + to end of line

    +
    +
    +
    +


    +

    +
    +

    Getting started

    + +

    Forth is a very 'lean' system. There is no terminal + prompt; only the default blinking cursor. When starting + the system the version string will be displayed, followed + by the command completed satisfactorily message (ok).

    +

    Start the system and press the <Enter> key a couple + of times. Each time the system should say 'ok' and the + cursor move to the next line for more input. To return to + the host system at any time type SYSTEM<Enter>.

    +

    The system can do much in its interpretive mode. Try (pay + particular attention to the spaces between each 'word':

    +

    5 2 + .<Enter>

    +

    Remember, + + + + + + Forth uses post-fix notation. The system should have + responded with '7 + ok'. The 'dot' tells Forth to print the top + number on the parameter stack.

    +

    Now, + let's create the traditional first program; type:

    +

    : HW ." Hello World!" ;<Enter>

    +

    Execute + + + + + + the program (word) by typing HW<Enter>. ':' creates a new + dictionary entry. 'HW' is the name we gave this word + that was compiled into the Forth vocabulary; you could + have used any other legal name. ' ." ' compiles a + literal string that will be displayed when the word is + executed. Finally, ';' completes the dictionary entry + and makes it findable.

    +

    Here's + + + + + + another short 'program' to try.

    +

    : LP 5 0 DO I . LOOP ; <Enter>

    +

    Execute the word by typing LP<Enter>. + + + + + + + Did the system respond with '0 + 1 2 3 4 ok'?

    +

    Alternately you could use : LP [ 5 0 ] DCLIT + DO I . LOOP ; <Enter>

    +

    Forth + uses a 2 stack virtual machine model. 'I' retrieves + the working loop counter of the outermost loop and + places it on the parameter stack and 'dot' prints out + a signed number. Loop counters and limits are stored + on the return stack so that the parameter stack can + still be easily accessed inside of loops.

    +

    DCLIT + requires that the 2 literals (constants) each fit into + a signed byte. The '[' stops compilation and allows + the numbers to be placed on the parameter stack. The + ']' resumes compilation and the definition completes + as before. This construct is a little quicker and + saves a little space in the dictionary.

    +

    Experiment and enjoy.

    +


    +

    +
    +

    Technical

    + +

    Register usage (generally):

    +
      +
    • ax general purpose arithmetic
    • +
    +
      +
    • bx general purpose and BIOS access
    • +
    +
      +
    • cx counter and general purpose
    • +
    +
      +
    • dx general purpose arithmetic
    • +
    +
      +
    • bp return stack (R)
    • +
    +
      +
    • sp parameter stack (S)
    • +
    +
      +
    • si execution pointer
    • +
    +
      +
    • di (temporary) pfa pointer when processing a colon + definition
      +
    • +
    +

    The system follows the Forth-79 standard as much as + possible. Although it is permissible to specify the system + as, "FORTH-79 Standard Subset," the author has chosen not + to do so.

    +

    Bytes have a numeric range of -128 to +127. Cells (16-bit + words), -32768 to +32767. And double words (32 bits), + -2,147,483,648 to +2,147,483,647.

    +

    Fixed point math can be remarkably precise. E.g. 355 113 + */ is excellent approximation of multiplying by π.

    +

    Forth words may perform 2 different operations: one + during word compilation and one during execution. In the + "Getting Started" section it was seen how ' ." ' compiled + a literal string into the dictionary during compilation + and then printed that string during execution.

    +

    This system uses the following dictionary entry format:

    +

    LFA = Link Field Address: a + pointer to the previous definition in this hash list

    +

    NFA = Name Field Address: a + counted string that represents the name and flags. The + maximum number of characters in a name is 31 (bits 4 to + 0). Bit 5 is used to 'smudge' an entry so that later + definitions can replace early ones. Bit 6 is reserved. And + bit 7 indicates immediate execution rather than + compilation. The name field may be 2 to 32 bytes long.

    +

    CFA = Code Field Address: + pointer to actual code to execute. For assembler (code) + definitions this is usually the beginning of the next + cell. (The mathematical operators at the start of the + dictionary are typical.) For colon definitions this points + to the colon run-time code.

    +

    PFA = Parameter Field + Address: the parameters needed by this definition. For + code definitions this would be machine code. For colon + definitions this would be a list of CFAs that make up this + word's definition (description). For constants and + variables this would be actual data.

    +

    When using an external compiler the link and name fields + may be omitted (entry is considered headerless) to + conserve space. Words using these headerless entries will + still execute, but the name will not be found for use in + future definitions. Alternatively, to save space, the + headers may be placed in a separate data segment during + compilation: only the final word needs to be able to be + found to execute an intricate program.

    +

    In the original specification of Forth higher level + definitions consisted of either code or colon types. There + are Forth-like systems that provide for inline code in + colon definitions. This construct has rarely been + advantageous in a true Forth system; the increased size + and complexity out weighs any speed gains.

    +

    CONTEXT and CURRENT are double variables (32-bits) that + contain lists of VOCABULARIES. A vocabulary is designated + by a nibble, 1-15, with null being 'none.' A 32-bit + variable has 8 nibbles and thus may designate up to 8 + vocabularies. The dictionary hash function uses the + vocabulary designator and the 7-bit ASCII value of the + first letter of the word to reduce the search to only one + of the 16 chains. The least significant nibble of CURRENT + specifies where new words are to be compiled. CONTEXT + specifies which vocabularies and in what order they are to + be searched for words making up the current word being + compiled.

    +

    This implementation follows the extended FIG model for + preventing inadvertent tampering with the kernel. There + are two arrays that describe the dictionary. One, GOLDEN, + contains the variables that map the protected portion of + the dictionary. The second array, HEADS, contains the + variables that map the working dictionary. The dictionary + may be returned to its golden state by using the word + EMPTY. Alternately, the FENCE can be moved to the current + working position with the word PROTECT.

    +

    This implementation was written to take advantage of many + of the input and output functions available in an IBM + compatible BIOS. All keyboard entry and screen output, + specifically, goes through the BIOS. The main OS (PC DOS + or MikeOS) is used to gain access to operating files on + the disk.

    +

    Two of the most basic and important operations in the + kernel are separating a word from the input stream and + finding a word in the dictionary. Many other operations + cannot be completed unless these two function properly. To + separate a word the system needs a delimiter. The most + common delimiter is space (or BL). Generally, with the + input stream pointer set, 'BL WORD' will separate the next + word from the stream and transfer the string to HERE + 2. + This sets it up to compile a new word -- link field goes + at HERE -- or place a literal string in the dictionary -- + CFA of defining word goes HERE. Although there are + standards, many programmers (as does the author) prefer + non-standard stack conditions for dictionary searches. In + this implementation 'FIND' is left headerless to prevent + confusion.

    +

    Most macro processors would have difficulty building the + dictionary hash lists during the assembly of the code. + This system uses a slightly different approach: the NASM + macro processor builds one long chain during the assembly, + then the Forth start-up code splits the single chain into + the desired hash lists. This can take a significant amount + of time on an 8-bit, 1 MHz microprocessor, but is not + noticeable on modern processors. All words in the initial + code must be in the FORTH vocabulary. The start up penalty + can be saved by saving the after start-up modified code as + an appropriate '.bin' or '.com' executable. The Forth word + 'write_exec <file-name>' will do this for the user. + Note that 'write_exec' is one of the few Forth words in + lower case; this helps prevent inadvertent writes to the + disk.

    +

    To do any serious work with a language it should be + possible to develop source as a text file and load it into + the system. Preferably, a way to store the updated + information would also be available. The 'write_exec' word + of this implementation provides a unique way to do the + latter; once the source is loaded and compiled by the + Forth kernel a new executable can be written to disk, + which includes the newly compiled code. To 'seal' the code + it is only necessary to tell the start-up code to go to a + word that will not exit nor abort. The former desire is + met by the word 'INCLUDE <file name>'. As an example + GEN.4TH is included in this package. At the Forth blinking + cursor type INCLUDE + GEN.4TH <enter>. GEN.4TH looks like a + normal text file and may be opened with any text + processor. The 'write_exec' word is contained within this + file so that the new executable is generated, as well. + [INCLUDE cannot currently use nested disk access, i.e. the + first INCLUDEd file cannot have an INCLUDE in its script.]

    +


    +

    +
    +

    Extra

    + +

    Help

    + +

    If you have any questions about MikeOS, or you're + developing a similar OS and want to share code and ideas, + go to the MikeOS + website and join the mailing list as described.

    +
    +

    License

    + +

    MikeOS is open source and released under a BSD-like + license (see doc/LICENSE.TXT in the + MikeOS .zip file). Essentially, it means + you can do anything you like with the code, including + basing your own project on it, providing you retain the + license file and give credit to the MikeOS developers for + their work.

    +
    +
    + + diff --git a/doc/handbook-sysdev.html b/doc/handbook-sysdev.html new file mode 100755 index 0000000..51c5c05 --- /dev/null +++ b/doc/handbook-sysdev.html @@ -0,0 +1,505 @@ + + + + + + +The MikeOS System Developer Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    Navigate

    + +

    Overview

    + + +

    Building

    + + +

    Modifying

    + + +

    Extra

    + + +
    + +

    The MikeOS System Developer Handbook

    + +

    For version 4.7, 9 April 2022 - (C) MikeOS Developers

    + +

    This documentation file explains how to build MikeOS from the source code, make changes +to the kernel, and add new system calls. If you have any questions, see +the MikeOS website for contact details +and mailing list information.

    + +

    Click the links on the left to navigate around this guide.

    + +
    + + +
    + + +

    Overview

    + + +

    Introduction

    + +

    The MikeOS kernel is written in 16-bit x86 real mode assembly language. This provides easy access +to BIOS routines for handling the keyboard, screen and floppy drive, so that we don't need complicated +drivers. Therefore most of the code is focused on actual OS aspects: loading programs, +system calls and so forth.

    + +

    Additionally, MikeOS avoids the real mode segmentation complications by existing in a single 64KiB segment. +The first 32KiB (0 - 32767) of RAM is reserved for the kernel; the second 32KiB is for external program code +and memory.

    + + +
    + + + +

    Structure

    + +

    These are the most important files and directories in the MikeOS zip file:

    + +
      +
    • source/ -- Contains the entire OS source code
    • +
    • source/bootload/ -- Source to generate BOOTLOAD.BIN, which is added to the disk image when building
    • +
    • source/features/ -- Components of MikeOS such as FAT12 support, string routines, the BASIC interpreter etc
    • +
    • source/kernel.asm -- The core kernel source file, which pulls in other source files
    • +
    • programs/ -- Source code for programs added to the disk image
    • +
    + + +
    + + + + +

    Memory map

    + +

    This is the makeup of the 64KiB memory segment after MikeOS has loaded:

    + +
    + +
    + + + +

    +0 - 24575 (hex: 0h - 5FFFh)
    +24KiB kernel executable code
    +
    - - - - - - - - - - - - - - -

    +24576 - 32767 (hex: 6000h - 7FFFh)
    +8KiB kernel disk operation buffer

    +
    +32768 - 65535 (hex: 8000h - FFFFh
    +32KiB space for external programs
    +
    + +
    + +

    So, the first 32KiB is devoted to the MikeOS kernel code and its 8KiB buffer for performing disk operations. +After that we have another 32KiB of memory, this time for external programs. These are loaded at the 32KiB point +and hence need to be ORGed to 32768 as described in the App Developer Handbook.

    + + +
    + + + +

    Code path

    + +

    When the PC starts up, it loads the bootblock, BOOTLOAD.BIN, that was inserted into +the first sector (512 bytes) of the floppy disk image by the build script. It loads this at memory location +31744 (7C00h in hex) and begins executing it.

    + +

    BOOTLOAD.BIN then scans the floppy disk for KERNEL.BIN and loads it at +memory location 2000h:0000h. Here, the 2000h is the segment and 0000h is the offset +in that segment -- you don't need to concern yourself with this, but effectively it means that the kernel is +loaded at location 131072 (128KiB) in the PC's RAM. (You get a complete memory location by multiplying the segment +by 16 and adding the offset.)

    + +

    Once the bootloader has loaded the kernel, it jumps to memory location 131072 (aka 2000h:0000h) +to begin executing it. After this, for simplicity we ignore segments and just use offsets (0000h to FFFFh), +thereby giving us 64KiB of RAM to use.

    + +

    At the start of the kernel we have a series of jmp instructions. +Why are these here? Well, the system calls are in semi-random places in the kernel executable. +As MikeOS evolves, the exact locations of these system calls shifts around; an external program can't guarantee +where they are. So we have a list of vectors right at the very start of the kernel which jmp to these +calls, so an external program can call these vectors and know that they'll never move!

    + +

    There's a jmp just before these vectors to skip over them, and then the main kernel execution +starts, setting up various things and offering the user a choice of a program list or command line interface.

    + + +
    + + +
    + + +

    Building

    + + +

    Linux

    + +

    Build requirements: the NASM assembler, dosfstools package, 'mkisofs' utility and root access. We need root +access because we loopback-mount the floppy disk image to insert our files.

    + +

    To build MikeOS, open a terminal and switch into the expanded MikeOS package. Enter sudo bash +in Ubuntu-flavoured distros, or just su in others, to switch to the root user. Then enter:

    + +
    +./build-linux.sh
    +
    + +

    This will use NASM to assemble the bootloader, kernel and supplied programs, then write the bootloader to the +mikeos.flp floppy disk image in the disk_images/ directory. (It writes the 512-byte +bootloader to the first sector of the floppy disk image to create a boot sector and set up a DOS-like +filesystem.) Next, the build script loopback-mounts the mikeos.flp image onto the filesystem - in other +words, mounting the image as if it was a real floppy. The script copies over the kernel (kernel.bin) +and binaries from the programs/ directory, before unmounting the floppy image.

    + +

    With that done, the script runs the 'mkisofs' utility to generate a CD-ROM ISO image of MikeOS, injecting +the floppy image as a boot section. So we end up with two files in the disk_images/ directory: +one for floppy disks and one for CD-Rs. You can now use them in an emulator or on a real PC as described in +the Running section above.

    + + +
    + + + +

    Windows

    + +

    Get the latest version of NASM for Windows from this site +(look for the 'win32' package. Then extract the nasm.exe file into your Windows folder (or somewhere in the path).

    + +

    The ImDisk Virtual Disk Driver is needed since Windows does not have a +built-in mechanism for loopback drives. Get it from here +(or Google it if the link is outdated). After downloading run imdiskinst.exe to install. Follow the default prompts +during the install. Also get PartCopy for copying +the bootloader on to the disk image.

    + +

    To build MikeOS, double-click on build-win.bat or run it from the command line. +This batch file calls NASM to do the work needed to compile MikeOS and its applications. +This script mounts the floppy disk image as if it were a real disk, using:

    + +
    +imdisk -a -f mikeos.flp -s 1440K -m B:
    +
    + +

    You can use that command outside of build-win.bat if you want to add files to mikeos.flp, +and unmount it with:

    + +
    +imdisk -d -m B:
    +
    + +

    Lastly, to test in the QEMU PC emulator, +Extract QEMU to somewhere on your computer -- C:\ is best. Then enter: the following to run MikeOS under QEMU:

    + +
    +qemu.exe -L . -m 4 -boot a -fda mikeos.flp -soundhw all -localtime
    +
    + +

    Make sure you put the proper path names in! Ask on the mailing list if you have any problems.

    + + + +
    + + +

    Others

    + +

    Along with the scripts for building on Linux and Windows, you'll also find scripts for macOS and OpenBSD. +These have not been as thoroughly tested as the others, so if you find any glitches, please let us know!

    + +

    If you want to make a build script for a new platform, it needs to:

    + +
      +
    1. Assemble the bootloader and add it to the first sector of mikeos.flp
    2. +
    3. Assemble the kernel and copy it onto the floppy
    4. +
    5. Assemble the add-on programs and copy them onto the floppy
    6. +
    + +

    So you will need some way of copying the 512 byte bootsector into a floppy image, and loopback mounting the +image to copy across the kernel and programs.

    + + +
    + + + +
    + + +

    Modifying

    + + +

    Overview

    + +

    To test out code, the simplest approach is to create a new app in the programs/ directory, build +MikeOS and run your program. You can then be guaranteed that your code isn't interfering with the kernel code (at least +at the assembling stage!). When you're happy with it, you may want to introduce it into source/kernel.asm +or a specific file in source/features/.

    + +

    Note that the files in source/features/ correspond to the system calls in programs/mikedev.inc +(and detailed in the App Developer Handbook), but those source files also include internal calls that are used by the kernel and +are not accessible to user programs. So use 'grep' or the search tool of your choice to find specific calls if they're not +available through the API.

    + +
    + + + +

    System calls

    + +

    Adding new system calls is easy and fun - it extends MikeOS! So if you want to help out, this is the best way to start. +Open up source/features/screen.asm in a text editor and paste in the following after the header text:

    + + +
    +; -----------------------------------------------------------------
    +; os_say_hello -- Prints 'Hello' to the screen
    +; IN/OUT: Nothing
    +
    +os_say_hello:
    +	pusha
    +
    +	mov si, .message
    +	call os_print_string
    +
    +	popa
    +	ret
    +
    +	.message db 'Hello', 0
    +
    + +

    There we have it: a new system call that prints 'Hello' to the screen. Hardly a much-needed feature, but it's +a starting point. The first three lines are comments explaining what the call does, and what registers it accepts +or returns (like variable passing in high-level languages). Then we have the os_say_hello: label +which indicates where the code starts, before a pusha.

    + +

    All system calls should start with pusha and end with popa before ret: +this stores registers on the stack at the start, and then pops them off at the end, so that we don't end up changing +a bunch of registers and confusing the calling program. (If you're passing back a value, say in AX, you should +store AX in a temporary word and drop it back in between the popa and ret, as +seen in os_wait_for_key in keyboard.asm.)

    + +

    The body of our code simply places the location of our message string into the SI register, then calls another +MikeOS routine, os_print_string. You can freely call other routines from your own system call.

    + +

    Once we've done this, we can access this routine throughout the kernel. But what about external programs? They +have no idea where this call is in the kernel! The trick we use is vectors - a bunch of jmp +instructions at the start of our kernel code, which jump to these routines. Because these vectors are at the start, +they never change their position, so we always know where they are.

    + +

    For instance, right now, your new system call may be at 0x9B9D in the kernel. But if you add another call before it, +or someone else does, it may move to 0x9FA6 in the kernel binary. We simply don't know where it's going to be. But +if we put at vector at the start of our kernel, before anything else happens, we can use that as the starting point +as the vector will never move!

    + +

    Open up source/kernel.asm and scroll down to the list of system call vectors. You can see they start +from 0003h. Scroll to the bottom of the list and you'll see something like this:

    + +
    +	jmp os_string_tokenize		; 00CFh
    +
    + +

    The comment here indicates where this bit of code lies in the kernel binary. Once again, it's static, and +basically says: if your program wants to call os_string_tokenize, it should call 00CFh, as +this jumps to the required routine and will never change position.

    + +

    Let's add a vector to our new call. Add this beneath the existing vectors:

    + +
    +	jmp os_say_hello		; 00D2h
    +
    + +

    How do we know this jmp is at 00D2h in the kernel binary? Well, just follow the pattern in the +jmps above - it's pretty easy to guess. If you're unsure, you can always use +ndisasm to disassemble the kernel and look for the location of the final +jmp in the list.

    + +

    That's all good and well, but there's one last thing: people writing external programs don't want to +call an ugly number like 00C9h when they run our routine. They want to access it by name, so we need +to add a line to mikedev.inc in the programs/ directory:

    + +
    +os_say_hello	equ	00D2h	; Prints 'Hello' to screen
    +
    + +

    Now, any program that includes mikedev.inc will be able to call our routine by name. +Et voila: a brand new system call for MikeOS!

    + + +
    + + + +

    Patches

    + +

    If you've made some improvements or additions to MikeOS and wish to submit them, great! If they're small changes - +such as a bugfix or minor tweak - you can paste the altered code into an email. Explain what it does and where it +goes in the source code, and if it's OK, we'll include it.

    + +

    If your change is larger (e.g. a system call) and affects various parts of the code, you're better off with a +patch. On UNIX-like systems such as Linux, you can use the diff command-line utility to generate +a list of your changes. For this, you will need the original (release) source code tree of MikeOS, along with the +tree of your modified code. For instance, you may have the original code in a directory called +mikeos-4.2/ and your enhanced version in new-mikeos-4.0/.

    + +

    Switch to the directory beneath these, and enter:

    + +
    +diff -ru mikeos-4.2 new-mikeos-4.2 > patch.txt
    +
    + +

    This collates the differences between the two directories, and directs the output to the file patch.txt. +Have a look at the file to make sure it's OK (you can see how it shows which lines have changed), and then attach the +file to an email.

    + +

    Please post fixes and patches to the MikeOS mailing list (see the website).

    + + + +
    + + +
    + + + + + + +

    Extra

    + + +

    Help

    + + +

    If you have any questions about MikeOS, or you're developing a similar OS and want +to share code and ideas, go to the MikeOS website +and join the mailing list as described.

    + + +
    + + + +

    License

    + +

    MikeOS is open source and released under a BSD-like license (see doc/LICENSE.TXT +in the MikeOS .zip file). Essentially, it means you can do anything you like with the +code, including basing your own project on it, providing you retain the license file and give credit +to the MikeOS developers for their work.

    + + +
    + + +
    + + +
    + + + + diff --git a/doc/handbook-user.html b/doc/handbook-user.html new file mode 100755 index 0000000..4ecf966 --- /dev/null +++ b/doc/handbook-user.html @@ -0,0 +1,469 @@ + + + + + + +The MikeOS User Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    Navigate

    + +

    Booting

    + + +

    Running

    + + +

    Extra

    + + +
    + +

    The MikeOS User Handbook

    + +

    For version 4.7, 9 April 2022 - (C) MikeOS Developers

    + +

    This documentation file explains how to boot and use the MikeOS operating system on a real PC or an +emulator. If you have just downloaded MikeOS and want to run it, this is the guide you need. If you have +any questions, see the MikeOS website for contact details +and mailing list information.

    + +

    Click the links on the left to navigate around this guide.

    + +
    + + +
    + + +

    Booting

    + + +

    Disk images

    + +

    After you have extracted the MikeOS .zip file, switch into the +disk_images/ directory and you'll see three files:

    + +
      +
    • mikeos.flp -- Floppy disk image containing MikeOS and programs
    • +
    • mikeos.dmg -- Same as above, but with a Mac-friendly extension
    • +
    • mikeos.iso -- CD ISO image built using the floppy disk image
    • +
    + +

    So, these files are virtual disk images that you can write to real floppy disks or +CD-Rs, or run in a PC emulator as described in a moment.

    + + +
    + + + +

    Writing

    + +

    For running MikeOS on a real PC, you will need to write one of the virtual disk images +to physical media. If you have a USB key then this is simple -- we can write the floppy disk +image to the USB key, and the PC will boot it like a virtual floppy.

    + +

    On Linux, insert your USB key and unmount it when it appears (but don't remove it). Then open a command line +window and enter dmesg to view the kernel messages. You will see an indication at the end of the messages of the device you just plugged +in -- eg /dev/sdb. Note that you just need the device, eg /dev/sdb, rather than the number (eg /dev/sdb1). Then enter (in the disk_images directory):

    + +
    dd if=mikeos.flp of=/dev/sdb
    + +

    Of course, replace sdb with the device node. The key is now ready for booting.

    + +

    On Windows, download the open source Flashnul program, plug in your USB key and +enter flashnul -p to get a list of drives. When you've spotted your USB key, enter +flashnul [number] -L mikeos.flp (in the disk_images directory), replacing [number] +with the number you got before. The key is now ready for booting.

    + +

    Note: if you plug your USB key back into the machine, the operating system may try to alter the +partition structure and stop it from working properly. So treat it as a MikeOS-only key until you +want to reformat it for normal use.

    + +

    For floppy disks, on Windows you can use a program called RawWrite +to copy mikeos.flp to a floppy disk. On Linux, use the dd +utility like this:

    + +
    dd if=mikeos.flp of=/dev/fd0
    + +

    If you want to run MikeOS on a machine that doesn't have a floppy drive and doesn't +boot from USB keys, you can burn and boot the mikeos.iso CD image. Any decent Windows CD burning software will +allow you to write an ISO image to a CD-R; if you don't have one, try InfraRecorder.

    + +

    On Linux, a graphical burning program such as K3b should do the trick, or you can use +the command line:

    + +
    cdrecord -dao dev=/dev/cdrom mikeos.iso
    + + +
    + + + +

    Real PCs

    + +

    At a minimum, any 386 PC with 1MB of memory and a keyboard should be able to run MikeOS. In +fact, you may be able to get it running on an older machine -- please do let us know if so! Just +start your PC with the MikeOS floppy, CD-ROM or USB key inserted, and you should see the initial +dialog screen.

    + +

    On some systems, you may need to change the boot order in your BIOS so that the PC boots +from the floppy, CD or USB key rather than the hard drive.

    + + +
    + + + +

    Emulators

    + +

    A quick way to try MikeOS, and one that doesn't involve writing disk images to physical media, +is to use an emulator. This is particularly useful if you're writing MikeOS software or changing +the OS as described in the other two Handbooks.

    + +

    Some of the best emulators:

    + +
      +
    • QEMU -- Small, simple and open source (link)
    • +
    • VirtualBox -- Very powerful with a good GUI (link)
    • +
    • VMware -- Popular proprietary virtualisation app (link)
    • +
    • Bochs -- Takes a bit of work to set up, but good debugging tools (link)
    • +
    + +

    For VirtualBox and VMware, configure the boot device to use the MikeOS floppy disk or CD ISO image. +With QEMU on Linux, run test-linux.sh, or for QEMU on Windows switch into the directory +where you installed the emulator and enter:

    + +
    +qemu.exe -L . -m 4 -boot a -fda mikeos.flp -soundhw all -localtime
    +
    + +

    You will need to change the path to mikeos.flp accordingly.

    + + +
    + + +
    + + +

    Running

    + + +

    Usage

    + +

    When MikeOS starts up, you'll see a dialog box which gives you the option of a program +list of a command line interface. Using the cursor keys and Enter, choose OK for the former +and Cancel for the latter.

    + +

    In the program list you can select a .BIN or .BAS program with the up/down cursor +keys and hit Enter to run it. Also, you can press Esc to return back to the original list/CLI +selection screen.

    + +

    At the command line, enter DIR to show a list of programs, and HELP +to display inbuilt commands. You can run a program by entering the full filename (eg EDIT.BIN) +or just the name without the extension (eg EDIT). There are also file management commands such +as COPY, REN, DEL and SIZE.

    + + +
    + + + +

    Programs

    + +

    MikeOS includes several programs to perform various tasks and demonstrate features of the OS, such as:

    + +
      +
    • EDIT.BIN -- Simple full-screen text editor (Unix-type text files only)
    • +
    • VEDIT.BIN -- An alternative Vi-like editor
    • +
    • EXAMPLE.BAS -- Demonstration of BASIC features (open it in EDIT.BIN to explore)
    • +
    • FILEMAN.BIN -- Delete, rename and copy files on the floppy disk
    • +
    • HANGMAN.BIN -- Guess the names of cities around the world
    • +
    • MEMEDIT.BAS -- Colourful, powerful memory editor
    • +
    • DRAW.BAS -- ASCII art drawing program
    • +
    • CALC.BAS -- Powerful calculator
    • +
    • SUDOKU.BAS -- Sudoku game
    • +
    • LIFE.BIN -- An implementation of Conway's Game of Life
    • +
    • CF.BAS -- Cosmic Flight game
    • +
    • FORTH.BIN -- Forth interpreter
    • +
    • PONG.BIN -- Pong game (press Esc to exit)
    • +
    • LINES.BIN -- VGA video mode demo (press F to speed up, S to slow down, C to clear and Esc to exit)
    • +
    • MUNCHER.BAS -- Snake-like game (use WASD keys)
    • +
    • ADVNTURE.BAS -- A text adventure
    • +
    • KEYBOARD.BIN -- Musical keyboard; use the bottom row of keys to play and Q to quit
    • +
    • MONITOR.BIN -- Simple machine code monitor (see below)
    • +
    • TERMINAL.BIN -- Minicom-like serial terminal program (see below)
    • +
    • VIEWER.BIN -- Views text files and 320x200x16 PCX images such as SAMPLE.PCX
    • +
    • CODEBYTE.BIN -- Machine code editor; load HELLO.512 for an example
    • +
    + +

    Note that FILEMAN.BIN and EDIT.BIN try to write to the floppy drive, +so if you've booted from a CD-R and try to manipulate files you will see write errors as it's a read-only +medium after burning.

    + + +
    + + + +

    Copying files

    + +

    If you've written MikeOS to a real floppy disk, you can just copy extra files +onto that disk in your file manager. But if you want to add files to the floppy disk images, +that requires a bit of extra work -- you need to access the disk image as if it was a real +floppy. First up is Linux: switch to the MikeOS main directory, then enter the following +commands as root:

    + +
    +mkdir looptmp
    +mount -o loop -t vfat disk_images/mikeos.flp looptmp
    +
    + +

    Now the contents of the MikeOS virtual floppy disk image are accessible in the newly-created looptmp/ +directory. (We have loopback-mounted the disk image onto our filesystem.) Copy your programs into that directory, for example:

    + +
    +cp MYPROG.BIN looptmp/
    +
    + +

    When you're done, unmount the virtual floppy image and remove the temporary directory:

    + +
    +umount looptmp
    +rm -rf looptmp
    +
    + +

    You can now write mikeos.flp to a floppy disk or boot it in an emulator. If you want +to recreate the CD ISO image, run build-linux.sh as root; this will update mikeos.iso +with the new floppy contents.

    + +

    If you're running Windows, you will need a special program to access mikeos.flp as if it +was a real floppy. One tool you can use is the ImDisk +Virtual Disk Driver; download and run it to install. You can then mount the floppy disk image like this:

    + +
    +imdisk -a -f mikeos.flp -s 1440K -m B:
    +
    + +Copy your files into the B: drive. When you are finished, enter: + +
    +imdisk -d -m B:
    +
    + +

    Now the files that you copied to B: have been written into mikeos.flp.

    + + +
    + + + +

    Monitor

    + +

    Yutaka Saito has contributed a MikeOS program that lets you enter machine code in hexadecimal format +and execute it. Run MONITOR.BIN from the command line and you'll be presented +with a '=' prompt. Now you can enter your instructions, or just 'x' to exit back to the OS.

    + +

    MikeOS programs are loaded at the 32KiB (32768) point. The monitor converts hex code and executes +it at location 36864 in RAM -- that is, 4KiB after the where the monitor program is loaded. This is +so that your code doesn't overwrite the monitor! Consequently, any code you run should +be ORGed to 36864. For example, this is a small MikeOS program which displays the letter 'M' on +the screen. After we've assembled it, we can run ndisasm on the resulting binary +to see the hexadecimal codes:

    + +
    + +
    + + + + + + + + + + + +
    Source codeHexadecimal
    BITS 16 
    %INCLUDE "mikedev.inc" 
    ORG 36864 
      
    mov si, messageBE0790
    call os_print_stringE8FD6F
    retC3
      
    message db 'M', 04D00
    +
    + +
    + +

    (The first three lines are merely assembly directives, so they don't generate any code.) Now +that we have the hex codes, we can enter them into the monitor. Note that the code must be terminated +with a dollar sign ($) character, and spaces are allowed. So, you can enter at the '=' prompt:

    + +
    BE0790 E8FD6F C3 4D00$
    + +

    When you enter this, the monitor will convert the hex codes to machine code at location 36864 in +RAM, and call that location to execute it. (Just like normal MikeOS programs, you should finish with +a ret instruction.) After execution, you'll be returned to the monitor. You can then +enter 'r' to re-run the converted code, or 'x' to exit.

    + + +
    + + + +

    Serial port

    + +

    You can use MikeOS as a Minicom-like serial terminal emulator with TERMINAL.BIN. This lets +you connect a MikeOS machine to, for instance, a UNIX machine, and operate the UNIX machine from +MikeOS. Connect a serial (null-modem) cable between the two machines, then set up your UNIX machine +with a terminal session on the serial port.

    + +

    For instance, if you have a Linux machine, you would add a line like this to /etc/inittab:

    + +
    +T0:2345:respawn:/sbin/getty/ -L ttyS0 9600 vt100
    +
    + +

    When you restart your Linux machine, it will wait for a login on the serial port. Connect +the null-modem cable to a MikeOS machine, and run TERMINAL.BIN in MikeOS. You can now enter your +username and password to log in.

    + +

    Note that MikeOS configures the serial port to be 9600 baud, no parity, 8 data bits, 1 stop +bit. If you wish to change these settings, edit source/features/serial.asm and see the port +port setup code at the start of the file (then rebuild MikeOS as described in the System Developer Handbook). +Also note that only a handful of VT100 commands have been implemented at present, so programs which do complicated +things with the screen (such as Emacs) may not display properly.

    + +

    To exit the program, press the F8 key. (You can change this to a different key by editing +the source code near the start of programs/terminal.asm.)

    + + +
    + + +
    + + +

    Extra

    + + +

    Help

    + + +

    If you have any questions about MikeOS, or you're developing a similar OS and want +to share code and ideas, go to the MikeOS website +and join the mailing list as described.

    + + +
    + + + +

    License

    + +

    MikeOS is open source and released under a BSD-like license (see doc/LICENSE.TXT +in the MikeOS .zip file). Essentially, it means you can do anything you like with the +code, including basing your own project on it, providing you retain the license file and give credit +to the MikeOS developers for their work.

    + + +
    + + +
    + + +
    + + + + + diff --git a/source/bootload/.bootload.asm.swp b/source/bootload/.bootload.asm.swp new file mode 100755 index 0000000..1f121f0 Binary files /dev/null and b/source/bootload/.bootload.asm.swp differ diff --git a/source/bootload/.hexdump.swp b/source/bootload/.hexdump.swp new file mode 100755 index 0000000..12fb9ee Binary files /dev/null and b/source/bootload/.hexdump.swp differ diff --git a/source/bootload/.swp b/source/bootload/.swp new file mode 100755 index 0000000..fb02fca Binary files /dev/null and b/source/bootload/.swp differ diff --git a/source/bootload/bootload.asm b/source/bootload/bootload.asm new file mode 100755 index 0000000..5515932 --- /dev/null +++ b/source/bootload/bootload.asm @@ -0,0 +1,357 @@ +; ================================================================== +; The Mike Operating System bootloader +; Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT +; +; Based on a free boot loader by E Dehling. It scans the FAT12 +; floppy for KERNEL.BIN (the MikeOS kernel), loads it and executes it. +; This must grow no larger than 512 bytes (one sector), with the final +; two bytes being the boot signature (AA55h). Note that in FAT12, +; a cluster is the same as a sector: 512 bytes. +; ================================================================== + + + BITS 16 + + jmp short bootloader_start ; Jump past disk description section + nop ; Pad out before disk description + + +; ------------------------------------------------------------------ +; Disk description table, to make it a valid floppy +; Note: some of these values are hard-coded in the source! +; Values are those used by IBM for 1.44 MB, 3.5" diskette + +OEMLabel db "MIKEBOOT" ; Disk label +BytesPerSector dw 512 ; Bytes per sector +SectorsPerCluster db 1 ; Sectors per cluster +ReservedForBoot dw 1 ; Reserved sectors for boot record +NumberOfFats db 2 ; Number of copies of the FAT +RootDirEntries dw 224 ; Number of entries in root dir + ; (224 * 32 = 7168 = 14 sectors to read) +LogicalSectors dw 2880 ; Number of logical sectors +MediumByte db 0F0h ; Medium descriptor byte +SectorsPerFat dw 9 ; Sectors per FAT +SectorsPerTrack dw 18 ; Sectors per track (36/cylinder) +Sides dw 2 ; Number of sides/heads +HiddenSectors dd 0 ; Number of hidden sectors +LargeSectors dd 0 ; Number of LBA sectors +DriveNo dw 0 ; Drive No: 0 +Signature db 41 ; Drive signature: 41 for floppy +VolumeID dd 00000000h ; Volume ID: any number +VolumeLabel db "MIKEOS "; Volume Label: any 11 chars +FileSystem db "FAT12 " ; File system type: don't change! + + +; ------------------------------------------------------------------ +; Main bootloader code + +bootloader_start: + mov ax, 07C0h ; Set up 4K of stack space above buffer + add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader) + cli ; Disable interrupts while changing stack + mov ss, ax + mov sp, 4096 + sti ; Restore interrupts + + mov ax, 07C0h ; Set data segment to where we're loaded + mov ds, ax + + ; NOTE: A few early BIOSes are reported to improperly set DL + + cmp dl, 0 + je no_change + mov [bootdev], dl ; Save boot device number + mov ah, 8 ; Get drive parameters + int 13h + jc fatal_disk_error + and cx, 3Fh ; Maximum sector number + mov [SectorsPerTrack], cx ; Sector numbers start at 1 + movzx dx, dh ; Maximum head number + add dx, 1 ; Head numbers start at 0 - add 1 for total + mov [Sides], dx + +no_change: + mov eax, 0 ; Needed for some older BIOSes + + +; First, we need to load the root directory from the disk. Technical details: +; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19 +; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14 +; Start of user data = (start of root) + (number of root) = logical 33 + +floppy_ok: ; Ready to read first block of data + mov ax, 19 ; Root dir starts at logical sector 19 + call l2hts + + mov si, buffer ; Set ES:BX to point to our buffer (see end of code) + mov bx, ds + mov es, bx + mov bx, si + + mov ah, 2 ; Params for int 13h: read floppy sectors + mov al, 14 ; And read 14 of them + + pusha ; Prepare to enter loop + + +read_root_dir: + popa ; In case registers are altered by int 13h + pusha + + stc ; A few BIOSes do not set properly on error + int 13h ; Read sectors using BIOS + + jnc search_dir ; If read went OK, skip ahead + call reset_floppy ; Otherwise, reset floppy controller and try again + jnc read_root_dir ; Floppy reset OK? + + jmp reboot ; If not, fatal double error + + +search_dir: + popa + + mov ax, ds ; Root dir is now in [buffer] + mov es, ax ; Set DI to this info + mov di, buffer + + mov cx, word [RootDirEntries] ; Search all (224) entries + mov ax, 0 ; Searching at offset 0 + + +next_root_entry: + xchg cx, dx ; We use CX in the inner loop... + + mov si, kern_filename ; Start searching for kernel filename + mov cx, 11 + rep cmpsb + je found_file_to_load ; Pointer DI will be at offset 11 + + add ax, 32 ; Bump searched entries by 1 (32 bytes per entry) + + mov di, buffer ; Point to next entry + add di, ax + + xchg dx, cx ; Get the original CX back + loop next_root_entry + + mov si, file_not_found ; If kernel is not found, bail out + call print_string + jmp reboot + + +found_file_to_load: ; Fetch cluster and load FAT into RAM + mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster + mov word [cluster], ax + + mov ax, 1 ; Sector 1 = first sector of first FAT + call l2hts + + mov di, buffer ; ES:BX points to our buffer + mov bx, di + + mov ah, 2 ; int 13h params: read (FAT) sectors + mov al, 9 ; All 9 sectors of 1st FAT + + pusha ; Prepare to enter loop + + +read_fat: + popa ; In case registers are altered by int 13h + pusha + + stc + int 13h ; Read sectors using the BIOS + + jnc read_fat_ok ; If read went OK, skip ahead + call reset_floppy ; Otherwise, reset floppy controller and try again + jnc read_fat ; Floppy reset OK? + +; ****************************************************************** +fatal_disk_error: +; ****************************************************************** + mov si, disk_error ; If not, print error message and reboot + call print_string + jmp reboot ; Fatal double error + + +read_fat_ok: + popa + + mov ax, 2000h ; Segment where we'll load the kernel + mov es, ax + mov bx, 0 + + mov ah, 2 ; int 13h floppy read params + mov al, 1 + + push ax ; Save in case we (or int calls) lose it + + +; Now we must load the FAT from the disk. Here's how we find out where it starts: +; FAT cluster 0 = media descriptor = 0F0h +; FAT cluster 1 = filler cluster = 0FFh +; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user) +; = (cluster number) + 31 + +load_file_sector: + mov ax, word [cluster] ; Convert sector to logical + add ax, 31 + + call l2hts ; Make appropriate params for int 13h + + mov ax, 2000h ; Set buffer past what we've already read + mov es, ax + mov bx, word [pointer] + + pop ax ; Save in case we (or int calls) lose it + push ax + + stc + int 13h + + jnc calculate_next_cluster ; If there's no error... + + call reset_floppy ; Otherwise, reset floppy and retry + jmp load_file_sector + + + ; In the FAT, cluster values are stored in 12 bits, so we have to + ; do a bit of maths to work out whether we're dealing with a byte + ; and 4 bits of the next byte -- or the last 4 bits of one byte + ; and then the subsequent byte! + +calculate_next_cluster: + mov ax, [cluster] + mov dx, 0 + mov bx, 3 + mul bx + mov bx, 2 + div bx ; DX = [cluster] mod 2 + mov si, buffer + add si, ax ; AX = word in FAT for the 12 bit entry + mov ax, word [ds:si] + + or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd + + jz even ; If [cluster] is even, drop last 4 bits of word + ; with next cluster; if odd, drop first 4 bits + +odd: + shr ax, 4 ; Shift out first 4 bits (they belong to another entry) + jmp short next_cluster_cont + + +even: + and ax, 0FFFh ; Mask out final 4 bits + + +next_cluster_cont: + mov word [cluster], ax ; Store cluster + + cmp ax, 0FF8h ; FF8h = end of file marker in FAT12 + jae end + + add word [pointer], 512 ; Increase buffer pointer 1 sector length + jmp load_file_sector + + +end: ; We've got the file to load! + pop ax ; Clean up the stack (AX was pushed earlier) + mov dl, byte [bootdev] ; Provide kernel with boot device info + + jmp 2000h:0000h ; Jump to entry point of loaded kernel! + + +; ------------------------------------------------------------------ +; BOOTLOADER SUBROUTINES + +reboot: + mov ax, 0 + int 16h ; Wait for keystroke + mov ax, 0 + int 19h ; Reboot the system + + +print_string: ; Output string in SI to screen + pusha + + mov ah, 0Eh ; int 10h teletype function + +.repeat: + lodsb ; Get char from string + cmp al, 0 + je .done ; If char is zero, end of string + int 10h ; Otherwise, print it + jmp short .repeat + +.done: + popa + ret + + +reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error + push ax + push dx + mov ax, 0 + mov dl, byte [bootdev] + stc + int 13h + pop dx + pop ax + ret + + +l2hts: ; Calculate head, track and sector settings for int 13h + ; IN: logical sector in AX, OUT: correct registers for int 13h + push bx + push ax + + mov bx, ax ; Save logical sector + + mov dx, 0 ; First the sector + div word [SectorsPerTrack] + add dl, 01h ; Physical sectors start at 1 + mov cl, dl ; Sectors belong in CL for int 13h + mov ax, bx + + mov dx, 0 ; Now calculate the head + div word [SectorsPerTrack] + mov dx, 0 + div word [Sides] + mov dh, dl ; Head/side + mov ch, al ; Track + + pop ax + pop bx + + mov dl, byte [bootdev] ; Set correct device + + ret + + +; ------------------------------------------------------------------ +; STRINGS AND VARIABLES + + kern_filename db "KERNEL BIN" ; MikeOS kernel filename + + disk_error db "Floppy error! Press any key...", 0 + file_not_found db "KERNEL.BIN not found!", 0 + + bootdev db 0 ; Boot device number + cluster dw 0 ; Cluster of the file we want to load + pointer dw 0 ; Pointer into Buffer, for loading kernel + + +; ------------------------------------------------------------------ +; END OF BOOT SECTOR AND BUFFER START + + times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros + dw 0AA55h ; Boot signature (DO NOT CHANGE!) + + +buffer: ; Disk buffer begins (8k after this, stack starts) + + +; ================================================================== + diff --git a/source/bootload/bootload.bin b/source/bootload/bootload.bin new file mode 100755 index 0000000..68580c7 Binary files /dev/null and b/source/bootload/bootload.bin differ diff --git a/source/features/.cli.asm.swp b/source/features/.cli.asm.swp new file mode 100644 index 0000000..13e6378 Binary files /dev/null and b/source/features/.cli.asm.swp differ diff --git a/source/features/.screen.asm.swp b/source/features/.screen.asm.swp new file mode 100644 index 0000000..cf7a5dd Binary files /dev/null and b/source/features/.screen.asm.swp differ diff --git a/source/features/.strings.asm.swp b/source/features/.strings.asm.swp new file mode 100644 index 0000000..d0ebb93 Binary files /dev/null and b/source/features/.strings.asm.swp differ diff --git a/source/features/cli.asm b/source/features/cli.asm new file mode 100644 index 0000000..852bdf1 --- /dev/null +++ b/source/features/cli.asm @@ -0,0 +1,49 @@ +os_start_cli: + pusha + + mov si, prompt + call os_print_string + + mov di, user_input + + call os_display_input + + popa + ret + +; ------------------------------------------------ + +os_read_cli: + pusha + +.output_the_user_input: + call os_print_newline + + mov si, command_result_text + call os_print_string + + mov si, user_input + call os_print_string + + call os_print_newline + +.check_matches: ; Check if the user input matches any internal commands + mov si, user_input + mov di, help_string + call os_compare_strings + cmp cl, 1 + je print_help_text + +.finish: + call os_start_cli + +print_help_text: + mov si, help_text + call os_print_string_nl + + +user_input times 20 db 0 +prompt db 'CrawOS > ', 0 +help_string db 'HELP', 0 +help_text db 'This is CrawOS', 0 +command_result_text db 'You typed: ', 0 diff --git a/source/features/power.asm b/source/features/power.asm new file mode 100644 index 0000000..6860564 --- /dev/null +++ b/source/features/power.asm @@ -0,0 +1,6 @@ +os_reboot: + mov ax, 0x5307 + mov bx, 0x0001 + mov cx, 0x0003 + int 0x19 + diff --git a/source/features/screen.asm b/source/features/screen.asm new file mode 100755 index 0000000..e9c1ed6 --- /dev/null +++ b/source/features/screen.asm @@ -0,0 +1,152 @@ +; ================================================================== +; MikeOS -- The Mike Operating System kernel +; Copyright (C) 2006 - 2021 MikeOS Developers -- see doc/LICENSE.TXT +; +; SCREEN HANDLING SYSTEM CALLS +; ================================================================== + +; ------------------------------------------------------------------ +; os_print_string -- Displays text +; IN: SI = message location (zero-terminated string) +; OUT: Nothing (registers preserved) + +os_print_string: + pusha + + mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something + +.repeat: + lodsb ; Get char from si into al + cmp al, 0 ; Compare al to 0 + je .done ; If char is zero, end of string + + int 10h ; Otherwise, print it + jmp .repeat ; And move on to next char + +.done: + popa + ret + +; Exact same as the above procedure, but this adds a newline +; after priting, similar to the difference between Rust's print! and println! +os_print_string_nl: pusha + + mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something + +.repeat: + lodsb ; Get char from si into al + cmp al, 0 ; Compare al to 0 + je .done ; If char is zero, end of string + + int 10h ; Otherwise, print it + jmp .repeat ; And move on to next char + +.done: + call os_print_newline + popa + ret + +; -------------------------------------------- + +os_print_newline: + pusha + + mov ah, 03h + int 10h + + mov ah, 02h + add dh, 1 + mov dl, 0 + int 10h + + popa + ret + + +; ------------------------------------------- + +os_clear_screen: + pusha + + mov ah, 00h + mov al, 03h ; Set video mode to textmode (80x25). 16 colors, 8 pages + int 10h + + mov ah, 02h + mov dh, 0 + mov dl, 0 + int 10h + + popa + ret + +; ------------------------------------------- + +; AX = key pressed +os_read_input: + mov ah, 11h ; BIOS call to check for key + int 16h ; Interrupt + jnz .key_pressed ; Jump if input isn't 0 + + hlt + jmp os_read_input + +.key_pressed: + mov ah, 10h + int 16h + ret + +; ------------------------------------------- + +os_display_input: + pusha + + call .check_key_pressed + + jmp os_display_input + +.check_key_pressed: + call os_read_input + + cmp al, 08h + je .backspace + + cmp al, 0Dh + je .enter_key + + cmp al, 1Bh + je .esc_key + + call .print_current_input + ret + +.esc_key: + call os_reboot + +.enter_key: + mov al, 0 + stosb + mov di, user_input + + call os_read_cli + +.backspace: + mov ah, 0Eh + + mov al, 08h + int 10h + mov al, 20h + int 10h + mov al, 08h + int 10h + + dec di + jmp os_display_input + +.print_current_input: + stosb + + mov ah, 0Eh + int 10h + + ret diff --git a/source/features/strings.asm b/source/features/strings.asm new file mode 100644 index 0000000..a921896 --- /dev/null +++ b/source/features/strings.asm @@ -0,0 +1,28 @@ +; How string comparison works +; DI => scasb compares value stored in DI which is 's' with 's' stored in AX register +; and then increments DI if DF is 0 +; v +; memory address 1: |s|n|a|t|0| +; memory address 2: |s|n|a|k|e|0| +; ^ +; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0 +os_compare_strings: + pusha + +.compare: + lodsb + scasb ; Compare di to si + jne .unequal ; If they are no equal, jump to .unequal + cmp al, 0 ; Check if string is finished + je .equal ; If it has, return true + jmp .compare ; Finally, repeat + +.unequal: + mov cl, 0 ; Change to 0 if unquality is proven + popa + ret + +.equal: + mov cl, 1 + popa + ret diff --git a/source/kernel.asm b/source/kernel.asm new file mode 100755 index 0000000..c1f7b96 --- /dev/null +++ b/source/kernel.asm @@ -0,0 +1,108 @@ +; ================================================================== +; MikeOS -- The Mike Operating System kernel +; Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT +; +; This is loaded from the drive by BOOTLOAD.BIN, as KERNEL.BIN. +; First we have the system call vectors, which start at a static point +; for programs to use. Following that is the main kernel code and +; then additional system call code is included. +; ================================================================== + + + BITS 16 + CPU 386 ; pusha offsets depends on a 386 or better + ; FS and GS require a 386 or better + + %DEFINE CRAWOS_VER '0.0.2' ; OS version number + %DEFINE CRAWOS_API_VER 1 ; API version for programs to check + + + ; This is the location in RAM for kernel disk operations, 24K + ; after the point where the kernel has loaded; it's 8K in size, + ; because external programs load after it at the 32K point: + + disk_buffer equ 24576 + + +; ------------------------------------------------------------------ +; OS CALL VECTORS -- Static locations for system call vectors +; Note: these cannot be moved, or it'll break the calls! + +; The comments show exact locations of instructions in this section, +; and are used in programs/mikedev.inc so that an external program can +; use a CrawOS system call without having to know its exact position +; in the kernel source code... + +os_call_vectors: + jmp os_main ; 0000h -- Called from bootloader + jmp os_print_string ; 0003h + jmp os_read_input + jmp os_display_input + jmp os_start_cli + + +; ------------------------------------------------------------------ +; START OF MAIN KERNEL CODE + +os_main: + cli ; Clear interrupts + mov ax, 0 + mov ss, ax ; Set stack segment and pointer + mov sp, 0FFFFh + sti ; Restore interrupts + + cld ; The default direction for string operations + ; will be 'up' - incrementing address in RAM + + mov ax, 2000h ; Set all segments to match where kernel is loaded + mov ds, ax ; After this, we don't need to bother with + mov es, ax ; segments ever again, as MikeOS and its programs + mov fs, ax ; live entirely in 64K + mov gs, ax + + cmp dl, 0 + je no_change + mov [bootdev], dl ; Save boot device number + push es + mov ah, 8 ; Get drive parameters + int 13h + pop es + and cx, 3Fh ; Maximum sector number + mov [SecsPerTrack], cx ; Sector numbers start at 1 + movzx dx, dh ; Maximum head number + add dx, 1 ; Head numbers start at 0 - add 1 for total + mov [Sides], dx + +no_change: + call os_clear_screen + call os_start_cli + +bootdev db 0 +SecsPerTrack dw 18 +Sides dw 2 + +; ------------------------------------------------------------------ +; SYSTEM VARIABLES -- Settings for programs and system calls + + + ; Time and date formatting + + fmt_12_24 db 0 ; Non-zero = 24-hr format + + fmt_date db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D + ; Bit 7 = use name for months + ; If bit 7 = 0, second byte = separator character + + +; ------------------------------------------------------------------ +; FEATURES -- Code to pull into the kernel + + %INCLUDE "features/screen.asm" + %INCLUDE "features/cli.asm" + %INCLUDE "features/power.asm" + %INCLUDE "features/strings.asm" + +; ================================================================== +; END OF KERNEL +; ================================================================== + diff --git a/test-linux.sh b/test-linux.sh new file mode 100755 index 0000000..bb5be71 --- /dev/null +++ b/test-linux.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# This script starts the QEMU PC emulator, booting from the +# MikeOS floppy disk image + +qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/mikeos.flp,index=0,if=floppy