Sorting Algorythms

Developer(s): Alvin Albrecht
Date: 1988
Type: Program
Platform(s): TS 2068

This program implements three sorting algorithms — Bubble Sort, Insertion Sort, and Shell Sort — as machine code routines embedded directly in the BASIC listing’s REM statements. The machine code begins at address 26715, with the three sort entry points at 26721, 26759, and 26800 respectively. Each routine operates on a linear array of fixed-length elements stored in memory, treating the first byte of each element as the most significant byte. The variables Length (element width in bytes), Start (address of the first element), and Size (number of elements) are stored as 16-bit words at addresses 26715, 26717, and 26719. The routines are called via RANDOMIZE USR and are noted as non-relocatable, with a Zeus Assembler source file distributed separately on tape.


Program Structure

The program is almost entirely contained within REM statements. Lines 1 through 8 carry all the executable content — machine code in line 1, documentation in lines 2–8 — while line 10 is the only active BASIC line, executing CLS followed by LIST 3 to display the title screen REM on startup.

LinePurpose
1Machine code payload (249 bytes) stored in REM
2REM noting the 249-byte count
3REM title screen / credits block
4REM documentation: base address and entry points, variable layout
6REM documentation: number storage format (MSB-first bytes)
7REM documentation: worked example of memory layout
8REM documentation: usage instructions and relocation warning
10Active BASIC: CLS : LIST 3

Machine Code in REM

Storing machine code in a REM statement is a standard technique for embedding Z80 routines in a BASIC program without using POKE loops or a separate binary. The REM body is part of the program file and loads at a fixed address, making the routine available immediately. The author explicitly warns that the code is not relocatable — the three entry points (Bubble Sort at 26721, Insertion at 26759, Shell Sort at 26800) are hardcoded, and the base variables at 26715–26720 must sit at exactly those addresses for the routines to function correctly.

Memory Layout of Variables and Data

Three 16-bit control words are stored at the very start of the REM block (offset 6 from the line start, i.e., address 26715 in RAM):

  • Length (26715/26716) — byte width of each element (LSB/MSB)
  • Start (26717/26718) — address of the first element in the array
  • Size (26719/26720) — number of elements to sort

Elements are stored as contiguous fixed-length byte strings with the most significant byte first, allowing the comparison logic in the sort routines to work with a simple byte-by-byte lexicographic comparison from MSB to LSB — a natural fit for Z80’s sequential memory access.

Sorting Algorithms Provided

  1. Bubble Sort (entry 26721) — O(n²) worst case; simplest implementation
  2. Insertion Sort (entry 26759) — O(n²) worst case; efficient for nearly-sorted data
  3. Shell Sort (entry 26800) — O(n log n) to O(n^1.5) depending on gap sequence; the most performant of the three for larger arrays

Usage Pattern

The caller is expected to poke the Length, Start, and Size values into addresses 26715–26720 before invoking the desired routine with RANDOMIZE USR 26721 (or 26759 / 26800). The routines sort in-place, modifying the data directly in memory at the address given by Start.

Notable Techniques and Observations

  • The 249-byte machine code count is explicitly cross-checked in line 2, suggesting the author was careful about the REM block length and the resulting absolute addresses.
  • The Zeus Assembler source being distributed on the same tape is a useful detail: Zeus was a popular Z80 assembler of the era, and providing source allows hobbyists to relocate or modify the routines despite the non-relocatable binary.
  • Line 10 uses LIST 3 rather than PRINT statements to display the credits, elegantly reusing the REM text that is already present in the program without duplicating it as string data.
  • The absence of any POKE or LOAD machinery means this is a self-contained file: the machine code travels with the BASIC listing and is ready to use as soon as the program is loaded and run.

Bugs and Anomalies

There are no apparent bugs in the BASIC portion. The relocation limitation is a design constraint rather than a defect — it simply means the program must be loaded at the address for which it was assembled, which is the normal expectation for a non-relocatable machine code module stored in a REM statement at a fixed line number.

Image Gallery

Source Code

  1 REM \{10}\{0}@\md\{0}\{1}\{0}\{0}\{3}*_hCODE GO SUB BCIRCLE \{17}\{0}\{0}\{19}*_h+CODE GO SUB R8FOR  OR MERGE STR$ \{19} STEP PRINT hBRIGHT \{16}i\{27}STR$ \{24}CONTINUE \{1}\{0}\{0}\{3}*_h+GO SUB BCIRCLE  OR  OR MOVE \{19}*_hGO SUB R8\{10} STEP PRINT h0NEXT MERGE STR$ CODE \{24}INPUT  OR MOVE STR$  STEP \{16}i?\{24}PAPER \{17}\{1}\{0} THEN # THEN \{18}*_hCODE GO SUB R0POKE  THEN : THEN \{27}zCOS >=\{1}\{0}\{0}\{3}*_hCODE GO SUB RGO SUB B8FOR MERGE  OR  OR LLIST \{25}FOR RESTORE  STEP PRINT hBRIGHT \{16}iMOVE 8\{4}STR$ MOVE \{24}LLIST  OR LLIST CODE GO SUB RRESTORE STR$ (NEXT 8LET \{24}LLIST  OR MERGE  STEP )i OR LLIST GO SUB K[h\{26}PEEK 8\{9} \{7}\{11}\{19}#xLEN  NEXT MOVE STR$ <> OR MERGE  STEP )i*[h\{26}PRINT \{10}\{18}LET \{2}\{19}\{3}+|ASN  NEXT MOVE STR$ 7<> OR GO SUB K[h*]hRESTORE \{27}zCOS (\{6}\{9}\{27}zCOS  IF FOR LLIST STR$ MERGE GO SUB [[h\{11}xLEN (\{6}\{25}\{11}xLEN  IF RESTORE STR$ MOVE <>
  2 REM 249 X's up there
  3 REM \{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}    \{20}\{1}<><><><><><><><><><><>\{20}\{0}          \{20}\{1}> SORTING ALGORYTHMS <\{20}\{0}          \{20}\{1}>  \* Alvin Albrecht  <\{20}\{0}          \{20}\{1}>     August 1988    <\{20}\{0}          \{20}\{1}>   CALGARY, CANADA  <\{20}\{0}          \{20}\{1}<><><><><><><><><><><>\{20}\{0}      
  4 REM \{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}Base address is 26715           BUBBLE SORT  == 26721           INSERTION    == 26759           SHELL SORT   == 26800                                           VARIABLES; (LSB/MSB)            Length (of each element) = 26715Start (add. of 1st element)                              = 26717Size (# of elements)     = 26719  Elements are stored as linear words or numbers of LENGTH      (variable) length one after the other (see example below)        
  6 REM \{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}For numbers, the first byte of  each number is MSB.  EG-  A listof 5 byte numbers (LENGTH)      stored in decimal;              BYTES    12345                    (a)    07600   OR  7,600         (b)    10000   OR 10,000         (c)    00001   OR      1         (d)    00596   OR    596        
  7 REM \{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}These numbers would be stored inmemory as;  07600100000000100596with length (see 4) = five      (length of #), size = 4 (four   #'s), & start = 40000 if that   was where the 1st digit of the  string was stored.               
  8 REM \{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}\{8}After these variables are set upchoose the sorting routine you  want to use by calling or       RANDOMIZE USRing the address    listed above.  THIS ROUTINE IS  NOT RELOCATABLE, but a Zeus     Assembler source file follows ontape.                            
 10 CLS :LIST 3

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.