CPU-Z80-Disassembler
view release on metacpan or search on metacpan
t/data/zx48.asm view on Meta::CPAN
AND $C0 ; test for program end marker $80 or a
; variable
SCF ; Set Carry Flag
RET NZ ; return with carry set if at end
; of program. ->
LD B,(HL) ; high byte of line number to B
INC HL ;
LD C,(HL) ; low byte to C.
LD ($5C42),BC ; set system variable NEWPPC.
INC HL ;
LD C,(HL) ; low byte of line length to C.
INC HL ;
LD B,(HL) ; high byte to B.
PUSH HL ; save address
ADD HL,BC ; add length to position.
LD B,H ; and save result
LD C,L ; in BC.
POP HL ; restore address.
LD D,$00 ; initialize statement counter to zero.
;; LOOK-P-2
L1DA3: PUSH BC ; save address of next line
CALL L198B ; routine EACH-STMT searches current line.
POP BC ; restore address.
RET NC ; return if match was found. ->
JR L1D8B ; back to LOOK-P-1 for next line.
; -------------------
; Handle NEXT command
; -------------------
; e.g. NEXT i
; The parameter tables have already evaluated the presence of a variable
;; NEXT
L1DAB: BIT 1,(IY+$37) ; test FLAGX - handling a new variable ?
JP NZ,L1C2E ; jump back to REPORT-2 if so
; 'Variable not found'
; now test if found variable is a simple variable uninitialized by a FOR.
LD HL,($5C4D) ; load address of variable from DEST
BIT 7,(HL) ; is it correct type ?
JR Z,L1DD8 ; forward to REPORT-1 if not
; 'NEXT without FOR'
INC HL ; step past variable name
LD ($5C68),HL ; and set MEM to point to three 5-byte values
; value, limit, step.
RST 28H ;; FP-CALC add step and re-store
DEFB $E0 ;;get-mem-0 v.
DEFB $E2 ;;get-mem-2 v,s.
DEFB $0F ;;addition v+s.
DEFB $C0 ;;st-mem-0 v+s.
DEFB $02 ;;delete .
DEFB $38 ;;end-calc
CALL L1DDA ; routine NEXT-LOOP tests against limit.
RET C ; return if no more iterations possible.
LD HL,($5C68) ; find start of variable contents from MEM.
LD DE,$000F ; add 3*5 to
ADD HL,DE ; address the looping line number
LD E,(HL) ; low byte to E
INC HL ;
LD D,(HL) ; high byte to D
INC HL ; address looping statement
LD H,(HL) ; and store in H
EX DE,HL ; swap registers
JP L1E73 ; exit via GO-TO-2 to execute another loop.
; ---
;; REPORT-1
L1DD8: RST 08H ; ERROR-1
DEFB $00 ; Error Report: NEXT without FOR
; -----------------
; Perform NEXT loop
; -----------------
; This routine is called from the FOR command to test for an initial
; iteration and from the NEXT command to test for all subsequent iterations.
; the system variable MEM addresses the variable's contents which, in the
; latter case, have had the step, possibly negative, added to the value.
;; NEXT-LOOP
L1DDA: RST 28H ;; FP-CALC
DEFB $E1 ;;get-mem-1 l.
DEFB $E0 ;;get-mem-0 l,v.
DEFB $E2 ;;get-mem-2 l,v,s.
DEFB $36 ;;less-0 l,v,(1/0) negative step ?
DEFB $00 ;;jump-true l,v.(1/0)
DEFB $02 ;;to L1DE2, NEXT-1 if step negative
DEFB $01 ;;exchange v,l.
;; NEXT-1
L1DE2: DEFB $03 ;;subtract l-v OR v-l.
DEFB $37 ;;greater-0 (1/0)
DEFB $00 ;;jump-true .
DEFB $04 ;;to L1DE9, NEXT-2 if no more iterations.
DEFB $38 ;;end-calc .
AND A ; clear carry flag signalling another loop.
RET ; return
; ---
;; NEXT-2
L1DE9: DEFB $38 ;;end-calc .
SCF ; set carry flag signalling looping exhausted.
RET ; return
; -------------------
; Handle READ command
; -------------------
; e.g. READ a, b$, c$(1000 TO 3000)
; A list of comma-separated variables is assigned from a list of
; comma-separated expressions.
; As it moves along the first list, the character address CH_ADD is stored
; in X_PTR while CH_ADD is used to read the second list.
;; READ-3
L1DEC: RST 20H ; NEXT-CHAR
; -> Entry point.
;; READ
L1DED: CALL L1C1F ; routine CLASS-01 checks variable.
CALL L2530 ; routine SYNTAX-Z
JR Z,L1E1E ; forward to READ-2 if checking syntax
RST 18H ; GET-CHAR
LD ($5C5F),HL ; save character position in X_PTR.
LD HL,($5C57) ; load HL with Data Address DATADD, which is
; the start of the program or the address
; after the last expression that was read or
; the address of the line number of the
; last RESTORE command.
LD A,(HL) ; fetch character
CP $2C ; is it a comma ?
JR Z,L1E0A ; forward to READ-1 if so.
; else all data in this statement has been read so look for next DATA token
LD E,$E4 ; token 'DATA'
CALL L1D86 ; routine LOOK-PROG
JR NC,L1E0A ; forward to READ-1 if DATA found
; else report the error.
;; REPORT-E
L1E08: RST 08H ; ERROR-1
DEFB $0D ; Error Report: Out of DATA
;; READ-1
L1E0A: CALL L0077 ; routine TEMP-PTR1 advances updating CH_ADD
; with new DATADD position.
t/data/zx48.asm view on Meta::CPAN
; alter the system variable MEM to point to 160 bytes of RAM to have
; use the full range available.
; A holds the derived offset $00-$1F.
; This is a unary operation, so on entry HL points to the last value and DE
; points to STKEND.
;; st-mem-xx
L342D: PUSH HL ; save the result pointer.
EX DE,HL ; transfer to DE.
LD HL,($5C68) ; fetch MEM the base of memory area.
CALL L3406 ; routine LOC-MEM sets HL to the destination.
EX DE,HL ; swap - HL is start, DE is destination.
CALL L33C0 ; routine MOVE-FP.
; note. a short ld bc,5; ldir
; the embedded memory check is not required
; so these instructions would be faster.
EX DE,HL ; DE = STKEND
POP HL ; restore original result pointer
RET ; return.
; -------------------------
; THE 'EXCHANGE' SUBROUTINE
; -------------------------
; (offset: $01 'exchange')
; This routine swaps the last two values on the calculator stack.
; On entry, as always with binary operations,
; HL=first number, DE=second number
; On exit, HL=result, DE=stkend.
;; exchange
L343C: LD B,$05 ; there are five bytes to be swapped
; start of loop.
;; SWAP-BYTE
L343E: LD A,(DE) ; each byte of second
LD C,(HL) ; each byte of first
EX DE,HL ; swap pointers
LD (DE),A ; store each byte of first
LD (HL),C ; store each byte of second
INC HL ; advance both
INC DE ; pointers.
DJNZ L343E ; loop back to SWAP-BYTE until all 5 done.
EX DE,HL ; even up the exchanges so that DE addresses
; STKEND.
RET ; return.
; ------------------------------
; THE 'SERIES GENERATOR' ROUTINE
; ------------------------------
; (offset: $86 'series-06')
; (offset: $88 'series-08')
; (offset: $8C 'series-0C')
; The Spectrum uses Chebyshev polynomials to generate approximations for
; SIN, ATN, LN and EXP. These are named after the Russian mathematician
; Pafnuty Chebyshev, born in 1821, who did much pioneering work on numerical
; series. As far as calculators are concerned, Chebyshev polynomials have an
; advantage over other series, for example the Taylor series, as they can
; reach an approximation in just six iterations for SIN, eight for EXP and
; twelve for LN and ATN. The mechanics of the routine are interesting but
; for full treatment of how these are generated with demonstrations in
; Sinclair BASIC see "The Complete Spectrum ROM Disassembly" by Dr Ian Logan
; and Dr Frank O'Hara, published 1983 by Melbourne House.
;; series-xx
L3449: LD B,A ; parameter $00 - $1F to B counter
CALL L335E ; routine GEN-ENT-1 is called.
; A recursive call to a special entry point
; in the calculator that puts the B register
; in the system variable BREG. The return
; address is the next location and where
; the calculator will expect its first
; instruction - now pointed to by HL'.
; The previous pointer to the series of
; five-byte numbers goes on the machine stack.
; The initialization phase.
DEFB $31 ;;duplicate x,x
DEFB $0F ;;addition x+x
DEFB $C0 ;;st-mem-0 x+x
DEFB $02 ;;delete .
DEFB $A0 ;;stk-zero 0
DEFB $C2 ;;st-mem-2 0
; a loop is now entered to perform the algebraic calculation for each of
; the numbers in the series
;; G-LOOP
L3453: DEFB $31 ;;duplicate v,v.
DEFB $E0 ;;get-mem-0 v,v,x+2
DEFB $04 ;;multiply v,v*x+2
DEFB $E2 ;;get-mem-2 v,v*x+2,v
DEFB $C1 ;;st-mem-1
DEFB $03 ;;subtract
DEFB $38 ;;end-calc
; the previous pointer is fetched from the machine stack to H'L' where it
; addresses one of the numbers of the series following the series literal.
CALL L33C6 ; routine STK-DATA is called directly to
; push a value and advance H'L'.
CALL L3362 ; routine GEN-ENT-2 recursively re-enters
; the calculator without disturbing
; system variable BREG
; H'L' value goes on the machine stack and is
; then loaded as usual with the next address.
DEFB $0F ;;addition
DEFB $01 ;;exchange
DEFB $C2 ;;st-mem-2
DEFB $02 ;;delete
DEFB $35 ;;dec-jr-nz
DEFB $EE ;;back to L3453, G-LOOP
; when the counted loop is complete the final subtraction yields the result
; for example SIN X.
( run in 0.651 second using v1.01-cache-2.11-cpan-96521ef73a4 )