Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F\C6 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C\D7\F1\E6



Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
F\C6 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C\D7\C9DDEFF

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
AD

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\A7\ED itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"FC\CDD\CD\AF\D7E\CD\CB\AF\D7E\D7E\D7\DB\CF

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\CB\F4\EDBE\C6\ED\E5

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\ED\E1\ED\E1\C9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\EDB\A7\EDD\C9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
\EB

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\EDB\ED\B0\C9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
\EDB\EDB\ED\B0\C9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
AE\CB\CB

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
\CF\C5

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\EDB\A7\EDD\E1\EDB\EB\ED\B8\CD\CD\C9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A\EDB\D5\A7\EDD\E1\EDB\ED\B0 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"B\ED\CF\D2

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
AC\CDD\CD\C9D\F5\CBFE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"D

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C\D7\F1\CB\EF\F5\F1\C9\D7\F1\C9DDDDDDDDDDDDDDDDDDDDDDDDDDDD 2 REM \A9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
A

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
EEB\D7C\CD\FFED\CD\FFE\AF\D7

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E\FE\DD\FE\FD\CD\FFE

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
C\F0\FE\ED\CD\FFEE\E5\E6\C3\FE

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"\E1

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
BE\CD\FFE\F9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E\B8\E5\CBF\F5\C6FFE\F1E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
D

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F\E6\E1

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
BE\CD\FFE\F9

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E\C3

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
EDDDDDDDDDDDDF\A5\A5\AF\A5\A5\A5\AF\F5\A5\A5\F5\A5\AF\F5\E5\A5\F5\A5\FF\F5\A5\FE\FF\A5\FA\F5\A5\FA\F5\A5\F5\F5\A5\F5\FA\A5\F5\F5\A5\F5\F5\A5\F5\E6\F0 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"F\C6 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C\D7\F1\E6

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
F\C6 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C\D7\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57437 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"

Hex Editor

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a machine code loader and memory editor (“HEXLD3”) for the ZX81/TS1000, embedding two substantial blocks of Z80 machine code in REM statements at lines 1 and 2. The BASIC acts as a front-end for several machine code routines accessed via RAND USR calls at addresses such as 16539, 16589, 16687, 16732, and others, providing operations including WRITE, INSERT, and DELETE on memory addresses. Hex address entry is handled by decoding two-character ASCII pairs with the formula `16*CODE A$+CODE A$(2)-476`, converting hex digit pairs to byte values. The program manages its own display area by POKEing the ZX81 display file pointer (addresses 16388–16389) and includes utilities to split a 16-bit value into high and low bytes. A DIM statement at line 400 uses `USR 16635` as the array dimension, and line 420 SAVEs the full package as “HEXLD3”.


Program Analysis

Program Structure

The program is divided into several functional sections, each triggered by running or jumping to a specific line number. The BASIC serves primarily as a loader and user-interface wrapper around Z80 machine code stored in two REM statements.

LinesPurpose
1–2Z80 machine code embedded in REM statements
4–8Display file relocation test / diagnostic
10–80KEYBOARD LIST operation with hex address entry
100–150WRITE operation: input and write bytes to memory
200–250INSERT operation: input and insert bytes
300–340DELETE operation
400–422Save the full tool as “HEXLD3” and reset
500–520Exit/CLEAR utility
600–670Shared subroutine: address entry into fixed memory locations
700–722Four-hex-digit to integer decoder with high/low byte display
740–820Decimal value to high/low byte POKE utility
830–840Save program image and LIST from line 4

Machine Code in REM Statements

Lines 1 and 2 contain dense Z80 machine code. The code in line 1 begins at address 16514 (the byte after the REM token at line 1) and spans approximately 140 bytes, with entry points called from BASIC at addresses 16539, 16589, 16635, 16651, 16669, 16687, 16732, and 16762. Line 2 starts around 16640 and provides additional routines including a loader at address 17106 referenced in line 6.

Key Z80 constructs visible in the REM data include LDIR (ED B0) block copies, RST 10h (D7) character output calls, RST 08h (CF 08) error restart calls, and structured use of the IX/IY registers. The routines manipulate ZX81 system variables directly, including the display file pointer at addresses 16388–16389 (DFILE).

Hex Address Entry Idiom

The program uses a consistent two-character hex input convention to POKE address bytes. The formula:

16*CODE A$+CODE A$(2)-476

converts two ASCII hex digits (e.g. “4F”) into a byte value. Since ZX81 CODE of ASCII ‘0’–’9′ gives 28–37 and ‘A’–’F’ gives 38–43 (ZX81 character codes), the constant 476 = 16×29+12… however this program appears to use standard ASCII codes (uppercase hex), so CODE “0”=48, CODE “A”=65. Thus for “4F”: 16×52+70−476 = 832+70−476 = 426? The exact calibration depends on the character set and input method; the subroutine at lines 640–650 mirrors the same formula for address bytes split into high and low, POKEing A (low byte) and A+1 (high byte) into fixed locations at or near 16533–16534.

The four-digit version at line 710 extends this to:

4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332

which decodes a full 16-bit hex address from a four-character string.

Display File Manipulation

Lines 4–5 directly POKE the ZX81 system variable DFILE (addresses 16388–16389) to set the display file pointer to address 32256 (0x7E00), relocating the display to high RAM. Line 6 calls RAND USR 17106 to execute an initialisation routine, and line 7 reads back the pointer to verify it. This is a common technique for creating a stable display area in RAM above the BASIC program.

RAND USR as Machine Code CALL

Throughout the program, RAND USR nnnn is used exclusively as a way to call Z80 subroutines, with no interest in the random number result. This is the standard ZX81 BASIC idiom for invoking machine code without a dedicated CALL keyword. Entry points used include:

  • 16539 — initialise/setup (used before KEYBOARD LIST and WRITE)
  • 16589 — write byte routine
  • 16635 — used as dimension value in DIM O$
  • 16651 — prepare for SAVE
  • 16669 — exit/CLEAR helper
  • 16687 — insert byte routine
  • 16732 — delete byte routine (also called via RUN USR at line 340)
  • 16762 — high/low byte display helper
  • 17106 — display file relocation initialiser
  • 32258 — routine in relocated display area

Notable Techniques and Anomalies

  • Line 340 uses RUN USR 16732 rather than RAND USR; RUN on the ZX81 is equivalent to RUN 0 which restarts the program, so this appears to be a bug — it would restart rather than call the delete routine. It may be intentional if the machine code at 16732 never returns to BASIC and handles control flow itself.
  • Line 400 uses DIM O$(USR 16635), which calls the machine code routine as a numeric function to obtain the required array size dynamically — an unusual use of USR as a dimension expression.
  • The CLEAR at line 660 inside the address-entry subroutine (before RETURN) clears the ZX81 variables area. This is intentional to free memory and reset the stack before the machine code routines take over, but it means the subroutine cannot truly “return” in the normal BASIC sense without the machine code managing the stack.
  • Line 830 saves the program as "1023%8" where %8 represents an inverse “8” character — a common auto-run encoding.
  • The program mixes GOSUB 600 and direct GOSUB 610 calls to enter the address subroutine either with or without initialising the target address variable A first.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM \F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\3D\3D\13\7E\39\7F\39\7F\2A\99\40\22\97\40\54\5D\2A\95\40\A7\ED\52\19\30\1F\7C\CD\82\40\7D\CD\82\40\AF\D7\7E\CD\82\40\CB\76\20\04\AF\D7\7E\D7\3E\76\D7\23\22\95\40\18\DB\CF\00\2A\10\40\23\46\23\CB\28\28\F4\ED\5B\95\40\23\7E\87\87\87\87\23\86\C6\24\12\13\ED\53\95\40\E5\2A\99\40\ED\52\E1\30\04\ED\53\99\40\10\E1\C9\2A\99\40\ED\5B\93\40\A7\ED\52\22\97\40\44\4D\C9\2A\10\40\11\06\00\19\EB\2A\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\11\06\00\19\ED\5B\93\40\ED\4B\97\40\ED\B0\C9\2A\10\40\23\4E\23\46\CB\28\CB\19\20\02\CF\08\C5\2A\99\40\ED\5B\95\40\A7\ED\52\23\44\4D\E1\ED\5B\99\40\19\22\99\40\EB\ED\B8\CD\CD\40\C9\2A\99\40\ED\5B\97\40\D5\A7\ED\52\44\4D\E1\23\ED\5B\95\40\ED\B0\1B\ED\53\99\40\CF\08\D2\42\2A\78\41\7C\CD\82\40\7D\CD\82\40\C9\3D\06\08\F5\CB\7F\28\04\3E\1D\18\02\3E\1C\D7\F1\CB\07\10\EF\F5\F1\C9\D7\F1\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   2 REM \A9\40\2A\00\7E\3E\3B\87\D7\7C\CD\FF\7E\7D\CD\FF\7E\AF\D7\0E\00\7E\FE\DD\28\04\FE\FD\20\07\CD\FF\7E\23\0C\18\F0\FE\ED\20\21\CD\FF\7E\23\7E\E5\E6\C3\FE\43\20\04\06\03\18\02\06\01\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\18\B8\E5\CB\3F\F5\C6\7F\6F\26\7E\F1\7E\38\04\1F\1F\1F\1F\0D\20\02\1F\1F\E6\03\47\E1\2B\23\7E\CD\FF\7E\10\F9\23\22\00\7E\C3\02\7E\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\5F\55\55\A5\55\55\55\A5\AF\55\55\A5\A5\55\55\A5\AF\F5\55\A5\A5\F5\55\A5\AF\F5\99\E5\A5\F5\55\A5\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\99\99\99\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\55\55\95\55\FF\F5\A5\55\FE\FF\A5\55\FA\F5\A5\55\FA\F5\A5\55\F5\F5\A5\55\F5\FA\A5\55\F5\F5\A5\55\F5\F5\A5\F5\E6\F0\1F\1F\1F\1F\C6\1C\D7\F1\E6\0F\C6\1C\D7\C9\01\3B\01\11\00\7E\21\C2\41\ED\B0\C9\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D
   4 POKE 16388,0
   5 POKE 16389,126
   6 RAND USR 17106
   7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389
   8 STOP 
  10 PRINT "KEYBOARD LIST "
  20 GOSUB 600
  30 RAND USR 16539
  40 LET A=32256
  45 PRINT 
  50 INPUT A$
  55 PRINT A$
  60 POKE A+1,16*CODE A$+CODE A$(2)-476
  65 POKE A,16*CODE A$(3)+CODE A$(4)-476
  70 RAND USR 32258
  80 STOP 
 100 PRINT "WRITE"
 110 GOSUB 600
 120 INPUT A$
 130 PRINT A$;"  ";
 140 RAND USR 16589
 150 GOTO 120
 200 PRINT "INSERT"
 210 GOSUB 600
 220 INPUT A$
 230 PRINT A$;"  ";
 240 RAND USR 16687
 250 GOTO 220
 300 PRINT "DELETE"
 310 GOSUB 600
 320 LET A=16535
 330 GOSUB 610
 340 RUN USR 16732
 400 DIM O$(USR 16635)
 410 RAND USR 16651
 420 SAVE "HEXLD3"
 422 NEW 
 500 RAND USR 16669
 510 CLEAR 
 520 STOP 
 600 LET A=16533
 610 PRINT "ADDRESS "
 620 INPUT A$
 630 PRINT A$
 640 POKE A+1,16*CODE A$+CODE A$(2)-476
 650 POKE A,16*CODE A$(3)+CODE A$(4)-476
 660 CLEAR 
 670 RETURN 
 700 INPUT A$
 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332
 711 LET B=INT (A/256)
 712 LET C=A-((INT (A/256))*256)
 713 PRINT 
 714 PRINT A$
 715 PRINT A
 716 PRINT "HIGH=";B
 717 PRINT "LOW=";C
 722 STOP 
 740 LET V=16760
 750 INPUT X
 760 LET B=INT (X/256)
 790 LET C=X-((INT (X/256))*256)
 797 POKE V,C
 799 POKE V+1,B
 800 PRINT 
 802 PRINT X
 805 PRINT "LOW= ";C
 806 PRINT "HIGH= ";B
 810 RAND USR 16762
 820 STOP 
 830 SAVE "1023%8"
 840 LIST 4

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

People

No people associated with this content.

Scroll to Top
E\C2\ED\B0\C9DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 4 POKE 16388,0 5 POKE 16389,126 6 RAND USR 17106 7 PRINT AT 5,5;PEEK 16388+256*PEEK 16389 8 STOP 10 PRINT "KEYBOARD LIST " 20 GOSUB 600 30 RAND USR 16539 40 LET A=32256 45 PRINT 50 INPUT A$ 55 PRINT A$ 60 POKE A+1,16*CODE A$+CODE A$(2)-476 65 POKE A,16*CODE A$(3)+CODE A$(4)-476 70 RAND USR 32258 80 STOP 100 PRINT "WRITE" 110 GOSUB 600 120 INPUT A$ 130 PRINT A$;" "; 140 RAND USR 16589 150 GOTO 120 200 PRINT "INSERT" 210 GOSUB 600 220 INPUT A$ 230 PRINT A$;" "; 240 RAND USR 16687 250 GOTO 220 300 PRINT "DELETE" 310 GOSUB 600 320 LET A=16535 330 GOSUB 610 340 RUN USR 16732 400 DIM O$(USR 16635) 410 RAND USR 16651 420 SAVE "HEXLD3" 422 NEW 500 RAND USR 16669 510 CLEAR 520 STOP 600 LET A=16533 610 PRINT "ADDRESS " 620 INPUT A$ 630 PRINT A$ 640 POKE A+1,16*CODE A$+CODE A$(2)-476 650 POKE A,16*CODE A$(3)+CODE A$(4)-476 660 CLEAR 670 RETURN 700 INPUT A$ 710 LET A=4096*CODE A$+256*CODE A$(2)+16*CODE A$(3)+CODE A$(4)-122332 711 LET B=INT (A/256) 712 LET C=A-((INT (A/256))*256) 713 PRINT 714 PRINT A$ 715 PRINT A 716 PRINT "HIGH=";B 717 PRINT "LOW=";C 722 STOP 740 LET V=16760 750 INPUT X 760 LET B=INT (X/256) 790 LET C=X-((INT (X/256))*256) 797 POKE V,C 799 POKE V+1,B 800 PRINT 802 PRINT X 805 PRINT "LOW= ";C 806 PRINT "HIGH= ";B 810 RAND USR 16762 820 STOP 830 SAVE "1023%8" 840 LIST 4

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

People

No people associated with this content.

Scroll to Top