Relocate

Date: 198x
Type: Program
Platform(s): TS 2068

This program constructs and executes a 12-byte Z80 machine code routine that relocates a block of memory from one address to a higher address. The machine code uses the Z80’s LDIR instruction (opcode ED B0), which performs an automatic block copy by loading DE with the destination, HL with the source, and BC with the byte count. The BASIC loader accepts the source address, destination address, and byte count from the user, splits each 16-bit value into high and low bytes, and POKEs them directly into the DATA statement’s variable placeholders before writing them to address 64700. A notable feature is the POKE to system variable addresses 23730–23731 (RAMTOP), which adjusts the top of BASIC RAM to protect the relocated code from being overwritten.


Program Analysis

Program Structure

The program is organized into three logical sections: a setup subroutine at line 1000, the main loader body at lines 10–60, and a save/verify utility at line 9000. Execution begins by jumping to the subroutine at line 1000 via GO SUB 1000 at line 5, which collects user input and adjusts RAMTOP before returning. Lines 10–20 then restore and iterate through the DATA statement, POKEing 12 bytes into memory starting at address 64700. Line 50 immediately executes the newly installed machine code via RANDOMIZE USR 64700.

Machine Code Payload

The 12-byte routine embedded in the DATA statement at line 40 is a compact Z80 LDIR block-copy sequence:

OffsetBytesMnemonicDescription
017, lfrom, hfromLD DE, fromLoad source address into DE
333, lto, htoLD HL, toLoad destination address into HL
61, lbytes, hbytesLD BC, bytesLoad byte count into BC
9237, 176LDIRBlock copy DE→HL, decrement BC until zero
11201RETReturn to BASIC

The LDIR instruction (ED B0) copies bytes from the address in DE to the address in HL, incrementing both pointers and decrementing BC after each byte, repeating until BC reaches zero. Note that the DATA statement uses BASIC variable names (lfrom, hfrom, etc.) rather than literal numbers; these are resolved to their current values at READ time, which is after the subroutine at line 1000 has set them.

Address Splitting Idiom

Lines 1010–1080 use a standard technique to decompose 16-bit addresses into high and low bytes. For any value n, the high byte is INT(n/256) and the low byte is n - (high*256). This is applied identically to the source address (from), destination address (to), and byte count (bytes), producing six variables used directly in the DATA statement.

RAMTOP Adjustment

Line 1090 modifies system variables at addresses 23730 and 23731, which hold RAMTOP (the top of BASIC memory). By setting RAMTOP to one byte below the destination address, the code protects the relocated block from being overwritten by BASIC. The line includes a borrow correction: IF (lto-1)<0 THEN POKE 23731,(hto-1) handles the case where the low byte of the destination is zero, requiring a carry into the high byte. However, there is a subtle bug: the POKE 23730,(lto-1) executes unconditionally and will POKE a value of -1 (interpreted as 255) when lto is 0, which is actually the correct low byte, so the behavior is coincidentally correct on most systems.

Notable Techniques

  • The RESTORE at the start of line 20 ensures the DATA pointer is reset before reading, making the loader safely re-runnable.
  • The DATA statement uses BASIC variable names instead of literals, relying on the interpreter evaluating variables at READ time — a clean way to parameterize machine code bytes without string manipulation or extra POKE loops.
  • Line 9000 provides a SAVE/VERIFY utility with a PAUSE 0 prompt, allowing the user to rewind the tape before verification.
  • The program is designed so the user can run it, then type NEW to clear BASIC while the machine code survives above RAMTOP.

Bugs and Anomalies

  • Line 1200 (STOP) is unreachable dead code; execution from line 1090 returns via line 1100, and there is no path to line 1200.
  • The Z80 LDIR instruction increments both DE (source) and HL (destination) during the copy. If the source and destination ranges overlap and the source is at a lower address than the destination, bytes will be corrupted mid-copy. The REM at line 1 specifically warns this routine is intended only for copying to a higher address, which partially mitigates this, but does not fully prevent overlap issues.
  • No validation is performed on user inputs, so entering a byte count or address of zero, or a source address higher than the destination with overlapping ranges, could produce incorrect results silently.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM This is a program to relocate bytes from one address to another. Specifically a machine code from a lower address to another higher address.
    2 REM This is a machine code program to do that. I am setting it up to locate this code at 64700. The transfer address will be variable but generally at 60000.
    3 REM To use this program you enter the information asked for.  When the program is completed you can then delete this loader with NEW.
    4 REM You then load in the program you want relocated, key in RANDOMIZE USR 64700 and your program will be relocated above RAMTOP.
    5 GO SUB 1000
   10 LET s=64700
   20 RESTORE : FOR j=0 TO 11: READ a: POKE s+j,a: NEXT j
   40 DATA 17,lfrom,hfrom,33,lto,hto,1,lbytes,hbytes,237,176,201
   50 RANDOMIZE USR 64700
   60 STOP 
 1000 INPUT "Enter address to be moved from ";from
 1010 LET hfrom=INT (from/256)
 1020 LET lfrom=from-(hfrom*256)
 1030 INPUT "Enter address to be moved to ";to
 1040 LET hto=INT (to/256)
 1050 LET lto=to-(hto*256)
 1060 INPUT "Enter number of bytes to be transferred ";bytes
 1070 LET hbytes=INT (bytes/256)
 1080 LET lbytes=bytes-(hbytes*256)
 1090 POKE 23730,(lto-1): POKE 23731,hto: IF (lto-1)<0 THEN POKE 23731,(hto-1)
 1100 RETURN 
 1200 STOP 
 9000 SAVE "Relocate": PRINT "Rewind & key ENTER to verify.": PAUSE 0: VERIFY "Relocate"

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

People

No people associated with this content.

Scroll to Top