Jim Blimey

Home About Archive Games Random Games Contact

Introduction to the ZXBASIC compiler

18/05/2021

ZXBASIC (not to be confused with Sinclair BASIC) is a compiler that targets the ZX Spectrum and ZX Spectrum Next. It expands the classic Sinclair BASIC syntax with modern features to give a familiar, yet powerful programming language. In this post I am going give a little introduction to it and how it is both similar and different to Sinclair BASIC.

The main thing to remember about ZXBASIC is that it is a compiler and not an interpreted language like Sinclair BASIC. This means that even though you are writing BASIC, your code will be compiled into machine code (or Z80 assembly if you prefer) instead of being executed line by line.

Let's take a look at that classic program, you know the one, we all typed it into a display Speccy in Dixons!

10 PRINT "bum"
20 GOTO 10

Type this in on a Speccy and you know what you're getting, and if you fed this program into ZXBASIC you'd get a very similar result, however it would be running as machine code! There'll be no Scroll? Message and no pressing break to stop program execution.

So ZXBASIC can work with Sinclair BASIC code, but it doesn't need to. The first thing we can do is drop the line numbers, they are not needed!

main:
PRINT "bum"
GOTO main

We use labels instead, although for compatibility ZXBASIC treats line numbers as labels so if you're not ready to give them up just yet you can still use them and they don't even have to be in order!

20 PRINT "bum"
10 GOTO 20

Let's look at the compiler itself. It is a command line based program which you run from a command prompt or shell depending on your OS - if you're using Windows you will call zxbc.exe and for UNIX based OS you'll likely be using the Python script zxbc.py. As most people are likely to be on a Windows based system I will use that style. I will also assume that you have downloaded and extracted the zip file to C:\zxbasic.

ZXBASIC is controlled via arguments on the command line, if you executed C:\zxbasic\zxbc.exe --help you will get a nice list of all of the available options, but for the time being I shall focus on the main ones.

Before that though, let's create a simple file. You can use Windows Notepad although plenty of programmers editors are available. Enter the following code into your editor:

CLS
main:
PRINT "Hello, world!"
GOTO main

And save it as hello.bas on your Desktop.

Open up a command prompt (Win key + R and type cmd), then change directory to your Desktop:

cd Desktop

Now let's take a look at some of the available arguments:

  -T, --tzx             Sets output format to tzx (default is .bin)
  -t, --tap             Sets output format to tap (default is .bin)
  -B, --BASIC           Creates a BASIC loader which loads the rest of the CODE. Requires -T ot -t
  -a, --autorun         Sets the program to be run once loaded
  -A, --asm             Sets output format to asm
  -S ORG, --org ORG     Start of machine code. By default 32768

We'll definitely want a tap or tzx file, with a BASIC loader which will autorun (SAVE "myprog" LINE 10). We can either pass these seperately (-B -a -t) or combine them (-Bat). Finally we add our filename:

C:\zxbasic\zxbc.exe -Bat hello.bas

Type this into the command prompt and hit enter, if all is good you should get returned to the prompt without any errors and a brand new tap file should now be on your Desktop.

Load this tap file into your favourite emulator and hey presto, lots of hello worlds will appear! Once the screen is full you WONT get a Scroll? Message - remember we're dealing with machine code now! If you want to ensure the message is scrolling just edit your file like so and re-issue the command above.

CLS

main:
PRINT INK RND*7; "Hello, world!"
GOTO main

Congratulations! You've created your first ZXBASIC program!

Labels aren't just for GOTO and GOSUB, they can also reference an area in memory. Here's how to create a UDG using inline assembly (more on that in a future post) instead of RESTORE and DATA.

CLS
DIM i AS UBYTE
GOTO main

mygraphic:
ASM
  defb 16, 8, 24, 60, 66, 126, 129, 126
END ASM

main:
FOR i=0 TO 7
  POKE USR "a"+i,PEEK (@mygraphic+i)
NEXT i

PRINT CHR$ 144

We can see where the UDG is stored in memory by simply using

PRINT @mygraphic

You'll notice in the above program a rather curious DIM statement. Unlike Sinclair BASIC which stored all numeric values as a 5 byte floating point type, ZXBASIC is more strict (and with it efficient) in its numeric variables. DIM has been extended to include the type of variable as well. There are 3 different sizes of whole number types (including a signed and unsigned variant) and 2 floating point types.

DIM a AS UBYTE
DIM b AS BYTE

A byte type unsurprisingly takes up 1 byte of memory and can store values between 0 and 255 for unsigned or -128 to 127 for signed.

DIM c AS UINTEGER
DIM d AS INTEGER

An integer in ZXBASIC is a 2 byte value allowing values of 0 to 65535 or -32768 to 32767.

DIM e AS ULONG
DIM f AS LONG

Long values are 4 bytes and can store numbers between 0 and 4,294,967,295 unsigned or -2,147,483,648 to +2,147,483,647.

DIM g AS FLOAT
DIM h AS FIXED

FLOAT and FIXED are the two floating point types, FLOAT being 5 bytes and identical to Sinclair BASIC and FIXED being a more efficient, albeit less precise 4 byte variable with a range -32767.9999847 to 32767.9999847

Finally we have strings, these don't need to be defined using DIM unless you're setting up an array – and unlike Sinclair BASIC you do not have to set a length.

DIM s$(0 TO 99) AS STRING

Hold on! What's that, arrays starting at zero? I promise you it's not witchcraft! ZXBASIC, like many compilers allow you to start arrays at zero where they should be.

One thing to keep in mind is the dollar sign is optional, s$ and s are the same thing so you need be careful when naming variables, but you do have a lot more freedom in that area so shouldn't be too much of a problem.

So there you have it! Next in the series I'll be looking at wonderful things such as ELSE and WHILE.

You can grab ZXBASIC for Windows, BSD/Linux and Fisher Price here.

Share me!