[back to main site]
Snowdrop OS - a homebrew operating system from scratch, in assembly language

Here is a summarized guide for the Snowdrop OS BASIC interpreter. Like all other Snowdrop OS applications, I wrote it in assembly language.
This BASIC interpreter opens the door to simple software development from within Snowdrop OS.

There are a few ways to run BASIC programs:

1. Directly from the text editor
2. Invoking the BASICRUN application from the command line
3. Creating a standalone application from a source file, using the BASICLNK linker

A few demo BASIC programs (extension .BAS) are included with Snowdrop OS. Instructions end with either semicolons or new lines. Thus, semicolons allow for multiple instructions on a single line.

I've designed Snowdrop OS BASIC mostly starting from Sinclair BASIC, a dialect for an 80s British 8bit computer called ZX Spectrum.


Labels are placed before instructions, "marking" places in the program, to be referenced by GOTO, CALL, etc.
Example (the label is myLoop):

myLoop: PRINT "Hello"; GOTO myLoop;


BASIC integers range from -32,768 and 32,767.


String literals use double quote delimiters, for example: "Hello, world!"


Expressions support a maximum of one operator or function. They can take the forms:

[value] [operator] [value]
[operator] [value]
[function] [value]
[function] [value], [value]
[function] [value], [value], [value]

where [value] can be literal ("one", "two", 0, 1337), or a variable.

Arithmetic and logic operators

+ integer addition and concatenation between a string and a second value
- integer subtraction
* integer multiplication
/ integer division quotient
% integer division modulo
= logical equality
> numerical greater than
< numerical less than
<= numerical less than or equal to
>= numerical greater than or equal to
<> numerical different than
AND logical
OR logical
XOR logical
NOT logical
BITAND bitwise AND
BITOR bitwise OR
BITXOR bitwise XOR
[x] BITSHIFTL [y] bitwise shift left [x] by [y] places
[x] BITSHIFTR [y] bitwise shift right [x] by [y] places
[x] BITROTATEL [y] bitwise rotate left [x] by [y] places
[x] BITROTATER [y] bitwise rotate right [x] by [y] places


LEN [expression]
returns the length of the specified string

RND [expression]
returns a random integer between 0 and [expression]-1, inclusive

KEY [expression]
returns true when the key with the specified scan code is currently pressed

CHR [expression]
converts a numeric ASCII value to a string with the character with that ASCII

ASCII [expression]
returns the numeric ASCII value of the character in a single-character string

VAL [expression]
returns the number represented by the specified string

BIN [expression]
returns the numeric value of the binary number specified as a string

returns true when serial port data is available for reading with SERIALR

CHARAT [row expression], [column expression]
returns a string containing the character at the specified location on screen

SUBSTRING [string expression], [start expression], [length expression]
returns a substring from the specified start, with the specified length

STRINGAT [string expression], [index expression]
returns a string containing the one character in the input string at the specified index


PRINT [expression]
writes the textual representation of [expression] to screen

PRINTLN [expression]
like PRINT, but also moves to a new line after writing

moves cursor to a new line

LET [variable] = [expression]
assigns a value to a variable

GOTO [label]
moves execution to another point in the program, as specified by the label

REM "comment"
inserts comments in the program

FOR [variable] = [expression] TO [expression]
marks the beginning of a loop; each iteration increments counter by one

FOR [variable] = [expression] TO [expression] STEP [expression]
marks the beginning of a loop; each iteration adds the step value to counter

NEXT [variable]
jumps to the corresponding FOR instruction, to perform the next loop iteration

IF [expression] THEN [instruction]
executes the instruction when the expression is true (non-zero)

IF [expression] THEN [instruction1] ELSE [instruction2]
executes instruction1 when the expression is true (non-zero)
executes instruction2 when the expression is false (zero)

CALL [label]
like GOTO, but allows the code to RETURN to right after CALL

returns to right after the last CALL

INPUTS [variable]
prompts the user to enter a string from the keyboard, assigning it to the variable

INPUTN [variable]
like INPUTS, but for numbers

AT [row expression], [col expression]
moves the cursor to the specified row and column

COLOURS [font expression], [background expression]
changes the current colours as specified

PAUSE [expression]
pauses for the specified number of centiseconds (hundredths of a second)

WAITKEY [variable]
waits for the user to press a key and assigns its string value to the variable

does absolutely nothing; used to simplify IF statements

BEEP [frequency expression], [duration expression]
emits a sounds over the internal speaker, moving immediately to the next instruction
frequency number is taken from the documentation for int 89h
duration is given in centiseconds (hundredths of a second)

BEEPW [frequency expression], [duration expression]
like BEEP, but pauses program execution for the duration of the sound

stops program execution

clears screen using the current font and background colours

PARALLELW [register expression], [value expression]
writes the specified value to the specified parallel port register

SERIALW [value expression]
writes the specified value to the serial port

SERIALR [variable]
blocks until a byte is available from the serial port and reads it into the variable
if SERIALDATAAVAIL is checked before and found true, SERIALR will read and not block

Sample program

PRINT "Input a number between 1 and 150: ";
INPUTN number;
LET withinLowerBound = number >= 1;
LET withinUpperBound = number <= 150;
IF withinLowerBound AND withinUpperBound THEN GOTO valid;

IF NOT withinLowerBound THEN PRINTLN "Too low, try again";
IF NOT withinUpperBound THEN PRINTLN "Too high, try again";
GOTO readNumber;

LET square = number * number;
PRINT "Its square is " + square;