ZX Spectrum ROM Listing (1983)

This is currently in the second chance pool at Hacker News, a detailed disassembly of the Sinclair Spectrum ROM, from 1983. From the preface:

The Sinclair ZX Spectrum is a worthy successor to the ZX 81 which in turn replaced the ZX 80. The Spectrum has a 16K monitor program. This program has been developed directly from the 4K program of the ZX 80 although there are now so many new features that the differences outweigh the similarities. We have both enjoyed producing this book. We have learnt a great deal about the techniques of Z80 machine code programming and now feel that between us we have unravelled the ‘secrets of the Spectrum’.

January 1983

The listing is broken down in various sections, like keyboard routines, various I/O routines, arithmetic routines, etc. The comments are informative and detailed, which makes it easy to follow along, and this may be one of the best ROM listings, I’ve ever seen. Maybe of general interest to anyone interested in Z80 code…

Here’s the link to the PDF (“The Complete Spectrum ROM Disassembly”) : http://www.primrosebank.net/computers/zxspectrum/docs/CompleteSpectrumROMDisassemblyThe.pdf

4 Likes

Notably, Basic’s SQR (square root) routine takes up only 7 bytes. (Page 225 of the PDF)

There are a number of amusing bugs - see here and here for example. The first has a longer list but the second has more detail on the reasons.

This error can be demonstrated by the now famous statement PRINT INT -65536 which gives -1

and

In the division loop at DIV_LOOP, the 34th bit of the quotient is always set to 0, meaning that some results - such as 1/10 and 1/1000 - are not rounded up as they should be. For example:

PRINT 1/2-.5

prints ‘2.3283064E-10’ instead of ‘0’, because while ‘1/2’ is calculated correctly, ‘.5’ is evaluated as ‘5 * 1/10’, which is not calculated correctly. Specifically, ‘1/10’ is represented as 7D 4C CC CC CC (0.0999999999767) in floating point form, but if the 34th bit were included, it would be rounded up to 7D 4C CC CC CD (0.100000000006), which is more accurate.

The problem is caused by the jump at 31FF, which should be to DIV_34TH instead of DIV_START.

1 Like

Obligatory remark on any floating point error; this couldn’t have happened with balanced terniary! :slight_smile:
On a more serious note, it’s rather surprising that this isn’t about a classic one-off error, but instead about a wrong jump target. – Which we may call a comparatively “solid” error.