CPU-Z80-Disassembler

 view release on metacpan or  search on metacpan

t/data/zx48_base.asm  view on Meta::CPAN

        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 (0x5C42),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,0x00               ; initialize statement counter to zero.

;; LOOK-P-2
LOOK_P_2:
        push bc                 ; save address of next line
        call EACH_STMT          ; routine EACH-STMT searches current line.
        pop bc                  ; restore address.
        ret nc                  ; return if match was found. ->

        jr LOOK_P_1             ; 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
NEXT:
        bit 1,(iy+0x37)         ; test FLAGX - handling a new variable ?
        jp nz,REPORT_2          ; 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,(0x5C4D)          ; load address of variable from DEST
        bit 7,(hl)              ; is it correct type ?
        jr z,REPORT_1           ; forward to REPORT-1 if not
                                ; 'NEXT without FOR'

        inc hl                  ; step past variable name
        ld (0x5C68),hl          ; and set MEM to point to three 5-byte values
                                ; value, limit, step.

        rst 0x28                ; ; FP-CALC     add step and re-store
        defb 0xE0               ; ;get-mem-0    v.
        defb 0xE2               ; ;get-mem-2    v,s.
        defb 0x0F               ; ;addition     v+s.
        defb 0xC0               ; ;st-mem-0     v+s.
        defb 0x02               ; ;delete       .
        defb 0x38               ; ;end-calc

        call NEXT_LOOP          ; routine NEXT-LOOP tests against limit.
        ret c                   ; return if no more iterations possible.

        ld hl,(0x5C68)          ; find start of variable contents from MEM.
        ld de,0x000F            ; 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 GO_TO_2              ; exit via GO-TO-2 to execute another loop.

; ---

;; REPORT-1
REPORT_1:
        rst 0x08                ; ERROR-1
        defb 0x00               ; 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
NEXT_LOOP:
        rst 0x28                ; ; FP-CALC
        defb 0xE1               ; ;get-mem-1        l.
        defb 0xE0               ; ;get-mem-0        l,v.
        defb 0xE2               ; ;get-mem-2        l,v,s.
        defb 0x36               ; ;less-0           l,v,(1/0) negative step ?
        defb 0x00               ; ;jump-true        l,v.(1/0)

        defb 0x02               ; ;to L1DE2, NEXT-1 if step negative

        defb 0x01               ; ;exchange         v,l.

;; NEXT-1
NEXT_1:
        defb 0x03               ; ;subtract         l-v OR v-l.
        defb 0x37               ; ;greater-0        (1/0)
        defb 0x00               ; ;jump-true        .

        defb 0x04               ; ;to L1DE9, NEXT-2 if no more iterations.

        defb 0x38               ; ;end-calc         .

        and a                   ; clear carry flag signalling another loop.
        ret                     ; return

; ---

;; NEXT-2
NEXT_2:
        defb 0x38               ; ;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
READ_3:
        rst 0x20                ; NEXT-CHAR

; -> Entry point.
;; READ
READ:
        call CLASS_01           ; routine CLASS-01 checks variable.
        call SYNTAX_Z           ; routine SYNTAX-Z
        jr z,READ_2             ; forward to READ-2 if checking syntax


        rst 0x18                ; GET-CHAR
        ld (0x5C5F),hl          ; save character position in X_PTR.
        ld hl,(0x5C57)          ; 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 0x2C                 ; is it a comma ?
        jr z,READ_1             ; forward to READ-1 if so.

; else all data in this statement has been read so look for next DATA token

        ld e,0xE4               ; token 'DATA'
        call LOOK_PROG          ; routine LOOK-PROG
        jr nc,READ_1            ; forward to READ-1 if DATA found

; else report the error.

;; REPORT-E
REPORT_E:
        rst 0x08                ; ERROR-1
        defb 0x0D               ; Error Report: Out of DATA

t/data/zx48_base.asm  view on Meta::CPAN

; This is a unary operation, so on entry HL points to the last value and DE 
; points to STKEND.

;; st-mem-xx
st_mem_xx:
        push hl                 ; save the result pointer.
        ex de,hl                ; transfer to DE.
        ld hl,(0x5C68)          ; fetch MEM the base of memory area.
        call LOC_MEM            ; routine LOC-MEM sets HL to the destination.
        ex de,hl                ; swap - HL is start, DE is destination.
        call MOVE_FP            ; 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
exchange:
        ld b,0x05               ; there are five bytes to be swapped

; start of loop.

;; SWAP-BYTE
SWAP_BYTE:
        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 SWAP_BYTE          ; 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
series_xx:
        ld b,a                  ; parameter $00 - $1F to B counter
        call GEN_ENT_1          ; 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 0x31               ; ;duplicate       x,x
        defb 0x0F               ; ;addition        x+x
        defb 0xC0               ; ;st-mem-0        x+x
        defb 0x02               ; ;delete          .
        defb 0xA0               ; ;stk-zero        0
        defb 0xC2               ; ;st-mem-2        0

; a loop is now entered to perform the algebraic calculation for each of
; the numbers in the series

;; G-LOOP
G_LOOP:
        defb 0x31               ; ;duplicate       v,v.
        defb 0xE0               ; ;get-mem-0       v,v,x+2
        defb 0x04               ; ;multiply        v,v*x+2
        defb 0xE2               ; ;get-mem-2       v,v*x+2,v
        defb 0xC1               ; ;st-mem-1
        defb 0x03               ; ;subtract
        defb 0x38               ; ;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 stk_data           ; routine STK-DATA is called directly to
                                ; push a value and advance H'L'.
        call GEN_ENT_2          ; 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 0x0F               ; ;addition
        defb 0x01               ; ;exchange
        defb 0xC2               ; ;st-mem-2
        defb 0x02               ; ;delete

        defb 0x35               ; ;dec-jr-nz
        defb 0xEE               ; ;back to L3453, G-LOOP

; when the counted loop is complete the final subtraction yields the result



( run in 0.428 second using v1.01-cache-2.11-cpan-71847e10f99 )