I read the article and code several times and could not get how data was returned from ML to B$.
I finally realized that the program needs the variable for return value to be defined as the last variable. The program counts back from E-LINE to the beginning of the variable and fills in the data. Very clever. Then you don’t have to search all variables.
Sync Magazine v3 n5 page 86 missing
Re: Sync Magazine v3 n5 page 86 missing

Those BASIC listings are bugged... the ASM listings ... too ...
The ASM is designed to be used in a REM (@16514), but Basic listings seem to use this routine after the RAMTOP.
The problem is the "JP NZ,label" /"CALL NZ,label" , how can't be relocate up to the RAMTOP !
The author had to use relative address to use it in annother address.
the correct listing 3, in a rem is:
Code: Select all
# Listing 3.
0 REM [HEX:\
21,FA,40,3E,EA,01,FF,FF,\
ED,B1,01,05,00,A7,ED,42,\
3E,76,BE,28,05,09,22,7B,\
40,C9,09,18,E6,2A,7B,40,\
3E,76,BE,CC,85,40,7E,23,\
18,EC,2A,14,40,2B,E5,2B,\
2B,E3,E5,CD,9F,40,E1,06,\
1A,B8,28,0D,77,23,E3,34,\
20,03,23,34,2B,E3,A7,30,\
E9,E3,E1,00,C3,9D,14,2A,\
1C,40,44,4D,21,00,00,39,\
BF,ED,42,44,4D,C9,2A,0C,\
40,44,4D,16,3B,CB,22,2A,\
10,40,0A,BA,28,03,C6,80,\
02,03,BF,ED,42,20,F0,C9,\
2A,04,40,01,88,FF,09,E5,\
E5,D9,C1,D9,21,82,40,D1,\
01,78,00,ED,B0,D9,0B,D3,\
FD,C3,CB,03 ]
1 SAVE "LISTING 3"
10 LET RS=16514
20 LET RD=RS+42
30 LET FM=RS+79
40 LET IV=RS+94
50 REM COMMANDS ,( USR ) FM IV RS RD , AND GOTO Z,9998,
60 PRINT USR FM
70 RAND USR RS
75 FOR L=1 TO 4
80 LET A$=""
90 RAND USR RD
100 IF L<=3 THEN PRINT A$
105 NEXT L
110 LET Z=VAL A$
120 STOP
9998 LIST 1
9999 RAND USR IV
Last edited by XavSnap on Sun Dec 30, 2018 7:02 am, edited 1 time in total.
Xavier ...on the Facebook groupe : "Zx81 France"(fr)
Re: Sync Magazine v3 n5 page 86 missing
Seem OK...
Have fun.
Have fun.
Xavier ...on the Facebook groupe : "Zx81 France"(fr)
Re: Sync Magazine v3 n5 page 86 missing

Commented resources:
Code: Select all
#define ORG .org ; TASM cross-assembler definitions
#define equ .equ
;-----------------------------------
;------- Rom and Ram Symbols -------
EXTERR equ $005B ; Basic Break function ! Ignore line instructions.
CURSEUR equ $8F5 ; Point to PRINT AT DEST.(BC=X,Y)
CHAINE equ $B6B ; PRINT A CHAINE (BC=LEN;DE=TEXT LOC)
; **** SYSTEM VARS ****
RAMTOP equ $4004
D_FILE equ $400C
VARS equ $4010
E_LINE equ $4014
STKEND equ $401C
; **** ROM ****
NEW equ $03CB
ROM equ $149D
ORG 16514
; Restore and READ String Routines.
RESTORE: ; BASIC USR RS
LD HL,16634 ; Start @16634 to avoid to point to the header's REM (second REM if exist)
FIND: LD A,$EA ; CODE "REM"
LD BC,$FFFF ; Byte counter, will be decremented.
CPIR ; DEC BC, CP (HL)<> reg A , INC HL
LD BC,5 ; line header length.
AND A ; reset F flags (CPIR artefact)
SBC HL,BC ; REM location - 5
LD A,118 ; N/L code.
CP (HL) ; If ind. HL value <> A (No N/L before lines arguments)
JR Z,BELOW ; Go to BELOW label else next...
ADD HL,BC ; Return to REM location
STASH: LD (16507),HL ; It's a REM LINE !
RET
BELOW: ADD HL,BC ; It's a REM line, not an ASM OPPCODE.
JR FIND ; Scan to the next true REM line.
; ASM CALL subroutine
READ_CHARACTER:
LD HL,(16507) ; REM line location.
LD A,118 ; Test end of line (N/L)
CP (HL) ; If ind. HL value <> A
CALL Z,FIND ; Go to FIND label
LD A,(HL) ; Copy ind. HL value to A
INC HL ; INC REM location
JR STASH ; save the new REM location
; Basic USR RD value.
READ_STRING:
LD HL,(E_LINE) ; Read the 'vars' address artefact pointer (LET A$="")
DEC HL ; Decrement to string length...
PUSH HL ; And store it to the top of stack [SP address]
DEC HL ; Decrement HL'
DEC HL ; ''''''''''''
EX (SP),HL ; Exchange contents of HL and top of stack
; HL=HL-2
LOOP1: PUSH HL ; And store it to the top of stack [SP address]
CALL READ_CHARACTER ; READ a character in the REM line.
POP HL ; Retrieve HL in stack.
LD B,26 ; Test the next character...
CP B ; Is it a "," [chr=26] character
COMA_DONE:
JR Z,DONE ; If the string is finished, go to DONE label...
LD (HL),A ; Copy the character in the vars
INC HL ; Increment vars value
INC_LEN:
EX (SP),HL ; Retrieve the vars len (stored previously E_LINE-1)
INC (HL) ; inc its value len A$=Len A$+1
JR NZ,NO_CARRY ; Test length >FF
INC HL ; Inc the length high byte
INC (HL) ; $01;$FF
DEC HL ; Return to the low byte length byte
NO_CARRY:
EX (SP),HL ; Store the length counter to the previous location
DO_MORE: ; unused label
AND A ; reset F flags
JR NC,LOOP1 ; !!! Retrieve the 'CP B' status (is it a "," char?)
DONE: EX (SP),HL ;
POP HL ;
NOP
JP ROM ;Return to the Basic.
;FREE MEMORY Routine.
FREE_MEM:
LD HL,(STKEND) ; Get STKEND address
LD B,H ; STORE HL in BC
LD C,L
LD HL,0 ; Reset HL
ADD HL,SP ; Store SP in HL
CP A ; ??? A NOT assigned
SBC HL,BC ; Subtract HL and BC
LD B,H ; STORE HL in BC
LD C,L
RET ; Return to Basic
; INSTANT REVERSE Routine.
IV: LD HL,(D_FILE) ; Get D_FILE address
LD B,H ; STORE HL in BC
LD C,L
LD D,59 ; D register = 59
SLA D ; Shift register left arithmetic
; D = $76 and clean the F flag
LOOP2: LD HL,(VARS) ; Get VARS address value
LD A,(BC) ; Get byte from D_FILE
CP D ;
JR Z,AGAIN ; Value <> $76... next
ADD A,128 ; char+128
LD (BC),A ; Refresh D_File
AGAIN: INC BC ; Inc D_File pointer
CP A ; $76 ?
SBC HL,BC ; HL=HL-BC
JR NZ,LOOP2 ; next char.
RET ; Return to basic
; RELOCATION Routine.
RELOCATE:
LD HL,(RAMTOP) ; Get Ramtop
LD BC,-120 ; BC=$FF88
ADD HL,BC ; RAMTOP + $FF88
PUSH HL ; store c -2
PUSH HL ; store stack -1
EXX ; Exchange register pairs and alt reg pairs
POP BC ; retrieve BC in stack
EXX ; Exchange register pairs and alt reg pairs
LD HL,16514 ; REM location
POP DE ; retrieve DE in stack
LD BC,120 ; REM LEN
LDIR ; Copy REM content HL TO BC
EXX ; Exchange register pairs and alt reg pairs
DEC BC ; DEC BC
OUT (253),A ; ZX81 NMI generator
JP NEW ; Go to [RAM-CHECK]
.end

Pretty routines !
Xavier ...on the Facebook groupe : "Zx81 France"(fr)