home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-13 | 196.6 KB | 7,754 lines |
- title * *** Z8E - Z80 Debug Monitor *** *
- subttl (C) Copyright 1984, 1985 by Richard A. Surwilo
-
- ;------------------------------------------------------------------------------
- ;
- ; Copyright (C) 1984, 1985 by Richard A. Surwilo. All rights reserved.
- ;
- ; No part of this publication may be reproduced, transmitted, transcribed,
- ; stored in a retrieval system, or translated into any language or computer
- ; language in any form or by any means, electronic, mechanical, magnetic,
- ; optical, chemical, manual or otherwise, without express prior written
- ; permission of:
- ;
- ; Richard A. Surwilo 330 Calvin Court, Wyckoff, NJ 074816
- ;
- ; Note:
- ; This program is distributed in violation of the restrictions
- ; on reproduction and transmission outlined above. It would
- ; appear that Rick Surwilo released this program to the public
- ; domain without removing the notice.
- ;
- ;------------------------------------------------------------------------------
- ;
- ; Revision history
- ;
- ; 27 Dec 88 jrs v3.5 Released 24 Jan 89. Includes a few patches by
- ; George Havach.
- ;
- ; 1. Changed operation of <cr> in some commands to make
- ; a more consistent user interface. (I won't be
- ; offended if users want it changed back - jrs.)
- ;
- ; 2. Enhancement to patch 1.5:- altered the search for
- ; "MACRO-80" sentinel in .PRN files to allow for a
- ; TITLE pseudo-op.
- ;
- ; 3. Shortened and improved the code for the 'I' command.
- ;
- ; 4. Tested and corrected the ANSIXYCP module which I have
- ; been supplying since May 1987. The code has now been
- ; incorporated into the main source file and can be
- ; activated during assembly by setting "aterm equ true".
- ;
- ; 5. Discarded the '#' command introduced in 3.3.11 as with
- ; a minor adjustment the 'L' command with no file name
- ; does the same thing.
- ;
- ; 6. If S or J was last command issued then <cr> alone
- ; repeats S or J in single-step mode. Very useful for
- ; stepping through a small section of a program.
- ;
- ; (gah) 7. Adapted a patch by George Havach to correct the display
- ; of IX and IY in disassembled instructions when upper
- ; case is set.
- ;
- ; (gah) 8. Made room for patching in 'clear screen' code at
- ; MBANNR: for more dignified start-up.
- ;
- ; (gah) 9. Replaced tilde ("~") with period (".") as a general
- ; substitute for non-displayable ASCII characters, for
- ; consistency with practically every other screen-dump
- ; utility. [Retained "hazeltine" conditional - jrs]
- ;
- ; 12 Dec 88 jrs v3.4 Made patch 3.3.1 object-configurable because some
- ; terminals, particularly those which have binary
- ; cursor addressing, must use an offset of 80h to stop
- ; the BDOS from expanding tabs and for those terminals
- ; clearing bit 7 is nasty.
- ;
- ; 5 Dec 88 eg v3.3 Included a number of fixes and features submitted by
- ; (installed by jrs) Eric Gans in January and March 88.
- ;
- ; 1. Clear bit 7 of characters sent to screen to avoid
- ; strange effects on some computers (such as Kaypro
- ; which prints graphic characters if bit 7 is on).
- ;
- ; 2. Allow 'z' command without an address to mean dis-
- ; assemble from last instruction for last-specified
- ; number of lines.
- ;
- ; 3. Allow 'g' command without an address to mean the
- ; equivalent of 'g pc' or 'g $' (i.e. continue
- ; execution from current instruction).
- ;
- ; 4. Show absolute destination addresses when dis-
- ; assembling relative jump instructions (jr and djnz).
- ;
- ; 5. Display flags along with registers when using the
- ; 's' and 'x' commands.
- ;
- ; 6. Allow easy refresh of the 'animated debug' screen
- ; after program output has disturbed it. Use 'j #'
- ; to force refresh.
- ;
- ; 7. After Z8E's internal disk I/O operations, reset
- ; DMA to 80h for the benefit of target programs.
- ;
- ; 8. Allow cancellation of commands with CAN (ctrl-X)
- ; when argument buffer is empty. For example if you
- ; have entered 'd 100' then first ^X erases the '100'
- ; and the second cancels the 'd'.
- ;
- ; 9. Implement '>' command to change user number and so
- ; allow loading of files from user areas other than
- ; that from which Z8E was initiated.
- ;
- ; 10. Implement '?' command to evaluate and display argument
- ; expressions. Accepts a register name as the first
- ; operand. (reg) allows indirect addressing so that,
- ; for example, '? (hl)' displays value at the memory
- ; location whose address is contained in HL.
- ;
- ; 11. Implement '#' command to recall and display the
- ; highest address occupied by a program.
- ;
- ; 4 Dec 88 jrs v3.2 Expand asterisks in file names when using 'i' command.
- ;
- ; 27 Nov 88 jrs v3.1 Bug fix - deleted three spurious instructions from
- ; the initialisation code which was added to support
- ; breakpoint vectors at addresses other than 38h.
- ;
- ; 16 Nov 88 jrs v3.0 Bumped version number to regain sequence with USA.
- ; Until now there were two independent streams of
- ; development. (A date prefixed by '-' denotes a
- ; version from the "USA" stream).
- ;
- ; Extended Jim Moore's idea of substituting RST 30h
- ; (RST 6) for RST 38h (RST 7). Now the breakpoint
- ; vector address can be patched without re-assembling.
- ;
- ; 11 Nov 88 jrs v1.5 Added code to distinguish between .PRN files created
- ; by Macro-80 and Z80ASM 1.3 so Z8E can load symbols
- ; from either type of .PRN file.
- ;
- ;- 30 Nov 87 eg v2.1 FCB and command tail initialisation routine supplied
- ; by Eric Gans. [Does not appear in the current source
- ; as it duplicated v1.4 but consumed more code space.]
- ;
- ; 15 May 87 jrs v1.4 Implemented "I" command to initialise the command
- ; tail at 80h and the default FCB name blocks at 5Ch
- ; and 6Ch.
- ;
- ; Renamed I(nput) command to L(oad) to make way for new
- ; I(nitialise) command. Documentation changed 13/6/87.
- ;
- ; Filtered source code to all lower case. Sometime
- ; Between 1.0 And 1.2 The Comments Had Been Modified So
- ; That Every Word Started With A Capital Letter And It
- ; Really Did Look Quite Silly.
- ;
- ; 20 Apr 87 jrs v1.3 Fixed register display in animated debug mode. Z8E
- ; now handles EX AF,AF' and EXX instructions correctly.
- ; Duplicates patch of 21 Oct 86 but was developed quite
- ; independently and coded very differently.
- ;
- ; Added equates to tailor the source to assemblers
- ; other than M80.
- ;
- ;- 21 Oct 86 fh v2.0 Fixed register display in animated debug mode. Z8E
- ; (installed by gmi) now handles EX AF,AF' and EXX instructions correctly.
- ;
- ; 08 Mar 86 jrs v1.2 (No version number change - all mods purely cosmetic)
- ; Modified org directives to bypass bug in m80
- ; Added jterm conditional for testing
- ; Added hazeltine conditional for tilde suppression
- ; Changed dates to more universal format
- ;
- ; 16 Jan 86 ijb v1.2 Cursor addressing for post '=>' in jdbg75
- ; to cover systems that have a destructive bs
- ;
- ;- 3 Dec 85 jgm v?.? Added EQUates for breakpoint address so it could be
- ; something other than 38h.
- ;
- ; 25 Sep 85 ras v1.1 Fix case bug
- ; Fix usym bug
- ; Clean up comments
- ;
- ; ras = Richard Surwilo Stamford, Connecticut
- ; ijb = ?
- ; jrs = Jon Saxton Sydney, New South Wales
- ; jgm = Jim Moore Anaheim, California
- ; eg = Eric Gans Los Angeles, California
- ; fh = Frankie Hogan
- ; gbi = Gary Inman Los Angeles, California
- ; gah = George Havach California
- ;
- ;------------------------------------------------------------------------------
-
- true equ -1
- false equ 0
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; The following EQUates should both be set to FALSE to generate a "standard"
- ; Z8E.COM for distribution. The JTERM is mine which I only put in for use
- ; while testing to save having to configure the object code for my terminal.
- ; (jrs 8 mar 86) The ATERM is for an ANSI-compatible terminal such as a
- ; VT100 in which case setting ATERM to TRUE will cause the ANSIXYCP module
- ; to be included during assembly. (jrs 28 dec 88)
-
- jterm equ false ;Should always be false for distribution
- aterm equ false ;- - - ditto - - -
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; The following equ should normally be set to 0. It is only required if
- ; you have a Hazeltine terminal which uses tilde as a command character
-
- hazeltine equ false
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Configure this source to your favourite assembler by setting one of
- ; the following equates to true. If you use an assembler not mentioned
- ; below then make up a new equate for it.
-
- M80 equ false ;Microsoft's Macro-80
- ASMB equ false ;Cromemco's Z80 assembler
- SLR equ true ;SLR's lightning-fast Z80ASM assembler
-
- ; (Note that there is no real distinction between M80 and SLR. Either
- ; assembler may be used with either EQUate set TRUE.)
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- compact equ jterm or aterm
-
- if compact
- if ASMB
- conmsg Non-standard version (not for distribution)
- else
- .printx * Non-standard version (not for distribution) *
- endif
- endif
-
- if not ASMB
- .Z80 ;so M80 users don't need /z switch
- endif
-
- if ASMB
- list nogen
- page macro ;Equivalence M80's "page" and ASMB's "form"
- form
- endm
- endif
-
- maxbp equ 16 ;Number of breakpoints configured
-
- bs equ 08h ;ASCII backspace
- tab equ 09h ; tab
- lf equ 0Ah ; line feed
- formf equ 0Ch ; form feed
- cr equ 0Dh ; carriage return
- esc equ 1Bh ; escape
- ctlx equ 'X' and 1fh ; control x - delete line
- ctlc equ 'C' and 1fh ; control c - warm boot
- eof equ 'Z' and 1fh ; control z - logical eof
- quote equ 27h ; quote
- tilde equ 7Eh ; tilde
- del equ 7Fh ; del
-
- bdos equ 5
- fcb5c equ 5Ch ;CP/M default FCB
-
- nop equ 000 ;Z80 instructions
- jp equ 0C3h
- rst38 equ 0FFh
-
- iobuf equ 80h ;Disk read buffer for symbol loading
-
- page
-
- ;******************************************************************************
- ;*
- ;* nint: Initialization - relocating loader - symbol loader
- ;*
- ;* Initialization:
- ;* - Save system I register
- ;* - Determine max symbol length before loading symbol table
- ;* permissable values are 6 and 14 which are converted to bit
- ;* masks by bumping by one
- ;* - Set CP/M DMA address to 80h
- ;* - Check first command line argument for (xx) where xx is the
- ;* number of slots in the symbol table to reserve.
- ;* - Move first file name found in command line to local memory
- ;* since it will be loaded last. At the end of initialization
- ;* (or symbol loading if required) this file name will be loaded
- ;* into the keyboard input buffer and the file will be loaded
- ;* just as if the user had entered the info as a Z8E command.
- ;* - Move all subsequent file names in the command line buffer to
- ;* local input buffer (inbf) in low memory, where they can
- ;* be found by the parse routine (prsr).
- ;*
- ;* Relocating loader:
- ;* - Move absolute memory image of Z8E to top of TPA
- ;* - Adjust all addresses in relocated monitor to reflect new
- ;* execution area. This is accomplished by repeated calls to
- ;* zlen to calculate instruction lengths.
- ;* - All addresses < the absolute value of z8eorg are considered
- ;* to be absolute values and are not modified.
- ;* - Relocate all address pointers in command and operand jump
- ;* tables.
- ;*
- ;******************************************************************************
-
- if M80 or SLR
- aseg
- endif
-
- if ASMB
- abs
- endif
-
- if ASMB
- entry case,column,init,row,rowb4?,mxycp
- entry ttyi,ttyi00,ttyo,ttyq,maxlen,bdos,xycp
- entry rstVec,coMask,mBannr
- endif
-
- ; if SLR or M80
- ; Use :: at end of label name to generate a global symbol
- ; when assembling to a .REL file (i.e. when using M80 or
- ; when using Z80ASM with the /M switch). Doing it this
- ; way lets us assemble to a .REL file with either assembler
- ; or directly to a .COM file with Z80ASM without changing
- ; the source at all.
- ; endif
-
- org 100h
-
- jp nint
-
- if ASMB
- rstVec:
- else
- rstVec::
- endif
- defb 38h ;Default (but patchable) breakpoint vector
-
- if ASMB
- coMask:
- else
- coMask::
- endif
- defb 7Fh ;Mask applied to characters before output
- ;to screen. Patch to 0FFh if your terminal
- ;needs high-order bit set on occasions.
-
- if ASMB
- mbannr:
- else
- mbannr::
- endif
- if jTerm
- defb 15h,17h
- else
- defb cr,cr,cr,cr,cr ;Patch with "clear screen" code
- endif
- defb cr,lf
- defb 'Z8E V3.5 - 24 Jan 89'
- defb cr,lf
- defb 'Copyright (c) 1984, 1985 Richard A. Surwilo'
- defb cr,lf,lf
- defb 0
-
- nint:
- ld sp,stack
- ld a,i ;Save i reg for user
- ld (ireg),a
- call init
- ld de,mbannr ;Dispense with formalities
- call print
-
- ; Patch code for a specific breakpoint routine address.
- ;
- ; Adapted from an idea by Jim Moore (3 Dec 85) but made object-patchable
- ; (jrs 15 Nov 88)
-
- ld a,(rstVec) ;Get breakpoint vector address
- ld l,a
- ld h,0
- ld (nint03+1),hl ;Patch the code
- inc hl ;HL now holds rstVec+1
- ld (nint71+1),hl ;Patch some more code
- or 0C7h ;Convert vector address into RST xx
- ld (g400+1),a ;Patch the code
- ld (g518+1),a
-
- ; Patch code for terminal output - jrs 3.4
-
- ld a,(coMask) ;Get console output character mask
- ld (ttyo00+1),a
-
- ; Do config based on max length of symbol names
-
- ld a,(maxlen) ;Check max symbol length
- inc a ;Create mask
- cp 15
- ld b,a ;B - maxlen mask - 15
- ld a,62 ;A - maxlin disassembly line length (62)
- ld c,68 ;C - column to display first byte of memory
- ; window for J command
- ld d,3 ;D - bytes per line of memory window display
- jp z,nint00 ;Z - max symbol length is 14
-
- ;If not 14 - use default values
- ld b,7 ;B - maxlen mask - 7
- ld a,30 ;A - maxlin disassembly line length (30)
- ld c,56 ;C - column to display first byte of memory
- ld d,7 ; window for J command
- nint00: ld (maxlin),a
- ld a,b
- ld (maxlen),a
- ld a,c
- ld (fwndow),a
- ld a,d
- ld (nlmask),a
-
- ;Reset CP/M DMA address for those instances in which Z8E is used to debug
- ;itself. Otherwise DMA address is left where Z8E stopped loading itself.
- ;(Last statement no longer true - see patch 3.3.1)
-
- ld de,80h
- ld c,26
- call bdos
-
- ld a,jp ;Initialize where L80 fears to tread
-
- ; The next instruction is PATCHED before it is executed
- nint03: ld (38h),a ;Init trap to breakpoint handler
-
- ld hl,5dh ;Save current contents of default fcb
- ld a,(hl)
- cp '(' ;Is first char in fcb a paren?
- dec hl
- jr nz,nint25 ;Not paren - no user symbol table requested
- inc hl ;Point back to paren
- ld de,inbf ;Start of input buffer here in low memory
- ld b,15 ;Max chars in fcb following first paren
- nint05: inc hl ;Bump fcb pointer
- ld (de),a ;Move char to low memory keyboard input buffer
- ;so that prsr thinks this is keyboard input
- inc de ;Bump input buffer pointer
- ld a,(hl)
- cp ')' ;Look for trailing paren
- jr z,nint10
- djnz nint05 ;Examine entire fcb at 5ch looking for paren
- ld hl,fcb5c ;Trailing paren not found - this must be
- ; kookie file name
- jr nint25 ;Ignore
-
- ;Call iarg to determine amount of space to allocate in user symbol table.
- ;This arg must be enclosed in parentheses and must appear after the first
- ;arg in the command line. Since opening and closing parens were found
- ;add a pound sign to make this into default decimal number then call xval
- ;to evaluate.
-
- nint10: ex de,hl ;HL - input buffer pointer
- ld (hl),'#' ;Add trailing paren before calling iarg
- ;who will evaluate argument as if it was
- ;entered from keyboard
- inc hl
- ld (hl),a ;Restore trailing paren following pound sign
- inc hl
- ld (hl),0 ;Add end of line null
- call iarg
- ex de,hl ;DE - evaluated argument
- ld hl,fcb5c
- jr nz,nint25 ;Arg error - ignore input
- ld hl,81h ;Start of command line tail
- nint15: ld a,(hl)
- ld (hl),' ' ;Replace the text which appeared between
- ;the parens and the parens themselves with
- ;spaces
-
- cp ')' ;Closing paren ends search
- jr z,nint20
- inc hl ;Point to char following closing paren
- jr nint15
- nint20: ex de,hl ;Arg to hl for mult times maxlen bytes per
- ;symbol table entry
- add hl,hl
- add hl,hl
- add hl,hl
- ld a,(maxlen) ;8 or 16 bytes per symbol table entry?
- cp 7
- jp z,nint22 ;z - must be 8
- add hl,hl
- nint22: ex de,hl
- ld (usymbl),de ;Save number of bytes to reserve
- ld hl,6ch ;since user symbol table arg was present then
- ;target file must be in default fcb number 2
-
- nint25: ld de,zbuf ;Local buffer
- ld bc,16
- ldir ;Move FCB contents to local memory
- ld hl,80h ;Command line buffer address
- ld a,(hl)
- and a ;Test for no input
- jr z,nint55 ;No input - clear symbol table
- ld c,a ;BC - number of chars in command line buffer
- ld (hl),b ;Clear byte count
- add hl,bc ;Point to last char in buffer
- inc hl
- ld (hl),b ;Set end of line null after last char
- ld hl,81h
- nint30: ld a,(hl) ;Look for start of first file name
- and a ;Found the end of line null?
- jr z,nint55 ;Z - no files to load
- cp ' ' ;Leading space?
- jr nz,nint35 ;Not space - found start of file name
- inc hl
- dec c ;Decrement command line byte count
- jr nint30 ;Keep looking for start of file name
- nint35: ld de,znmbuf ;Save name here for later display
- ld (de),a
- inc de
- nint40: inc hl ;Find first trailing space
- ld a,(hl)
- cp ' '
- jr z,nint45 ;Found space - move remainder of buffer
- ld (de),a ;Save file name character for display
- inc de
- and a ;End of line?
- jr z,nint55 ;z - only one file specified
- dec c
- jr nint40
- nint45: ld a,c ;Check byte count
- cp inbfsz ;versus size of our local input buffer
- jr c,nint50 ;carry - size is ok
- ld c,inbfsz ;Only move as much as will fit
- nint50: ld de,inbf
- ldir ;Move command line to local memory
- xor a
-
- nint55: ld hl,z8eorg ;clear local symbol table to nulls
- ld b,z8e-z8eorg ;symbol table size
- nint60: ld (hl),a ;nulls to entire local symbol table
- inc hl
- djnz nint60
- ld hl,(06) ;start of bdos
- ld l,a ;init stack address to 256 boundary
- ld bc,nmem ;monitor size
- and a
- sbc hl,bc ;hl - starting address of z8e in upper
- ;memory
- ld (z8eb),hl ;monitor bias - for relocation work
- ld de,(usymbl)
- sbc hl,de
- ld (ntpa),hl ;end of tpa - for symbol loading
- ld a,d ;check for no user symbol table
- or e
- jr z,nint75 ;no table - no clearing required
- nint70: ld (hl),0 ;fill user symbol table with nulls
- inc hl
- dec de
- ld a,d
- or e
- jr nz,nint70
- nint75: ex de,hl ;hl - start of z8e in hi memory
-
- ld hl,bphn-z8eorg ;entry point to breakpoint handler
- add hl,de
-
- ; The next instruction will be PATCHED by the time it is executed.
- nint71: ld (39h),hl ;Init RST 38h trap location
-
- ld hl,z8eorg
- ldir ;z8e now in hi memory - relocate addresses
- ld hl,(z8eb) ;recover hi memory starting address
- ld de,z8ecmd-z8eorg
- add hl,de ;first instruction to relocate
- ex de,hl
- nint80: call zlen00 ;calculate instruction length
- ld h,d
- ld l,e ;de - current instruction hl - ditto
- ld b,0
- add hl,bc
- ex de,hl ;de - next address to relocate
- ld a,c ;test length
- sub 3
- jr c,nint90 ;one or two byters are non-relocatable
- ld c,a
- add hl,bc ;bump if four byter
- ld a,(hl)
- ld hl,z80r ;table of relocatable instructions
- ld c,z80rl ;size
- cpir
- jr nz,nint90 ;nz - not relocatable
- ex de,hl
- dec hl ;point to address byte requiring bias
- ld a,(hl)
- sub z8eorg shr 8 ;test for absolute address < z8eorg
- jr c,nint85 ;absolute - no relocation needed
- ld b,a
- ld a,(z8ebh) ;hi order byte of address bias
- add a,b ;plus upper byte of operand address
- ld (hl),a ;set relocated address
- nint85: inc hl
- ex de,hl ;de - next address to test
- nint90: ld bc,nrel-z8eorg ;end of relocatable portion of monitor
- ld hl,(z8eb)
- add hl,bc ;hl - absolute end of relocated monitor
- and a
- sbc hl,de ;reached end?
- jr nc,nint80 ;nc - more
- ld de,ncmd+zopjtl ;size - command and operand jump tables
- ld hl,(z8eb) ;base of relocated monitor
- ld a,-(high z8eorg); [was: ld a,-(z8eorg/256)]
- add a,h ;relocation bias byte to add to ptrs
- ld d,a ;d - bias to add e - count of pointers
- ; requiring relocation
- add hl,bc ;first point to operand names
- ld bc,zopjtb ;add length of operand name table
- add hl,bc ;point to first entry in jump table
- nint95: inc hl
- ld a,(hl) ;hi byte jump table entry
- add a,d ;plus bias
- ld (hl),a ;replace in table
- inc hl
- dec e
- jr nz,nint95 ;nz - more table entries to relocate
-
-
- ;******************************************************************************
- ;*
- ;* ZSYM: Symbol table build from .sym and .prn files
- ;*
- ;* LFCB called to parse the input buffer (inbf) in low memory.
- ;* INBF contains the command line tail which bdos passed to us at
- ;* 80h and which we have since moved to inbf (so that prsr thinks
- ;* it's just keyboard input).
- ;*
- ;* All valid file names are opened for input.
- ;*
- ;* If the file name terminates with a comma then we assume the
- ;* user is specifying a bias which is to be added to every symbol
- ;* loaded from the file.
- ;*
- ;* zsym general file handiling
- ;* .sym load L80 .sym file or load SLR .lst file
- ;* .prn load M80 .prn file or load SLR .prn file
- ;*
- ;* Symbol table always begins on an 8 or 16 byte boundary
- ;* depending on the value in maxlen.
- ;*
- ;******************************************************************************
-
- zsym: call lfcb ;Initialize fcb
- jp nz,zstx ;nz - error
- ld de,mldg ;Display loading message
- call nprint ;Output crlf - then print
- ld de,prsbf
- call print ;Display file name
- ld a,c ;lfcb returns delimeter in c reg
- ld (delim),a ;Temp save delimiter so we know if a bias has
- ;been specified
- call crlf
- call lopn ;Try to open symbol table file
- dec a ;
- jp m,zfnf ;m - file not found
- ld a,(delim) ;Check delimeter
- cp ','
- ld hl,00
- jr nz,zsym10 ;nz - no comma means no symbol bias
- call prsr ;Let prsr extract symbol bias
- jp nz,zoff ;Parse error - use bias of 0000
- ld (delim),a ;Save delimeter which followed bias
- ld de,prsbf
- ld hl,00
- call xval ;Evaluate bias
- jr z,zsym10 ;z - numeric bias specified
-
- ;User has specified a bias in the form
- ; of a symbol name
- ld hl,(ntpa) ;Check bias specified by symbol name
- ld a,(maxlen)
- cpl
- ld e,a
- ld d,0ffh ;Lower end of TPA by amount equal to
- ; the value of maxlen negated to insert
- ; jump to bdos
- add hl,de
- ld a,(case) ;Check case of symbol table
- and a
- jp z,zsym05 ;z - symbol names are already in upper case
- ld de,prsbf ;prsr stored symbol name here
- zsym00: ld a,(de)
- and a
- jp z,zsym05 ;z - end of label symbol name
- call ilcs ;Change each char in symbol name to lower case
- ld (de),a
- inc de ;Store converted character
- jp zsym00
- zsym05: ld de,prsbf
- call fsym00 ;Search symbol table
- jp nz,zoff ;nz - not found
- ld a,(maxlen)
- or l
- ld l,a
- ld a,(hl) ;Fetch hi order address associated
- ; with symbol
- dec hl
- ld l,(hl)
- ld h,a ;HL - symbol value
- zsym10: ld (bias),hl ;Bias to add to each symbol address
- ld hl,00
- ld a,(fcbtyp)
- ld bc,(ntpa) ;Current end of TPA
- cp 'S' ;Is this a .sym file?
- jp z,.sym ;.SYM file loaded differently from .PRN
- cp 'L'
- jp nz,.prn ;If not .LST then must be .PRN
- ld de,.lst?? ;Look for .LST string id string
- ld (pstrng),de ;Store pointer to string to find
- call fstrng
-
- ;BC - symbol table pointer
-
- .sym: ld a,(maxlen) ;Lower TPA address by 16 or 8
- cpl
- and c ;for storing next symbol and address
- ld c,a
- ld a,(maxlen)
- cpl ;This is negate plus one
- add a,c
- ld c,a
- jp c,.sym00 ;Treat carry as complement of subtraction
- dec b
- .sym00:
- ex de,hl
- ld hl,stack+8 ;Check for monster symbol table ready to eat us
- and a
- sbc hl,bc
- jp nc,zmem ;End symbol load before stack is clobbered
- ex de,hl
- ld a,(maxlen) ;Load symbol length mask (7 or 15)
- dec a ;
- ld d,a ;D - actual max length of symbols (6 or 14)
- xor a
- .sym10: ld (bc),a ;Init symbol table entry to nulls
- inc bc
- dec d
- jr nz,.sym10
- ld e,d ;Clear DE for hex00
- xor a
- ld (star),a ;Clear ** found flag
- ld a,4 ;Convert four bytes of address
- ld (bytes),a
- .sym20: call nchr ;Fetch next character in file
- cp eof
- jp z,.eof ;End of this symbol file
- cp '0'
- jr nc,.sym25 ;c - must be control character or space
- ;nc - possible first char of address
- cp lf
- jp z,.sym21
- cp '*' ;** in slr .sym file?
- jp nz,.sym20
- ld (star),a
- jp .sym25
-
- .sym21:
- call nchr ;Fetch char following lf
- cp cr
- jp z,.sym22 ;z - consecutive crlf's means end of page
- cp '0'
- jp nc,.sym25 ;nc - symbol address on new line
- cp eof
- jp z,.eof
- cp '*' ;** ?
- jp nz,.sym20
- ld (star),a
- jp .sym25
-
- .sym22:
- ld a,(fcbtyp)
- cp 'L' ;z80asm .LST file?
- jp z,.sym23
- cp 'P' ;macro 80 v3.4?
- jp nz,.sym20
- .sym23:
- ld de,.lst?? ;Bypass inter-page verbiage
- ld (pstrng),de
- call fstrng
- cp eof
- jp z,.eof
-
- call nchr
- cp eof
- jp z,.eof
-
-
- .sym25: call hex00 ;Have first char of address - convert
- call totsym ;Bump total of symbols loaded
- ld a,(fcbtyp) ;Is this a .SYM file?
- cp 'S'
- call nz,nchr ;Eat addrress/symbol separator for .LST file
- ld a,(maxlen)
- dec a
- ld (bytes),a ;Init max symbol length counter
- .sym30: call nchr ;Read symbol name char
- cp tab
- jp z,.sym45
- cp cr
- jp z,.sym45
- cp ' '
- jp z,.sym45
- ld (bc),a
- ld a,(case) ;Check user requested case
- and a
- jr z,.sym35 ;z - upper case requested by user
- ld a,(bc) ;Recover char
- cp 'A'
- jr c,.sym35 ;c - must be number
- cp 'Z'+1
- jp nc,.sym35
- or 20h
- ld (bc),a ;Restore symbol name char as lower case
- .sym35: inc bc
- ld a,(bytes)
- dec a
- ld (bytes),a
- jr nz,.sym30
- .sym40: call nchr
- cp 21h
- jp nc,.sym40
- .sym45: ld a,(star) ;Check if this was ** in address field
- and a
- jp nz,.sym50
- ld a,(relchr) ;Check for external symbol
- cp ' '
- jp z,.sym ;Space means absolute
- cp quote
- jp z,.sym ;Quote means relocatable
- .sym50: ld a,(maxlen)
- or c
- ld c,a
- inc bc ;Point BC to next higher symbol block so
- ;that rewinding by maxlen bytes will actually
- ;overlay this symbol. This ensures that
- ;external symbols are not kept in table.
-
- jp .sym
-
-
- .prn: ;Don't yet know if this .prn file was
- ;generated by M80 or Z80ASM. To find out
- ;I pull a dirty trick. I force a read
- ;and look for a formfeed, up to 80 characters
- ;of program title, a HT and "MACRO-80" in the
- ;I/O buffer, then I reset the pointer so that
- ;the next character read comes from the
- ;beginning of the file. Will probably get
- ;confused by a HT in the program title.
- ; jrs 14/11/88, 22/12/88.
-
- call nchr ;Force a read. First byte of file is
- ; returned in A, pointer to next byte in HL
- cp formf ;Test character
- jr nz,.prnBB ;Exit M80 testing now if not a formfeed
- ld b,82 ;Maximum number of characters to search
- ld a,tab ;What to look for
- cpir
- jr nz,.prnBB ;If no tab then not an M80 .prn file
- ex de,hl ;Point at strings to be compared
- ld hl,.m80??
- ld b,(hl) ;Number of bytes to compare
- inc hl
- .prnAA:
- ld a,(de) ;Compare bytes
- cp (hl)
- jp nz,.prnBB ;Exit loop if different
- inc hl ; otherwise step the pointers
- inc de
- djnz .prnAA ;Loop until difference encountered or
- .prnBB: ; all bytes compared.
- ld hl,iobuf ;Reset buffer pointer
- ld bc,(ntpa)
- jp nz,.slr ;If not M80 then do Z80ASM .prn file load
-
- ; End of dirty trick code
-
- ld de,.prn??
- ld (pstrng),de
- call fstrng
- cp eof
- jp nz,.prn00
- .prnCC:
- ld de,msymnf ;display symbol table not found message
- call print
- jp .eof50 ;check for more symbol files to load
-
- .prn00:
- ld bc,(ntpa) ;bc - current end of the tpa
- dec bc ;this points us into the next lower
- ;symbol table block
- ;this is first char of symbol table
- xor a
- or l ;get next byte from file but without bumping
- ;pointer allowing us to reread same char (in
- ;case it is last character in buffer
-
- call z,read ;only do true read if last character was last
- ;in buffer
- ld a,(hl)
- cp '0'
- jp c,.pr325 ;non-numeric: macro-80 v3.44
-
- cp '9'+1
- jp c,.pr4 ;numeric: macro-80 v3.4
-
-
- ;Macro-80 v3.4 dec 1980 symbol table load
-
- .pr325: ld a,(maxlen)
- cpl
- and c ;now rewind within 8 or 16 byte block
- ;(depending on maxlen) in order to point
- ;to first byte
- ld c,a
-
- ex de,hl ;de - save file buffer pointer
- ld hl,stack + 16 ;check for encroaching symbol table
- sbc hl,bc ;versus current symbol table address
- jp nc,zmem ;nc - out of memory
- ex de,hl ;return file buffer pointer
- ld a,(maxlen)
- ld d,a
- dec d ;d - symbol name length
- xor a
- ld e,a
- .pr330: ld (bc),a ;pre-clear name portion of symbol table to
- ;nulls
- inc bc
- dec d ;now any name less than maxlen chars in length
- jp nz,.pr330 ;is terminated with a null
- ld a,(maxlen)
- cpl
- and c
- ld c,a
- .pr335: call nchr ;next char from file buffer
- cp 21h
- jp nc,.pr351 ;nc - this is first character of symbol name
- cp eof ;end of file?
- jp z,.eof
- cp lf ;line feed?
- jp nz,.pr335
- .pr340: call nchr ;get character following line feed
- cp cr
- jp z,.pr342
- cp formf ;form feed?
- jp nz,.pr351
- .pr342: ld e,3 ;symbols resume three lines hence following
- ;a form feed character - so count linefeeds
- cp cr ;did we find cr or a formf?
- jp nz,.pr345 ;nz - formf
- dec e ;just look for two lf's
- .pr345: call nchr
- cp lf
- jp nz,.pr345 ;loop til three found
- dec e
- jp nz,.pr345
-
- xor a
- or l ;get next byte from file but without bumping
- ;pointer allowing us to reread same char in
- ;case it is last character in buffer
-
- call z,read ;only do true read if last character was last
- ;in buffer
- ld a,(hl)
- cp cr ;four crlf's is eof
- jp z,.eof
-
- .pr350: call nchr ;next char from file
- cp eof
- jp z,.eof
- cp tab
- jp z,.pr355
- .pr351: ld (bc),a ;move character of symbol name
- ld a,(case) ;check user requested case
- and a
- jr z,.pr352 ;z - user wants upper case
- ld a,(bc) ;get char back from symbol table
- cp 'A'
- jr c,.pr352 ;must be numeric - no case here
- cp 'Z'+1
- jr nc,.pr352
- add a,20h
- ld (bc),a ;replace char with lower case equivalent
- .pr352: inc bc
- jp .pr350
-
- .pr355: ld a,4
- ld (bytes),a
- .pr357: call nchr
- cp ' '
- jp z,.pr357
-
- call hex00 ;now read the next four characters from the
- ;file and convert them to a hex address -
- ;store in symbol table entry
-
-
- ld a,(relchr) ;recover char which followed address
-
- cp ' ' ;this char followed address
- jr z,.pr370 ;microsoft absolute address
- cp quote ;relocatable address?
- jp nz,.pr325
- ;by not rewinding the symbol table pointer
- ;the next symbol will overlay this one.
-
- .pr370: dec bc
- call totsym
-
- jp .pr325
-
-
- ;macro-80 v3.44 symbol loading routine
-
- .pr4: ld a,(maxlen) ;lower tpa address by maxlen
- cpl
- and c ;for storing next symbol and address
- ld c,a ;bc - next address of symbol table entry
- ; on an 8 or 16 byte boundary
- ex de,hl
- ld hl,stack+8 ;check for monster symbol table
- and a
- sbc hl,bc
- jp nc,zmem ;end symbol load before stack is clobbered
- ex de,hl
- ld a,(maxlen)
- dec a ;pre-clear symbol table entry with nulls
- ld d,a
- xor a
- .pr410: ld (bc),a ;for length equal to maxlen
- inc bc
- dec d
- jr nz,.pr410
- ld e,d ;clear de for hex00
- ld a,4 ;convert four bytes of address
- ld (bytes),a
- .pr420: call nchr ;fetch next character in file
- cp eof
- jp z,.eof
- cp '0'
- jr nc,.pr425 ;nc - address digit
- cp lf
- jp nz,.pr420 ;nz - leading space or cr
-
-
- call nchr ;check character following lf
- cp cr
- jp z,.eof ;blank line is eof
-
- cp formf ;form feed?
- jp nz,.pr425 ;no - first character of next address
-
- ld e,3 ;must be form feed
- .pr421: call nchr
- cp lf ;three lf's follow form feed before symbols
- ;resume on next page
- jp nz,.pr421
- dec e
- jp nz,.pr421
-
- call nchr
- cp eof
- jp z,.eof
-
- .pr425:
- call hex00 ;have first char of address - convert
-
- call nchr ;eat address/symbol separator
-
- ld a,(maxlen)
- dec a
- ld (bytes),a ;max chars to store in symbol table
-
-
- .pr430: call nchr ;read symbol name char
- cp 21h
- jp c,.pr440 ;found separator
- ld (bc),a
- ld a,(case) ;check user requested case
- and a
- jr z,.pr435 ;c - upper case requested by user
- ld a,(bc) ;recover char
- cp 'A'
- jr c,.pr435 ;c - must be number
- cp 'Z'+1
- jr nc,.pr435
- or 20h
- ld (bc),a ;restore symbol name char as lower case
- .pr435: inc bc ;bump symbol table pointer
- ld a,(bytes) ;character counter
- dec a
- ld (bytes),a
- jp nz,.pr430 ;not max length
-
-
- .pr438: call nchr ;eat chars until next address found
- cp eof
- jp z,.eof
- cp ' ' ;found symbol/address
- jp nz,.pr438
-
-
- .pr440: ld a,(maxlen)
- cpl
- and c
- ld c,a
-
- ld a,(relchr) ;recover char which followed address
- cp ' ' ;this char followed address
- jr z,.pr450 ;microsoft absolute address
- cp quote ;relocatable address?
- jp nz,.pr4 ;nz - must be external symbol. we don't
- ;actually load them or count them in total.
- ;by not rewinding the symbol table pointer
- ;the next symbol will overlay this one.
-
- .pr450: dec bc
- call totsym
- jp .pr4
-
- ; SLR Z80ASM symbol table loading routines
-
- .slr:
- ld de,.slr?? ;If this .prn file really is a Z80ASM
- ld (pstrng),de ;product then we can use existing code
- call fstrng ;to load the symbols.
- cp eof
- jp nz,.sym
- ld de,msymnf ;display symbol table not found message
- call print
- jp .eof50 ;check for more symbol files to load
-
-
- .eof: ;We always pre-decrement the symbol table
- ;pointer in anticipation of storing the next
- ;symbol. Now that we hit the end of a symbol
- ;table we must adjust the pointer in
- ;preparation for loading the symbols from the
- ;next file (if there is one).
- ld a,(maxlen)
- ld l,a
- ld h,0
- inc l
- add hl,bc ;point to last loaded symbol
- ld b,h
- ld c,l ;bc - spare copy
- cpl
- and c
- ld c,a
- ld (ntpa),bc ;save current end of tpa address
- ld a,(nsymhi) ;hi order number of symbols loaded (bcd)
- call hexc ;convert to ascii
- ld h,a ;returned in a - move to h (other digit in l)
- ld (mhex),hl ;store in message
- ld a,(nsymlo)
- call hexc ;convert lo order
- ld h,a
- ld (mhex+2),hl
- ld de,msym.. ;display number of symbols loaded message
- ld c,9
- call bdos
- ld de,mhex ;now look thru ascii number of symbols to
- ;strip leading zeros
- ld b,3
- .eof10: ld a,(de)
- cp '0'
- jr nz,.eof20 ;nz - found first non-zero
- inc de
- djnz .eof10 ;if first three chars zero - fall thru and
- ;print the fourth regardless
- .eof20: ld c,09
- call bdos ;print the number as string ending with $
- call crlf
- ld hl,(tsym) ;now add in bcd total for this file to bcd
- ;total for all files
- ld de,(nsym) ;tsym - total for all files
- ;nsym - total for this file
- ld a,h
- add a,d
- daa
- ld h,a
- ld a,l
- adc a,e
- daa
- ld l,a
- ld (tsym),hl
- ld hl,00 ;clear out total for next file
- ld (nsym),hl
- ld hl,(z8eb)
- ld de,symflg-z8eorg
- add hl,de ;hl - pointer to symbol flag in hi memory
- xor a
- ld (hl),a ;zero - symbol table present
- ld (symflg),a ;also set flag in lo memory where we are
- ;currently so that fsym knows theres a symbol
- ;table to search thru if the user specified a
- ;symbol name bias as part of the command line
-
- .eof50: ld a,(delim) ;check command line delimter
- and a ;test for end of line null
- jp nz,zsym ;nz - not null means more files
-
-
-
-
- load: ld hl,(ntpa) ;current end of memory
- ld a,(symflg) ;check for symbol table
- and a
- jr nz,load00 ;nz - no symbol table
- ld d,a
- ld a,(maxlen)
- ld e,a ;de - length of a symbol table block
- inc e
- sbc hl,de ;compensate for pre-increment of pointer
- load00: ld de,(06) ;de - real entry point to bdos
- ld (06),hl ;point to our origin in hi memory
- ld (hl),jp ;init jump to bdos at start of z8e
- inc hl
- ld (hl),e
- inc hl
- ld (hl),d
- ld e,0 ;de - old start of bdos address in also our
- ;ending address
- ld hl,(z8eb) ;load out starting address in hi memory
- ld bc,z8e-z8eorg ;fetch the number of bytes between z8e's base
- ;address and the entry point of the command
- ;processor - internal symbol table size
-
- add hl,bc
- ld b,h
- ld c,l ;BC - relocated z8e address
- ex de,hl ;DE - entry point z8e HL - old start of bdos
- dec hl ;HL - last byte in our memory
- ld (hl),b
- dec hl
- ld (hl),c ;z8e (monitor entry point) on stack
- ld sp,hl ;now set current stack to just below our
- ;return address
- ex de,hl ;hl - relocated address z8e
- inc hl
- inc hl ;hl - points to ld sp,0000 instruction at the
- ;start of the command processor. replace 0000
- ;with the address bdos-1
- ld (hl),e ;set real stack address
- inc hl
- ld (hl),d
- ld hl,(z8eb) ;base of relocated code
- ld de,fcb-z8eorg ;relative offset from start of monitor
- add hl,de
- ex de,hl ;de - fcb address in relocated monitor in hi
- ;memory
- ld hl,zbuf ;
- ld bc,16
- ldir ;init fcb with saved file name
- ld de,mz8eld ;print memory space occupied by z8e
- call print
- ld hl,(z8eb) ;display our base address in upper memory
- call outadr
- ld a,'-'
- call ttyo
- call space
- call space
- ld hl,(06) ;this points to the new jump to bdos
- inc hl
- ld e,(hl) ;de - old start of bdos address
- inc hl
- ld d,(hl)
- ex de,hl
- ld l,0 ;256 byte boundary to bypass cp/m serial no.
- call outadr
-
- ld a,(symflg) ;test for presence of symbol table
- and a
- jr nz,load40 ;nz - no table
- ld de,msymld ;display start address of symbol table message
- call print
- ld hl,(06) ;vector to bdos is start of symbol table
- call outadr
- ld a,'-'
- call ttyo
- call space
- call space
- ld hl,(z8eb) ;start of internal symbol table is end of
- ;symbol table built from files
- dec hl
- call outadr
-
- ld a,(tsymhi) ;total number of symbols from all files (bcd)
- call hexc ;convert to ascii
- ld h,a ;move hi order ascii digit to h
- ld (mhex),hl ;store double ascii digit
- ld a,(tsymlo)
- call hexc ;convert lo order
- ld h,a
- ld (mhex+2),hl ;save in string
- ld de,tsym.. ;total symbols message
- ld c,9
- call bdos
- ld de,mhex ;address of ascii digits
- ld b,3 ;check for leading zeros
- load20: ld a,(de)
- cp '0'
- jr nz,load30 ;nz - found first nz in string
- inc de
- djnz load20 ;check first three digits then fall thru and
- ;print fourth regardless
- load30: ld c,09
- call bdos
-
- load40: ld hl,(06)
- dec hl ;hl - address of new tpa
- ld de,mnvmem ;display address as memory available
- call print
- call outadr
- call crlf
- ld (hl),0 ;now store two zeros at the top of the tpa and
- ;set stack pointer to this very same address.
- ;this allows users to do a warm boot via ret
- ;in the same way as if they had been loaded by
- ;cp/m.
- dec hl
- ld (hl),0
- ld bc,(z8eb) ;our relocated address in hi memory
- ex de,hl ;de - last available location in tpa
- ld hl,spreg-z8eorg ;address (relative to the start of z8e) where
- ;we store the user stack pointer address
- add hl,bc ;hl - pointer to
- ld (hl),e ;save user stack in spreg in hi memory
- inc hl
- ld (hl),d
- ld hl,z8e-z8eorg
- ld a,(zbufnm) ;first char of file name
- cp ' ' ;do we have a file to load?
- jr z,load50 ;z - no
- ld de,mldg ;display loading message and target file name
- call nprint
- ld de,znmbuf
- call print
- ;enter the monitor in hi memory at entry
- ;point lldr10
-
- ld hl,lldr10-z8eorg
- ld bc,(z8eb)
- load50: add hl,bc ;hl - actual address of lldr10 in hi memory
- ex de,hl ;now clear out the buffer at 80h so the user
- ;program doesn't mistakenly think that our
- ;command line tail is really his.
- ld hl,iobuf
- ld (hl),0 ;set number of chars zero (80h)
- inc hl
- ld b,127 ;clear until start of tpa
- load60: ld (hl),' '
- inc hl
- djnz load60
- ex de,hl ;lldr10 address back to HL
- jp (hl) ;Hi-ho, hi-ho to the loader we must go
-
-
-
- page
- ;This routine reads one char from the disk I/O
- ;buffer returning it in A. Upon entry we check
- ;the low order buffer pointer - 0 means we hit
- ;the 256 boundary (end of buffer) and a read
- ;is needed.
-
- nchr: xor a
- or l
- call z,read
- ld a,(hl)
- inc hl
- ret
-
- read: push bc
- push de
- ld de,fcb
- ld c,20 ;sequential file read
- call bdos
- and a ;test for error
- ld hl,iobuf ;assume ok - init i/o buffer address
- pop de
- pop bc
- ret z ;z - no errors
- ld de,msymnf ;display symbol table not found message
- call print
- ld sp,stack ;reinit stack
- jp .eof50 ;check for more symbol files to load
-
-
- ;hexc
- ;Convert byte in a to two ASCII hex digits.
- ;return: a - converted hi order digit
- ; l - lo order digit
-
- hexc: ld h,a
- rrca
- rrca
- rrca
- rrca
- call hexc00
- ld l,a
- ld a,h
- hexc00: and 0fh
- add a,90h
- daa
- adc a,40h
- daa
- ret
-
-
- ;hex:
- ;This routine is called by the symbol table
- ;building routines, .sym and .prn and its
- ;function is to convert ascii addresses
- ;into binary. Since we are reading files in
- ;a known format we don't init any loop counts;
- ;instead, we look for delimeters.
-
-
- hex: call nchr ;get char from disk i/o buffer
- hex00: cp 3ah ;convert ascii to hex
- jp c,hex10 ;c - must be delimeter
- sub 7
- hex10: sub '0'
- ex de,hl ;shift hl left four
- add hl,hl
- add hl,hl
- add hl,hl
- add hl,hl
- or l ;or in this new digit
- ld l,a
- ex de,hl
- ld a,(bytes)
- dec a
- ld (bytes),a
- jp nz,hex
- call nchr
- cp 'I' ;global?
- call z,nchr ;z - need to read next to determine absolute
- ; or relocatable
-
- ld (relchr),a ;we need to save this character for .prn files
- ;so we can tell whether to add this symbol
- ;to the count of symbols loaded. if this
- ;is an external name we skip the add.
-
- cp ' ' ;space means absolute
- jr z,hex30 ;no bias added to absolute symbols
- ld a,(biaslo)
- add a,e ;add in bias as specified by user or default
- ;as initialized by us (zero)
- ld e,a
- ld a,(biashi)
- adc a,d
- ld d,a
- hex30: ld a,(maxlen) ;now point to last byte of symbol table
- ;entry, which is where we will store
- ;address just computed
- cpl
- and c
- ld c,a
- ld a,(maxlen)
- or c
- ld c,a ;never worry about carry - we always start
- ;with 256 boundary
- ld a,d ;store lo order symbol address
- ld (bc),a
- dec bc ;point to penultimate byte in block
- ld a,e ;hi order byte of address into symbol table
- ld (bc),a
- ld a,(maxlen) ;mask to rewind symbol table pointer to the
- ;start of this block
- cpl
- and c
- ld c,a
- ret
-
-
- totsym: ld de,nsymlo ;nsym - bcd running count of the number of
- ld a,(de) ; symbols loaded so far
- add a,1 ;bump by one symbol
- daa ;keep bcd format
- ld (de),a
- ret nc
- dec de ;account for carry by bumping hi order byte
- ld a,(de)
- add a,1
- daa
- ld (de),a
- ret
-
-
- ;zstx:
- ;Possible syntax error was detected as lfcb tried to init the FCB.
- ;However, we never keep track of how many files appeared in the
- ;command line we just keep calling lfcb. Hence, we will always get
- ;an error return at some point when the input buffer runs out of
- ;valid input. We check for real syntax error or end of command
- ;line by examining the first byte of the parse buffer: if zero then
- ;prsr found no valid characters in the input buffer and this is the
- ;end of input - else, lfcb found real syntax error.
-
-
- zstx: ld a,(prsbf)
- and a ;real syntax error - or end of input?
- jp z,load ;z - more files
- ld de,mldg ;display loading message and symbol name
- ;to preserve the syntax used on good loads
- call nprint
- ld de,prsbf ;display file name currently in parse buffer so
- ;user knows where goof was
- call print
- call crlf
- ld de,msntx ;now display syntax error
- call print
- jp .eof50 ;check for more files to load
-
-
- zfnf: ld de,mfilnf ;display file not found
- call print
- jp .eof50
-
-
- zmem: ld de,mmem?? ;display out of memory message
- call print
- call crlf
- ld hl,maxlen
- ld l,(hl)
- ld h,00
- add hl,bc
- ld (ntpa),hl
- jp load
-
-
- zoff: ld de,minvof ;display invalid offset using 0000 message
- call print
- ld hl,00
- jp zsym10
-
-
- fstrng:
- push bc
- push de
- fstr00:
- ld de,(pstrng) ;address of canned string pointer
- ld a,(de) ;length
- ld b,a
- inc de
- fstr10: call nchr ;get char
- cp eof
- jp z,fstr20
- ex de,hl ;DE - buffer ptr HL - "symbols:" string ptr
- cp (hl)
- ex de,hl
- jp nz,fstr00 ;mismatch read more from file
- inc de
- djnz fstr10 ;check entire string length
- fstr20: pop de
- pop bc
- ret
-
- .lst??: defb .lstsz ;string length
- defb 'Symbol Table:'
- defb cr,lf,cr,lf
- .lstsz equ $ - .lst?? - 1
-
-
- .prn??: defb .prnsz ;string length
- defb 'Symbols:' ;string to search for in M80's .prn files
- ;indicating start of symbol table
- defb cr,lf
- .prnsz equ $ - .prn?? - 1
-
- .slr??: defb .slrsz
- defb 'Symbols Detected.'
- defb cr,lf
- .slrsz equ $ - .slr?? - 1
-
- .m80??: defb .m80sz
- defb 'MACRO-80'
- .m80sz equ $ - .m80?? - 1
-
- tsym:
- tsymhi: defb 0
- tsymlo: defb 0
-
- usymbl: defw 0
-
- pstrng: defw 0
-
- relchr: defb 0
-
- .idprn: defb 0
-
- star: defb 0
-
- nsym:
- nsymhi: defb 0
- nsymlo: defb 0
- mhex: defb ' '
- defb '$'
-
- msym..: defb 'Number Of Symbols Loaded: $'
-
- tsym..: defb cr,lf
- defb 'Total Symbols: $'
-
- msymnf: defb 'Symbol Table Not Found'
- defb cr,lf,0
-
- minvof: defb 'Invalid Offset - Using 0000'
- defb cr,lf,0
-
- msymld: defb cr,lf
- defb 'Symbol Table: '
- defb 0
-
- mz8eld: defb cr,lf
- defb 'Z8E Relocated: '
- defb 0
-
- mnvmem: defb cr,lf
- defb 'Top Of Memory: '
- defb 00
-
- z8eb: defb 00
- z8ebh: defb 00
- ntpa: defw 00
-
- bytes: defb 00
-
- zbuf: defb 00
- zbufnm: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- znmbuf:
- rept 18
- defw 0,0
- endm
- if ASMB
- init:
- else
- init::
- endif
- ret
- defs 255
- page
- ;******************************************************************************
- ;*
- ;* z8e: Entry point to monitor
- ;*
- ;* Each command begins with the output of the '*' prompt.
- ;* Command character is validated by checking the cmd table,
- ;*
- ;* Relative position of command letter in cmd table also used
- ;* as index into command jump table jtcmd.
- ;*
- ;* All commands entered with b = 0.
- ;*
- ;******************************************************************************
-
-
- org ($+255) and 0ff00h
- ;was org 256*(($+255)/256)
-
- z8eorg:
- ;Note: first three bytes here become a jump to
- defs 16 ; BDOS after we are loaded
- ;
- ;This is the internal symbol table
-
- z8e: and a ;Any do-nothing instruction with the sign
- ;bit set to indicate end of internal symbol
- ;table
-
- defb 31h ;LD SP,nnnn - Load monitor stack pointer
- z8esp: defw 8000h ;Actual address filled in by nint at load
- ;time when we figure out where bdos is
-
- z8ecmd: ld hl,z8e
- push hl
- ld de,prompt ;display prompt (asterisk)
- call nprint
- ld hl,jstepf ;full screen debugging in effect?
- ld a,(hl)
- and a
- jr nz,z8e10 ;nz - no
-
- ld c,10
- call spaces ;If this was jdbg clear command line residue
- ld b,10
- z8e00: call bksp
- djnz z8e00
-
- z8e10: call inchar ;Read in command character
-
- ; +++ jrs 3.5.6 ++++++++++++++++++
- cp cr ;+Check for empty command line
- jr nz,z8e16 ;+Something there - process it
- ld a,(lcmd) ;+Nothing - see if S or J was last command
- cp 'J' ;+Repeat 'J' command?
- jp z,jdbg00 ;+
- ld hl,1 ;+
- cp 'S' ;+Repeat 'S' command?
- jp z,step40 ;+
- ld a,cr ;+
- z8e16: ;+
- ; ++++++++++++++++++++++++++++++++
- call ixlt ;Translate to upper case for compare
- ld (lcmd),a
- cp 'J' ;If command is anything but j then indicate
- ;that screen is corrupted. at next invokation
- ;jdbg will know to repaint the screen.
- jr z,z8e20
- ld (jstepf),a ;Full screen flag nz - full screen debugging
- ;in progress
-
-
- z8e20: ld bc,ncmd ;total number of commands
- ld hl,cmd ;table of ascii command characters
- cpir
- jp nz,e??? ;command letter not found in table
- ld hl,jtcmd ;command jump table
- add hl,bc
- add hl,bc ;index into table
- ld e,(hl) ;lo order command processing routine
- inc hl
- ld d,(hl) ;upper address
- ld c,3
- call spaces ;print spaces regardless
- ex de,hl ;hl - address of command processing routine
- jp (hl)
- page
- ;******************************************************************************
- ;*
- ;* bphn: breakpoint handler - rst38s land here
- ;*
- ;* bphn - bphn00 save all user registers
- ;* bphn10 - bphn20 check that user pc matches entry in brktbl.
- ;* bphn80 special single step processing.
- ;*
- ;* note: sbps is both a flag and the count of the number of step bps.
- ;* sbps is set to 1 merely to indicate that the single-stepping
- ;* is in effect. then the number of step bps is added to one.
- ;* hence, if 1 step bp was set then sbps = 2 and if 2 step bps
- ;* were set (conditional jump, call, ret) sbps = 3.
- ;*
- ;******************************************************************************
-
- bphn: ld (hlreg),hl ;save user hl
- pop hl ;pop breakpoint pc from stack
- ld (spreg),sp ;save user sp
- ld sp,(z8esp) ;switch to our stack
- dec hl ;point to location of rst instruction
- ld (pcreg),hl ;save user pc
- ld (dereg),de ;save user de
- ld (bcreg),bc ;save user bc
- push af
- pop hl ;user accumulator and flag to hl
- ld (afreg),hl ;save user af
- ld a,i
- ld h,a ;save user i reg
- ld a,r
- ld l,a ;save user r reg
- ld (rreg),hl
- ex af,af' ;Bank In Prime Regs
- exx
- ld (hlpreg),hl ;save
- ld (depreg),de
- ld (bcpreg),bc
- push af
- pop hl
- ld (afpreg),hl
- ld (ixreg),ix ;save user ix
- ld (iyreg),iy ;save user iy
- ld a,(bps)
- and a ;check for zero bp count
- jp z,bp??? ;error - no bps set
- ld b,a ;b - number of breakpoints
- ld hl,brktbl ;breakpoint storage table
- xor a
- ld c,a ;init breakpoint found flag
- bphn10: ld e,(hl)
- inc hl
- ld d,(hl) ;de - breakpoint address
- inc hl
- ld a,(hl) ;saved contents of breakpoint address
- inc hl
- ld (de),a ;replace rst 38 with actual data
- ld a,(pcregl) ;user pc - lo order
- xor e
- ld e,a ;versus breakpoint address in table
- ld a,(pcregh)
- xor d ;check hi order
- or e
- jr nz,bphn20 ;no match - check next entry in table
- ld c,b ;pc found in table set c reg nz
- bphn20: djnz bphn10 ;restore all user data
- ld hl,sbps ;fetch number of step bps (0-2)
- ld b,(hl)
- xor a
- ld (hl),a ;clear regardless
- or c ;test bp found flag
- jp z,bp??? ;z - bp not in table
- inc hl ;point to bp count
- ld d,(hl) ;d - bp count
- dec b
- jp m,bphn30 ;m - this was user bp not step or jdbg
- ld a,(hl)
- sub b ;subtract number of step bps from bp count
- ld (hl),a ;restore bp count
- ld a,(lcmd) ;what command got us here?
- cp 'S' ;step?
- jr z,bphn90 ;step command - check count
-
- ;now we know we have jdbg in progress. need
- ;to check for user specified bp at the same
- ;address. if we find one stop trace.
- ld a,b ;number of step bps to accumulator (1 or 2).
-
- sub c ;compare number of step bps with the offset
- ;into the bp table where the current bp was
- ;found. since step bps are always at the end
- ;of the table we can determine how bp was set.
-
- jp nc,jdbg30 ;nc - we are at end of table so more tracing
-
- bphn30: ld a,c
- neg
- add a,d ;create index into pass count table
- add a,a
- ld hl,psctbl ;pass count table
- add a,l
- ld l,a
- jr nc,bphn35
- inc h
- bphn35: ld e,(hl)
- inc hl
- ld d,(hl) ;de - pass count
- ld a,d
- or e
- jr z,bphn50 ;no count in effect
- dec de
- ld (hl),d
- dec hl
- ld (hl),e ;restored updated count
- ld a,d
- or e ;did it just go zero?
- jr z,bphn50 ;count just expired
- ld a,b ;pass count not zero - go or jdbg?
- and a
- jp p,jdbg30 ;if step flag p we had step bps
- ld hl,(pcreg)
- jp g100 ;continue go command
- bphn50: or b ;test if we had step bps
- jp m,bphn60 ;this was go - print bp message
- ld a,'X'
- ld (lcmd),a ;clear command letter so xreg disassembles
- call home ;home cursor
- call xreg
- ld b,22 ;cursor on penultimate line
- ld c,00
- call xycp
-
- bphn60: ld de,bpmsg ;print *bp*
- call print ;print message pointed to by de
- ld hl,(pcreg)
- call outadr ;display breakpoint address
- ex de,hl
- call fadr ;attempt to find label at this address
- ex de,hl ;de - bp address
- jp nz,z8e ;nz - no label found
- ld a,(maxlen)
- dec a
- ld c,a ;c - max size of label
- call printb
- jp z8e
- bphn90: call xreg ;display all registers
- ld hl,(nstep) ;fetch trace count
- dec hl
- ld a,l
- or h
- jp z,z8e ;count expired - prompt for command
- call ttyq ;test for abort trace
- cp cr
- jp z,z8e
- call crlf ;
- jp step40 ;continue trace
-
-
- bp???: ld de,bpemsg
- call print
- ld hl,(pcreg)
- call outadr
- jp z8e
-
-
- e???: ex de,hl
- ld de,em???
- call print
- ex de,hl
- ret
- page
- ;******************************************************************************
- ;*
- ;* jdbg: animated debugger
- ;*
- ;* Jdbg allows the user to watch the Z80 CPU actually execute the
- ;* code. Jdbg displays 18 disassembled instructions on the screen
- ;* as well as a user defined memory block referred to in the
- ;* comments as a window.
- ;*
- ;* Entry point jdbg:
- ;*
- ;* Jdbg processes user input as a prelude to the actual animation
- ;* of the code. The user enters the starting address to animate
- ;* optionally preceded by a subroutine qualifier. The subroutine
- ;* qualifier may be either a "*" which instructs Z8E not to trace
- ;* any subroutines which are located below 100h (ie. bdos calls),
- ;* or it may be a "/" which means no tracing of any subroutines.
- ;* Jdbg will also paint the original screen with the register
- ;* contents as well as the memory window. The contents of the
- ;* memory window are also moved into argbuf so that we can compare
- ;* the 'old' contents with the 'new' contents once a the first bp
- ;* is reached.
- ;*
- ;* Entry point jdbg30:
- ;*
- ;* Entered here via bphn who determines that animation is in
- ;* effect. In order to cut down on superfluous cursor move-
- ;* ment on the screen we compare the old register and memory
- ;* window contents with the new contents following the latest
- ;* bp. We only output the changes. Next we determine if the
- ;* current pc exists in disassembled form somewhere on the
- ;* screen; if not, we display 18 new disassembled instructions
- ;* with the current pc as line one.
- ;*
- ;* Exit jdbg95:
- ;*
- ;* Save current register contents and jump to step40 for next
- ;* single step.
- ;*
- ;******************************************************************************
-
- jdbg:
- call iedtbc ;get command line
- jp p,jdbg02 ;p - have input
-
- jdbg00: ld hl,lastro
- ld b,(hl) ;row position of arrow on screen
- ld c,18 ;column
- call xycp
- ld c,2
- call spaces
- ld b,17h
- ld c,00
- call xycp
- ld hl,jstepf
- ld a,(hl)
- ld (hl),1
- and a
- jp z,jdbg90 ;J was last means screen intact - just move
- ;arrow, else fall thru and repaint screen.
- ;Indicate single step
- jdbg01: ;+ eg 3.3.6
- ld a,10
- jr jdbg10 ;init timer
-
- jdbg02: ld a,(hl) ;check first char of input
- cp '#' ;+ eg 3.3.6
- jr nz,jdbg2a ;+ Skip if not repaint request
- ld hl,jstepf ;+
- ld (hl),1 ;+ Signal repaint request
- jr jdbg01 ;+
- jdbg2a: ;+
- ex de,hl ;de - save input buffer address
- ld hl,wflag ;wflag tells us whether to trace subroutines
- ;or walk around them
- ld (hl),0ffh ;conditionally assume trace all
- sub '/' ;slash means don't trace any
- jr z,jdbg03 ;
- add a,'/'-'*' ;check for star - no trace of bdos subs
- jr nz,jdbg05
- inc a ;set flag one to indicate no trace of subs
- ;at address < 100h (bdos calls)
- jdbg03: ld (hl),a ;set wflag
- xor a ;if slash or space replace with null in inbf
- ;so parser will ignore
- ld (de),a
- jdbg05: call iarg ;now evaluate address
- jr z,jdbg08 ;z - no error
- ld a,(inbfnc) ;check number of characters
- dec a ;check for just / or just *
- jr z,jdbg00 ;treat as single step
- ld (jstepf),a ;indicate screen corrupted
- jp e??? ;error -
- jdbg08: ld (pcreg),hl ;save address at which to start tracing
- and a ;check delimter
- ld a,10 ;no delimeter use default timer value
- jr z,jdbg10
- call iarg ;check if user wants non-default timer
- ld a,10
- jr nz,jdbg10 ;error - use default
- ld a,l ;a - timer value as entered by user
- jdbg10: ld (timer),a
- ld b,24 ;xmit crlf's to clear screen
- jdbg15: call crlf ;clear screen
- djnz jdbg15
- call rgdisp ;display current user regs
- call zwnw ;display disassembled window
- ld a,(wnwsiz)
- and a ;test if window being displayed
- jr z,jdbg28
- ld de,window ;save user specified memory block til next bp
- ld hl,(wnwtab) ;start of memory window address
- ld bc,3
- jdbg20: ld a,(fwndow) ;position cursor starting at column
- sub 6
- call curs
- call outadr ;display address of memory window
- jdbg25: ld a,(fwndow)
- call curs ;column position on screen of memory window
- ;is (rel pos * 3) + (fwndow)
- ld a,(hl) ;display this byte
-
- ld (de),a ;save this byte in window between bps
- call outhex
- inc b ;move and display user specifed number
- ;of bytes (wnwsiz)
- ld a,(wnwsiz)
- sub b
- jr z,jdbg28
- inc hl
- inc de
- ld a,(nlmask) ;check for new line time
- and b
- jr nz,jdbg25 ;not end of line - display next byte else...
- jr jdbg20 ;...display address first
- jdbg28: ld a,3 ;point to very first instruction
- jp jdbg75
-
-
- ;breakpoint handler jumps here for full
- ;screen single step
- jdbg30: ld c,3
- call spaces ;remove => from screen
- ld b,c ;(c=0 after spaces executes)
- ld hl,regcon ;new contents of registers following bp
- ld de,regsav ;old prior to bp
- jdbg35: ld a,(de) ;compare old vs new
- cp (hl)
- inc hl
- inc de
- jr nz,jdbg40 ;different - display new
- ld a,(de) ;check hi order byte of this reg pair
- cp (hl)
- jr z,jdbg45 ;z - hi and lo bytes the same so try next reg
- jdbg40:
- ; ld a,4 ;col position of reg pair is (rel pos * 9) + 3
- ; and b
- ; jr z,jdbg42
- ; ld a,3
- ; and b ;- 9 bytes deleted here
- ; inc a
- push bc ;+save register number
- ld c,b ;+move it to c while we build line number
- ld b,0 ;+assume first line for now
- ld a,7 ;+regs-per-line mask
- cp c ;+generate carry if second line
- rl b ;+shift carry into line number
- and c ;+generate line-relative register number
- ld c,a ;+col = reg * 9 + 3 if non-prime
- add a,a ;+ *2
- add a,a ;+ *4
- add a,a ;+ *8
- add a,c ;+ *9
- bit 2,c ;+is it a prime (alternate) register?
- jr z,jdbg42 ;+skip if not
- add a,c ;+*10
- sub 3 ;+col = reg * 10 if prime
- jdbg42:
- add a,3 ;+
- ld c,a ;+
- call xycp ;+
- pop bc ;+ added 29 bytes
-
- ; add a,3 ;- deleted another 5 bytes here
- ; call curs ;- nett cost = 14 bytes for new code
- ; ;- but we save 19 bytes in 'curs:' routine
-
- ld a,(hl) ;display upper byte of reg contents
- call outhex
- dec hl ;rewind to pick up lo order byte
- ld a,(hl)
- inc hl
- call outhex ;display lo order
- jdbg45: inc hl
- inc de
- inc b
- ld a,regsiz/2 ;number of reg pairs to display
- sub b
- jr nz,jdbg35
- call space
- ld b,1
- ld c,36
- call xycp
-
- ld b,0
- call pswDsp ;now display flag reg mnemonics
-
- ld a,(wnwsiz) ;check window size
- and a
- jr z,jdbg60 ;z - no memory window in effect
- ld hl,(wnwtab) ;hl - address of start of window
- ld bc,03
- ld de,window ;old contents of window stored here
- jdbg50: ld a,(de) ;compare old vs new
- cp (hl)
- jr z,jdbg55 ;same - no reason to display
- ld a,(fwndow) ;col position of byte is (rel pos * 3) + 50
- call curs
- ld a,(hl) ;display byte
-
- ld (de),a ;we only need to move byte if it changed
-
- call outhex
- jdbg55: inc b ;bump memory window byte count
- ld a,(wnwsiz) ;max size
- inc hl
- inc de
- sub b
- jr nz,jdbg50 ;loop until entire window examined
-
- jdbg60: ld a,18 ;init count of disassembled instructions
- ld (jlines),a
- ld de,(zasmfl) ;address of first disassembled instruction
- ;on screen
- jdbg65: ld hl,(pcreg)
- and a
- sbc hl,de
- jr z,jdbg70 ;found - pc exists somewhere on screen
- call zlen00 ;compute length of this instruction
- ld b,0
- ex de,hl ;hl - address on disassembled instruction
- add hl,bc ;add length to compute address of next inline
- ;instruction for display
- ex de,hl ;de - restore new istruction pointer
- ld hl,jlines
- dec (hl) ;dec screen line count
- jr nz,jdbg65
- ld hl,(pcreg) ;pc not on screen - so current pc will be new
- ;first pc on screen
- ld (zasmfl),hl
- ld bc,0300h ;cursor row 4 - col 1
- call xycp
- call zwnw ;instruction not on screen so paint a new
- ;screen starting at current pc
- ld a,3 ;disassembled instructions start on line 4
- jr jdbg75
- jdbg70: ld a,(jlines)
- neg
- add a,21 ;a - screen row on which to position cursor
- jdbg75: ld (lastro),a ;save position of arrow
- ld b,a ;pass to xycp
- ld c,18 ;pass column
- call xycp ;position cursor routine
- ld de,mrrow
- call print
- ld a,(lastro) ;xy positioning added after '=>' as
- ;some systems have a destructive bs
- ld c,17 ;new cursor loc
- call xycp ;put it there
- ld a,(jstepf)
- dec a ;test if single stepping
- jp z,jdbg95
- call ttyq
- ld hl,timer
- ld b,(hl)
- jr z,jdbg80
- cp '0'
- jr c,jdbg78
- cp 3ah
- jr nc,jdbg95
- and 0fh
- ld (hl),a
- ld b,a
- jr jdbg80
- jdbg78: cp cr ;carriage return ends command
- jr z,jdbg95
-
- jdbg80: call clok
-
- jdbg90: ld de,regsav ;move current reg contents to save area
- ld hl,regcon
- ld bc,regsiz
- ldir
- jp step40
-
-
- ;user requested abort from console
- jdbg95: ld b,22 ;position cursor on line 23 for prompt
- ld c,0
- call xycp
- xor a
- ld (jstepf),a ;indicate we have full screen of data
- jp z8e ;to z8e command processor
-
-
-
- zwnw: ;display disassembly window
- ld a,18 ;number of instructions to disassemble
- zwnw05: ld hl,(pcreg)
- ld (zasmfl),hl ;save pc of first line
- zwnw10: ld (jlines),a
- ld (zasmpc),hl ;save here as well
- ld de,zasmbf+96 ;disassemble in upper portion of buffer to
- ;prevent overlap with big memory windows.
- ;otherwise, every time we disassemble a new
- ;screen we have to repaint the window.
-
- call zasm10 ;disassemble first instruction
- ld a,30 ;test line length
- cp c
- jr z,zwnw20
- ld c,42
- zwnw20: call printb
- call crlf
- ld hl,(zasmnx) ;hl - next address to disassemble
- ld a,(jlines)
- dec a
- jr nz,zwnw10
- ld b,3 ;position cursor next to next instruction
- ;to execute which is the first one on the
- ;screen - line 4 col 20
- ld c,20
- call xycp
- ret
-
-
- ;display regs at top of screen:
- rgdisp: call home ;home cursor
- call xreg ;display regs
- call pswDsp ;display flag reg
- jp crlf
-
-
-
- curs: push bc ;This routine has been simplified and shortened
- push de ;by 19 bytes because it is no longer used for
- push hl ;register display positioning. jrs 20/4/87
- ld d,a
- ld e,c ;save base row address
- ; cp 3 ;test if reg or memory window (3 is reg)
- ; ld a,7
- ; jr z,curs00 ;z - regs are eight per line (first line)
-
- ld a,(nlmask)
- curs00: and b ;item number mod lnmask is the relative pos of
- ld c,a ;reg contents or memory data byte
- add a,a ;
- add a,c
- ld c,a ;c - rel pos times three
-
- ; ld a,d ;if base column address is < 50 then this is
- ;reg display
- ; sub 3
- ; ld h,a
- ; ld a,c
- ; jr nz,curs20 ;nz - not reg display - must be memory
- ; add a,a ;so multiply times three again
- ; add a,c ;times 9 in all for register display
-
- curs20: add a,d ;add in base
- ld c,a ;c - absolute col number
- ; xor a ;test if this is reg or memory window display
- ; or h
- ; jr z,curs30 ;z - this is register display
- ld a,(fwndow)
- cp 68 ;14-char symbols in effect?
- jp z,curs40
- curs30: srl b
- curs40: ld a,0fch
- and b ;now compute row number
- rrca
- rrca
- add a,e ;base row address
- ld b,a ;b - absolute row number
- call xycp ;convert row and column to xy cursor address
- pop hl
- pop de
- pop bc
- ret
-
-
-
- clok:
- ld d,50 ;idle loop - decrement to 0 and reload
- ld e,00
- dec b ;user specified the loop counter
- ret m
- clok10: dec de
- ld a,e
- or d
- jr nz,clok10
- jr clok
-
- page
- ;******************************************************************************
- ;*
- ;* exam: examine memory and display in hex and ascii. user is allowed
- ;* to modify memory after every byte is displayed. ilin called
- ;* to parse input buffer into a single string of bytes which is
- ;* returned in argbuf. the byte count of the string is returned
- ;* in argbc, and this number of bytes is transferred to the
- ;* current memory address.
- ;*
- ;* user may optionally scan memory by entering cr. command
- ;* terminates when a single space is entered.
- ;*
- ;* enter: b - 0
- ;* de - address at which to display first byte
- ;*
- ;******************************************************************************
-
- exam: call ilin
- jp nz,e???
- ex de,hl
- exam00: call newlin
- ld a,(de) ;fetch byte to display regardless
- call outbyt
- call byte
- jr nz,exam00 ;nz - don't replace memory contents
- cp '.'
- jr nz,exam10
- ld a,(inbfnc)
- dec a
- ret z
- exam10: ld hl,argbc ;byte count to c
- ld c,(hl)
- ld b,0
- ld (exampt),de
- ld hl,argbf ;start of evaluated input
- ldir
- ld a,(trmntr)
- cp cr
- jr z,exam00
- ld de,(exampt)
- jr exam00
- page
- ;------------------------------------------------------------------------------
- ;
- ; hsym: display symbol table
- ;
- ; User may display the symbol table on the console. If no arg
- ; entered on command line then the entire table is dumped start-
- ; ing with the first symbol. If a valid symbol is entered then
- ; we will try to find the symbol in the table; if found, the
- ; table is dumped starting at that point. If the symbol is not
- ; found the user gets a ? and the command terminates.
- ;
- ; Symbols are displayed in blocks of 32. After each block the
- ; user is given the opportunity of continuing or ending the
- ; command:
- ;
- ; cr - Terminate \ jrs 27 Dec 88
- ; not cr - Display next block / v 3.5.1
- ;
- ;------------------------------------------------------------------------------
-
- hsym: call ilin ;Read in line of data
- ld hl,z8e ;Assume no symbol entered
- jr nz,hsym10 ;NZ - no input means display entire table
- ld de,prsbf
- call fsym ;Attempt to find this symbol name in table
- jp nz,e??? ;Error - symbol not found in symbol table
- ld a,(maxlen)
- or l ;Point to next symbol table entry (next block)
- ld l,a ;HL - ptr to last byte in this entry
- inc hl ;Now next entry toward hi memory
- hsym10: ld a,(maxlen) ;Max size of symbol name
- ld c,a
- dec c
- inc a ;Make 8 or 16
- ld e,a
- xor a
- ld d,a ;DE - size of symbol table entry
- sbc hl,de ;Previous entry toward low memory
- ld a,(hl) ;Null means this is unused slot is user
- ;defined symbol table
- and a
- jr z,hsym10
- dec a ;Neg means this is jp opcode (0c3h) of jump to
- ;BDOS
- ret m
- ld a,(maxlen)
- srl a
- srl a
- xor 2
- and b ;Check symbols per line count
- call z,crlf ;crlf every fourth
- dec b ;Now decrement symbols per line count
- call printb ;Treat symbol table entry as a buffer and
- ;Six chars or until null, whichever is first
- inc c ;Tack on two spaces
- inc c
- call spaces
- ld a,(maxlen)
- or l ;Point to last byte in symbol table block
- ld l,a
- ld d,(hl) ;Upper byte of symbol address
- dec hl
- ld e,(hl) ;Low order
- ex de,hl
- call outadr ;HL - symbol address to display
- ld c,4
- call spaces ;Next symbol name starts 4 spaces to the right
- ex de,hl ;HL - symbol table pointer
- ld a,(maxlen)
- cpl
- and l ;Rewind to point to byte zero of entry
- ld l,a
- ld a,b
- and 31 ;Displayed block of 32 symbols?
- jr nz,hsym10
- call crlf
- call ttyi ;Test if user wants abort
- cp cr
- jr nz,hsym10 ;Not CR - continue (jrs v3.5.1)
- ret ;CR - end command
- page
- ;*****************************************************************************
- ;*
- ;* usym: write symbol table to disk
- ;*
- ;*****************************************************************************
-
- usym: call iedtbc ;get a command line
- ret m ;no input ends command
- call bldf ;build fcb
- jp nz,esntx ;syntax error
- ld hl,z8e ;start at beginning
- ld a,(symflg) ;do we even have a symbol table?
- and a
- ret nz ;no table - end command
- ld b,128 ;disk write buffer size
- ld (lines),a ;clear symbols per line counter
- ld de,symbuf
- usym10: ld a,(maxlen)
- ld c,a ;max size of symbol name
- cpl
- and l ;rewind to byte zero of symbol table entry
- ld l,a
- ld a,b ;temp save buffer count
- ld b,0
- sbc hl,bc
- dec hl ;point to 8 or 16 byte boundary
- ld b,a ;restore buffer count
-
- ld a,(hl) ;null means this is unused slot in user
- ;defined symbol table
- and a
- jr z,usym10
- dec a ;neg means this is jp opcode (0c3h) of jump to
- ;bdos
- jp p,usym20
- call pcrlf ;hit end of table - put crlf in buffer
- ld a,eof
- ld b,1 ;force buffer write
- call putc ;put eof in file
- jp closef ;this is a wrap
-
- usym20: ld a,(maxlen)
- or l
- ld l,a ;point to hi order byte of symbol address
- call pbin ;put address in buffer
- ld a,' '
- call putc ;followed by space just like l80
- ld a,(maxlen)
- cpl
- and l ;rewind to byte zero of symbol entry
- ld l,a
-
- dec c ;14 Sep 85 restore maxlen size as count
-
- usym25: ld a,(hl) ;fetch char of symbol name
- and a ;null?
- jr z,usym40 ;name is less than 6 chars long
- call putc ;put valid symbol name chars in buffer
- dec c
- jr z,usym40 ;z - just moved last char
- inc hl
- jr usym25
- usym40: ld a,tab ;tab separates name and next address
- call putc ;insert tab before address field
- ld a,(lines)
- dec a
- ld (lines),a
- and 3 ;insert crlf every fourth symbol
- jr nz,usym10
- call pcrlf
- jr usym10
-
-
-
- pcrlf: ld a,cr
- call putc
- ld a,lf
- jr putc
-
-
- ;convert two byte binary address to ascii
- ;and put into buffer
- pbin: call pbin00
- dec hl
- pbin00: ld a,(hl)
- call binx
- call putc
- ld a,(hl)
- call binx00
-
-
- putc: ld (de),a ;just like pascal - put char into buffer
- inc de
- dec b ;buffer count passed in b
- ret nz
- putc00: ld de,symbuf ;hit end of buffer - reinit pointer to start
- call bwrite ;write current buffer [ras 14 sep 85]
- ld b,128 ;reinit tally
- ret
- page
-
- ;------------------------------------------------------------------------------
- ;
- ; dump: Dump memory in hex and ASCII
- ;
- ; Memory is dumped in hex and ASCII in user-specified block size.
- ; If the D command is given without arguments then memory is dumped
- ; beginning at the address where we left off as store in blkptr.
- ; User is queried after each block is dumped:
- ;
- ; cr - End command \ v 3.5.1
- ; Not cr - Dump next consecutive block / jrs 27 Dec 88
- ;
- ;------------------------------------------------------------------------------
-
- dump: call iedtbc ;Solicit input
- jp p,dump00 ;p - input present
- ld de,(bsiz) ;No input means use previous block size
- ld hl,(blkptr) ; ... and address
- jr dump30
- dump00: call iarg ;Read in next arg (starting address)
- jp nz,e??? ;Invalid starting address
- ex de,hl ;DE - starting address to dump
- call iarg ;Next arg (block size)
- jr z,dump15 ;Z - no errors
- ld hl,000 ;Default to block size of 256
- jr dump20
- dump15: xor a
- or h ;Test for block size or ending address
- jr z,dump20 ;Less than 256 must be block size
- sbc hl,de ;Compute size
- jp c,e???
- dump20: ld a,l
- or h
- jr nz,dump25
- inc h
- dump25: ld (bsiz),hl
- ex de,hl ;DE - block size HL - memory pointer
- dump30: ld b,16 ;Init bytes-per-line count
- call ttyq
- cp cr
- ret z
- call crlf ;Display current address on new line
- call outadr
- ld c,2
- call spaces ;Hex display starts two spaces right
- dump40: dec b ;Decrement column count
- ld a,(hl)
- inc hl
- call othxsp ;Display memory in hex
- inc c ;Tally of hex bytes displayed
- dec de ;Decrement block count
- ld a,d
- or e ;Test for end of block
- jr z,dump50 ;Z - end of block
- xor a
- or b ;End of line?
- jr nz,dump40 ;Not end of line - dump more in hex
- jr dump60
- dump50: ld a,(bsizhi)
- and a ;Block size greater than 256?
- jr nz,dump55 ;NZ - greater
- ld a,(bsizlo)
- and 0f0h ;Block size less than 16?
- jr z,dump60 ;Z - less
- dump55: ld a,(bsizlo)
- and 0fh ;Block size multiple of 16?
- jr z,dump60 ;Multiple of 16
- neg
- add a,16
- ld b,a
- add a,a
- add a,b
- dump60: add a,3 ;Plus three - begin ASCII display
- ld b,a ;Pad line until ASCII display area
- dump70: call space
- djnz dump70
- sbc hl,bc ;Rewind memory point by like amount
- dump80: ld a,(hl) ;Start ASCII display
- inc hl
- call asci
- dec c
- jr nz,dump80
- call ttyq ;CR aborts command
- cp cr
- jp z,z8e
- ld a,d ;Test for block size tally expired
- or e
- jr nz,dump30
- ld de,(bsiz) ;Reinit block size
- call ttyi ;Query user for more
- cp cr
- ; Next two lines replaced by inverted test - 27 Dec 88 - jrs - V 3.5.1
- ; call z,crlf
- ; jr z,dump30 ;not cr - next block
- ;---- (Comment on last line is wrong anyway!)
- call nz,crlf ;Not cr - next block
- jr nz,dump30
- ;----
- ld (blkptr),hl
- ret ;end command
- page
- ;******************************************************************************
- ;*
- ;* rgst: display and optionally modify individual registers
- ;*
- ;* call iedt: read edited input into inbf
- ;* call prsr: parse input
- ;* call mreg: validate register name and map into reg storage
- ;* call iarg: query user for replacement
- ;*
- ;******************************************************************************
-
- rgst: ld c,' ' ;get edited input
- ld b,inbfsz
- call iedt
- ret m
- ld a,(trmntr)
- cp ' '
- call z,bksp
- call prsr
- or b ;unbalanced quotes (prime reg?)
- jp p,rgst00
- and 7fh
- cp 3
- jr nz,rgst25
- dec hl
- ld a,(hl)
- sub quote
- jr nz,rgst25
- ld (hl),a
- rgst00: ld a,(inbfnc) ;number of characters in buffer
- cp 4
- jr nc,rgst25 ;error - too many chars
- neg
- add a,4 ;calculate space padding
- ld c,a
- cp 3 ;was it one?
- jr nz,rgst10
- ld a,(de)
- call ixlt
- cp 'P'
- jr nz,rgst10
- ld (inbfnc),a ;any number > 2 indicates 16 bit register
- rgst10: call spaces
- ld a,(hl) ;check last char in parse buffer
- sub quote
- jr nz,rgst15 ;not quote
- ld (hl),a ;replace with null
- rgst15: call mreg ;validate register name
- jr nz,rgst25 ;error
- ld a,(regtrm) ;mreg stored char following reg name
- and a
- jr nz,rgst25 ;error - no operators allowed
- ld a,(inbfnc) ;now check number of chars in buffer
- ld b,a ;save in b reg for 8 or 16 bit reg test
- dec a ;test for one - 8 bit reg
- ld c,3
- jr z,rgst20
- ld a,(hl)
- call outhex ;display byte of reg contents
- dec hl
- ld c,1
- rgst20: ld a,(hl)
- call othxsp
- call spaces ;reg c - number of spaces to print
- ex de,hl ;de - save reg contents pointer
- rgst22: call istr ;query user for reg value replacement
- ld a,(inbfnc) ;test number of chars in input buffer
- dec a ;
- jp m,rgst40 ;none - prompt for next reg name
- call irsm
- jr z,rgst30
- ld a,(inbfnc)
- and a
- jr z,rgst22
- rgst25: call e???
- jr rgst40 ;accept new reg name
- rgst30: ex de,hl
- ld (hl),e
- dec b ;test for 16 bit reg
- jr z,rgst40 ;z - 8 bit reg
- inc hl
- ld (hl),d ;save upper byte of user input
- rgst40: call crlf
- call space5
- jp rgst
-
-
-
- mreg: ld c,23 ;number of reserved operands
- call oprn00 ;check validity of register name
- ld a,(de) ;last char examined by operand routine
- call oprtor
- ret nz ;error - not null or valid operator
- ld (regtrm),a ;save terminator character for rgst
- ld a,c
- cp 17 ;valid reg names are less than 17
- jr c,mreg00 ;so far so good
- sub 23 ;last chance - may be pc
- ret nz ;error - invalid reg name
- ld a,10 ;make pc look like p for mapping
- mreg00: ld hl,regmap ;ptrs to register contents storage
- add a,l ;index into table by operand value
- ld l,a
- jr nc,mreg05
- inc h
- mreg05: ld a,b ;b reg set m by prsr if trailing quote
- and a
- ld a,0 ;assume no quote - not prime reg
- jp p,mreg10 ;p - correct assumption
- ld a,8 ;bias pointer for prime reg contents
- mreg10: add a,(hl)
- ld c,a ;save mapping byte
- and 7fh ;strip sign
- ;so iarg knows 16 bit reg pair
- ld hl,regcon ;use mapping byte to build pointer
- add a,l
- ld l,a
- jr nc,mreg50
- inc h
- mreg50: xor a ;hl - pointer to register contents
- ret
-
- page
- ;******************************************************************************
- ;*
- ;* qprt: read and display / write to i/o ports
- ;*
- ;* contents of ports are displayed and the user is queried
- ;* input character effects the current port address:
- ;*
- ;* space - display next sequential port on same line
- ;* lf - display next sequential port on new line
- ;* cr - end command
- ;* slash - display same port on same line
- ;* ^ - display previous port on new line
- ;*
- ;* any other input is treated as a replacement byte and
- ;* is output to the current port address. any of the
- ;* above characters may be used to continue the display.
- ;*
- ;* enter: e - port at which to begin display
- ;*
- ;******************************************************************************
-
- qprt:
- nprt:
- xor a
- ld (parenf),a
- call iedtbc ;get port specified by user
- ld hl,port
- ld e,(hl)
- jp m,qprt30 ;m - no input means use last port number
- ex de,hl
- call iarg ;extract address
- jp nz,e???
- ex de,hl ;e - new port number
- ld (hl),e
- ld a,(parenf)
- cp '('
- jr nz,qprt30
- ld c,2
- call spaces
- qprt00: ld c,e
- in a,(c)
- ld b,a
- call outhex
- ld c,2
- call spaces
- ld c,8 ;number of bits to display
- qprt10: sla b ;most significant bit to carry
- ld a,'0'
- adc a,0 ;carry makes it a 1
- call ttyo
- dec c
- jr nz,qprt10
- ld c,e
- ld b,3
- call ttyq
- cp cr
- ret z
- call clok ;so we don't go faster than the terminal
- ld e,c
- ld a,b
- and a
- ret p
- ld b,12
- qprt20: call bksp
- djnz qprt20
- jr qprt00
- qprt30: call crlf
- ld a,e
- ld (port),a
- call othxsp
- call space
- ld c,e
- ld a,(lcmd)
- cp 'N'
- jr z,qprt50
- in a,(c)
- call outbyt
- qprt50: call byte
- ld a,(trmntr)
- jr nz,qprt60
- cp '.'
- ret z
- ld hl,argbc
- ld b,(hl)
- ld hl,argbf
- ld c,e ;port number
- otir
- jr qprt30
- qprt60: cp ' '
- jr nz,qprt30
- dec de
- jr qprt30
-
-
- page
- ;******************************************************************************
- ;*
- ;* break: set breakpoint routine
- ;*
- ;* breakpoint address storage table (brktbl) is examined and user
- ;* specified breakpoint is considered valid unless:
- ;*
- ;* - table full
- ;* - address already exists in table
- ;*
- ;* optional pass counts can be specified by the user immediatley following
- ;* the breakpoint if they are enclosed in parens.
- ;*
- ;* entry point brk30:
- ;* entered from single step command to set breakpoint. two table
- ;* slots are permanently available for step breakpoints. step
- ;* routine calls with c pos to tell us not to look for more args
- ;* in the input buffer.
- ;*
- ;******************************************************************************
-
- break: call iedtbc
- ret m ;end command - no input
- ld c,0ffh ;set neg - distinguish ourselves from step
- brk10: ld a,(bps) ;fetch current bp count
- cp maxbp ;table full
- jp nc,e??? ;full - abort command
- ld b,a ;save current count
- call iarg
- jp nz,e???
- ex de,hl ;de - breakpoint address to set
- brk30: ld hl,brktbl
- xor a
- or b ;check for no breakpoints in effect
- jr z,brk60 ;none - bypass check for duplicate
- brk40: ld a,e
- cp (hl) ;check lo order address match
- inc hl
- jr nz,brk50 ;no match - check next
- ld a,d
- sub (hl) ;check hi order
- jr nz,brk50 ;no match - check next
- or c
- ret p
- ld hl,bps ;pointer to bp count
- ld a,(hl)
- sub b ;create index into psctbl
- jr brk70
- brk50: inc hl
- inc hl ;bump past contents storage byte
- djnz brk40
- brk60: ld (hl),e ;set in table
- inc hl
- ld (hl),d
- ld hl,bps ;breakpoint count
- ld a,(hl) ;fetch current count for user as index
- inc (hl) ;bump bp count
- brk70: ld de,psctbl ;base of pass count table
- add a,a ;two byte table
- add a,e
- ld e,a
- jr nc,brk80
- inc d
- brk80: xor a
- ld (de),a ;pre-clear pass count table entry
- inc de
- ld (de),a
- or c ;test if this was step calling
- ret p ;i'm positive it was
- ld a,(delim) ;check delimeter which followed bp address
- and a
- ret z ;end of line null - terminate command
- cp ',' ;check for pass count delimeter
- jp nz,brk10 ;not comma means treatt this as new bp
- call iarg ;get next arg
- jp nz,e??? ;nz - evaluation error
- ex de,hl ;de - pass count as entered by user
- ld (hl),d ;store pass count in table
- dec hl
- ld (hl),e
- and a ;check delimeter
- jp nz,brk10 ;nz - more arguments follow
- ret ;end of line null - terminate command
- page
-
- ;******************************************************************************
- ;*
- ;* cbreak: clear breakpoint
- ;*
- ;* breakpoint address storage table (brktbl) is examined and breakpoint
- ;* is removed if found. breakpoint is removed by bubbling up all bp
- ;* addresses which follow, ditto for pass counts.
- ;*
- ;******************************************************************************
-
- cbreak: call iedtbc
- ret m ;no input ends command
- ld a,(bps) ;fetch breakpoint count
- or a ;any if effect
- ret z ;no
- ld b,a ;temp save count
- call iarg ;extract address to clear from input buffer
- ld de,brktbl ;bp address storage table
- jr z,cbrk10
- ld a,(prsbf)
- cp '*'
- jp nz,e???
- ld a,(inbfnc)
- dec a
- jp nz,e???
- ld (bps),a
- ret
-
- cbrk10: ld a,(de) ;test lo order address for match
- cp l
- inc de
- jr nz,cbrk20 ;no match - examine next entry
- ld a,(de)
- cp h ;versus hi order bp address
- cbrk20: inc de
- inc de ;bump past contents save location
- jr z,cbrk30 ;zero - found bp in table
- djnz cbrk10
- jp e??? ;error - breakpoint not found
- cbrk30: ld h,0ffh ;rewind to point to bp address
- ld l,-3
- add hl,de
- ex de,hl ;de - ptr to bp hl - ptr to next bp
- ld a,b ;multiply number of bps remaining in table
- ;times three bytes per entry
- add a,a
- add a,b
- ld c,a ;init c for ldir
- ld a,b ;save number of bps remaining
- ld b,0
- ldir ;bubble up all remaining entries in table
- ld c,a ;
- ld hl,bps ;address of bp count
- ld a,(hl) ;
- dec (hl) ;decrement system breakpoint count
- sub c ;compute relative number of pass count table
- ;entry we wish to clear
- add a,a ;times two bytes per entry
- ld l,a
- ld h,b ;cheap clear
- ld de,psctbl
- add hl,de ;index into pass count table
- ex de,hl
- ld hl,02
- add hl,de ;de - ptr to pass count hl - next in table
- sla c ;number of pass counts to move
- ldir
- ld a,(delim) ;recheck delimeter
- and a
- jr nz,cbreak ;not end of line terminator - clear more
- ret
- page
- ;***********************************************************************
- ;*
- ;* obreak: output all breakpoints and associated pass counts to
- ;* console. search symbol table for match, if symbol name
- ;* found display it along with address.
- ;*
- ;* wbreak: wipe out (clear) all breakpoints currently in effect
- ;*
- ;* entered: b - zero
- ;*
- ;***********************************************************************
-
- obreak: ld a,(bps) ;fetch bp count
- dec a ;test for no breakpoints
- ret m ;m - none
- ld b,a ;save count
- obrk00: ld hl,brktbl ;base of breakpoint storage table
- ld e,b ;use current breakpoint count as index
- ld d,0 ;clear
- add hl,de ;this is a three byte table
- add hl,de
- add hl,de
- ld e,(hl) ;fetch lo order bp address
- inc hl
- ld d,(hl) ;upper address
- ex de,hl
- call outadr ;display address
- ex de,hl ;hl - breakpoint table
- call fadr ;check symbol table for name match
- ; symbol table pointer returned in de
- ; zero flag set if found
- ld a,(maxlen)
- ld c,a
- dec bc ;max number of chars in a symbol name
- ex de,hl ;hl - symbol table address if
- call z,printb ;display name if found in symbol table
- ld a,b
- add a,a ;bp number times two
- ld hl,psctbl ;base of pass count table
- add a,l
- ld l,a
- jr nc,obrk10
- inc h
- obrk10: ld e,(hl) ;lo order pass count
- inc hl
- ld d,(hl) ;upper byte
- ld a,d ;test if pass count in effect
- or e
- jr z,obrk20 ;z - no pass count for this bp
- inc c
- call spaces
- ex de,hl
- call outadr ;display pass count in hex
- obrk20: call crlf
- ld c,5
- call spaces
- dec b ;dec bp count
- jp p,obrk00
- ret
-
-
-
- kdmp: call iedtbc ;let user input address of memory to display
- ret m ;no input ends command
- call iarg ;evaluate user arg
- jp nz,e???
- ex de,hl ;de - save memory address
- call iarg ;now get count
- ld a,0
- jr nz,kdmp20 ;error during input - display 00 bytes
- or h
- jp nz,e??? ;greater than 256 is error
- ld a,(maxlen) ;max symbol length
- ld b,2 ;assume big names
- cp 15
- ld a,18 ;number of disassembled lines displayed
- jr z,kdmp00
- ld b,3 ;double number of lines one extra time
- kdmp00: add a,a ;times two
- djnz kdmp00
- cp l
- jr c,kdmp20 ;if number of bytes specified by user is too
- ;large then use default
- ld a,l ;use value specified by user
- kdmp20: ld (wnwtab),de
- ld (wnwsiz),a
- ret
- page
- ;**************************************************************************
- ;*
- ;* begin/resume execution of user program
- ;*
- ;* address entered: execution begins at entered address
- ;* no address entered: execution resumed at specified by saved pc
- ;*
- ;* breakpoint table examined:
- ;* - memory contents from each address is removed from user
- ;* program and saved in breakpoint table
- ;* - rst 38 instruction is placed at each breakpoint address
- ;* in user program
- ;*
- ;* user registers restored
- ;*
- ;***************************************************************************
-
- go: call iedtbc ;query user for execution address
-
- ; ret m ;- eg 3.3.3 no input - reprompt
- jp p,g001 ;+ Skip if argument supplied, else:
- ld hl,(pcreg) ;+ Use current PC
- jr g002 ;+
- g001: ;+
- call iarg
- jp nz,e??? ;error - invalid argument
- g002: ;+
- call crlf
- call crlf
- g100: ld (jmplo),hl ;store execution address
- ld a,jp
- ld (jmp),a ;set jp instruction
- ld (jmp2jp),a ;just in case
- ld a,(bps) ;check breakpoint count
- and a
- jp z,g600 ;z - no bps in effect - no restoration needed
- ld b,a
- ld hl,brktbl
- ld c,0ffh
- g300: ld e,(hl)
- inc hl
- ld d,(hl) ;de - breakpoint address removed from table
- inc hl ;point to contents save byte in table
- ld a,(de)
- ld (hl),a
- ld a,(jmplo)
- cp e ;check if bp from table matches next pc
- jr nz,g400 ;no match - set breakpoint
- ld a,(jmphi)
- cp d ;check hi order next pc address
- jr nz,g400 ;no match - set bp
- ld c,b ;set flag - current pc matches breakpoint
- jr g500
- g400: ld a,rst38 ;set rst38 instruction
- ld (de),a ;save user byte in brktbl
- g500: inc hl
- djnz g300 ;examine all entries
- inc c ;current pc match breakpoint?
- jp z,g600 ;z - no (c reg not 0ffh)
- ld a,(sbps) ;check number of step breakpoints
- and a ;tracing?
- jp nz,g600 ;nz - this is trace
-
- ;pc points to address in breakpoint table
- ;next instruction will not be executed where
- ;it resides. it will be moved to our internal
- ;buffer (execbf) and executed there. then we
- ;set an rst38 at actual location in user
- ;program. this allows us to debug loops in
- ;which only one bp is set. otherwise we would
- ;not be able to set a bp at the address where
- ;the pc points and debugging loops would be
- ;impossible.
- ld hl,execbf
- ld de,(jmplo) ;de - pointer to next instruction to execute
- ld (jmplo),hl ;execute buffer
- ld b,4 ;clear execute buffer
- g505: ld (hl),nop
- inc hl
- djnz g505
- call zlen00 ;calculate length
- ;if instruction modifies pc then zlen lets us
- ;know by setting b reg nz and c contains
- ;instruction length
-
- ld (jropnd),hl ;if this is a jr instruction we need to save
- ;address where we will be jumping
-
-
- ;default execbf has been initialized:
- ;
- ;four nops
- ; jp user program
- ;
- ex de,hl ;hl - ptr to user instruction
- ld de,execbf
- ld a,(hl) ;first object byte from user program
- g518: ld (hl),rst38 ;replace
- push bc ;b - if nz this is a pc modifying instruction
- ;c - number of bytes of object code for this
- ; instruction
- g520: ld (de),a ;into execute buffer
- inc de
- inc hl ;bump user program pointer
- ld a,(hl) ;next byte of instruction from user program
- dec c
- jr nz,g520
- pop bc
- ;the four nops in execbf have now been replaced
- ;by from one to four bytes of actual user
- ;instruction. if user instruction was shorter
- ;than four bytes the nops remain and are
- ;executed until the jump back to the user
- ;program at jmp2jp is reached.
-
-
- ld (jmp2),hl ;address of next inline instruction within
- ;user code
-
- ex de,hl ;de - next inline instruction in user program
- xor a
- or b
- jr z,g600 ;z - the instruction in execbf is not a pc
- ;modifying instruction
-
- ld a,(execbf) ;first byte of instruction
- dec c ;one byte instruction?
- jr z,g600
- dec c
- jr z,g550 ;two byter
- dec c
- jr nz,g600 ;nz - must be four byter
- ld b,c ;clear for cpir
- ld c,z803sl ;test for call instruction
- ld hl,z803s ;load list of first byte of call instructions
- cpir
- jr nz,g600 ;nz - not call
-
- ;moving call instructions and executing them
- ;locally requires special processing because
- ;the z80 will store the address pc+3 on the
- ;stack. in this case we do not want the
- ;address execbf+3 on the stack. we want the
- ;address of the actual location of the user
- ;instruction+3 on the stack. we must do this
- ;by simulating a call instruction. we use the
- ;jp instruction which is equivalent to the
- ;call and we also push a computed return
- ;address on to the user stack pointed to by
- ;spreg.
-
- ld bc,08 ;point to jump instruction which is equivalent
- ;to call (call nz = jp nz)
- add hl,bc
- ld a,(hl) ;fetch jump object byte
- ld hl,(spreg) ;push next pc onto user stack
- dec hl ;decrement user sp
- ld (hl),d ;de - "return address"
- dec hl
- ld (hl),e
- ld (spreg),hl
- ld (execbf),a ;store jp op code
- ld hl,jmp2 ;if conditional call and we fall thru
- ;we need to go back to address of call
- ;in user program + 3
- ld (hl),e
- inc hl
- ld (hl),d
- jr g600
- ;if next instruction to execute is a
- ;relative jump we need to replace it with
- ;an absolute equivalent. this is because
- ;having relocated the user jr instruction
- ;into execbf we will undoubtedly be out of
- ;range of the destination.
-
- g550: ld c,z802cl ;check if this is relative jump
- ld hl,z802c
- and a ;clear carry
- cpir
- jr nz,g600 ;not a jr
- ld a,c
- ld bc,z802c
- sbc hl,bc
- dec hl
- ld bc,z803c
- add hl,bc ;point to equivalent absolute jump
- and a
- ld a,(hl)
- ld hl,execbf
- jr nz,g555 ;nz - not last in list (not djnz)
-
- ;replace djnz with dec b
- ; jp nz,
-
- ld (hl),05 ;dec b instruction
- inc hl
- ld a,0c2h ;jp nz absolute
- g555: ld (hl),a
- inc hl
- ld bc,(jropnd) ;if this is a conditional jr we need the
- ;absolute destination of the jump
- ld (hl),c
- inc hl
- ld (hl),b
-
- g600: ld iy,(iyreg) ;restore user iy
- ld ix,(ixreg) ;restore user ix
- ld a,(rreg)
- ld r,a ;restore user r reg
- ld a,(ireg)
- ld i,a ;restore user i reg
- ld bc,(bcpreg) ;restore user grade a prime regs
- ld de,(depreg)
- ld hl,(afpreg)
- push hl
- pop af
- ld hl,(hlpreg)
- ex af,af'
- exx
- ld hl,(afreg) ;restore user accumulator and flag
- push hl
- pop af
- ld bc,(bcreg) ;restore user bc
- ld de,(dereg) ;restore user de
- ld hl,(hlreg) ;restore user hl
- ld sp,(spreg) ;restore user sp
- jp jmp
- page
- ;******************************************************************************
- ;*
- ;* step: Single step (trace) routine
- ;*
- ;* Call zlen to determine where to set breakpoint.
- ;*
- ;* pass: de - current pc address
- ;*
- ;* returned: b: z - next instruction will not modify pc.
- ;* set bp at address specified by pc+length.
- ;*
- ;* b: nz - next instruction will modify pc (jumps,
- ;* calls, and returns) thus set bp at address
- ;* returned in hl.
- ;*
- ;* c: - number of bytes in current instruction.
- ;*
- ;* zlen handles secondary breakpoint to set for all conditional
- ;* call, return, and jump instructions.
- ;*
- ;* Call brk00 to set breakpoint.
- ;*
- ;* pass: b - current number of breakpoints.
- ;* hl - address at which to set breakpoint.
- ;*
- ;* entry point step: entered by user via (s)ingle step command.
- ;* entry point step40: entered by breakpoint handler - step count nz
- ;*
- ;* exit: to go routine to resume execution.
- ;*
- ;******************************************************************************
-
- step: ld a,0ffh
- ld (wflag),a ;set trace subroutine flag on
- call iedtbc ;query user for trace count
- ld hl,0001
- jp m,step40 ;null input - step count of one
- call prsr
- jp nz,e???
- ld a,(de) ;first character from parse buffer
- sub '/'
- ld (wflag),a ;may be slash - no subroutine tracing
- ld hl,00
- jr nz,step20
- ld (de),a
- ld a,(inbfnc)
- dec a
- inc hl
- jr z,step40
- dec hl
- step20: call xval ;evaluate contents of parse buffer
- jp nz,e???
- ld de,(pcreg)
- ld a,(de) ;first byte of op code at current pc
- cp 0c7h ;test for rst
- jp z,e??? ;no tracing of rsts
- step40: ld (nstep),hl ;save step count
- ld hl,sbps ;set step flag nz - trace in effect
- inc (hl)
- ld de,(pcreg) ;fetch current pc
- call zlen00 ;determine number of bytes in instruction
- inc b ;test where to set breakpoint
- djnz step50 ;nz - set at address in hl
- ex de,hl
- add hl,bc ;z - set at address pc + instruction length
- step50: ld a,(bps) ;get current number of bps
- ld b,a ;pass to set bp routine in b reg
- ex de,hl ;de - bp address to set
- call brk30
- ld hl,(pcreg) ;resume execution at next pc
- xor a
- or b
- jp nz,g100 ;nz - collision with user bp
- ex de,hl
- ld hl,sbps ;step bp set by brk30 - bump count
- inc (hl)
- ex de,hl
- jp g100
- page
- ;******************************************************************************
- ;*
- ;* asmblr: z80 assembler
- ;*
- ;******************************************************************************
-
- asmblr:
- call ilin
- jp nz,e???
- asm000: call crlf
- ld (zasmpc),hl ;save here as well
- call zasm08 ;disassemble first instruction
-
- asm005:
- ld hl,(asmbpc)
- asm010: call crlf
- call outadr ;display current assembly pc
- ld c,22 ;
- call spaces ;leave room for object code
- ld a,3
- ld hl,objbuf ;zero scratch object code buffer
- asm015: ld (hl),c
- inc hl
- dec a
- jp p,asm015
- ld (oprn01),a ;init operand key values to 0ffh
- ld (oprn02),a
- call iedtbc ;get user input
- ret m ;m - no input ends command
- call cret
- call prsr ;parse to obtain label
- ld a,(hl) ;check last character
- cp ':'
- jr nz,asm040 ;no colon found - must be op code
- ld (hl),0 ;erase colon
- ld a,(de) ;fetch first char of label from parse buffer
- cp 'A'
- jp c,asm??l ;error - first character must be alpha
- cp 'z'+1
- jp nc,asm??l ;label error
- cp 'a'
- jr nc,asm030
- cp 'Z'+1
- jp nc,asm??l
- asm030: ld hl,00
- ld (isympt),hl ;clear pointer
- call isym ;attempt to insert symbol into symbol table
- jp nz,asm??t ;error - symbol table full
- ld (isympt),hl ;save pointer to symbol value in symbol table
- call prsr ;extract opcode
- jp m,asm005 ;m - statement contains label only
- asm040: ld a,(delim) ;check delimeter
- cp ',' ;check for invalid terminator
- jp z,asm??o
- ld c,73 ;number of opcodes in table as index
- asm050: dec c
- jp m,asm??o ;opcode not found
- ld b,0
- ld hl,zopcnm ;table of opcode names
- add hl,bc
- add hl,bc ;index times four
- add hl,bc
- add hl,bc
- ld de,prsbf ;start of parse buffer
- ld b,4
- asm060: ld a,(de) ;character from parse buffer
- and a ;null?
- jr nz,asm070
- ld a,' ' ;for comparison purposes
- asm070: call ixlt ;force upper case for compare
- cp (hl)
- jr nz,asm050 ;mismatch - next opcode name
- inc de
- inc hl
- djnz asm060 ;must match all four
- ld a,(de) ;null following opcode?
- and a
- jp nz,asm??o ;error - opcode more than 4 characaters
- ld hl,ikey ;relative position in table is key value
- ld (hl),c ;save opcode key value
- call prsr ;extract first operand
- jp m,asm085 ;m - none
- call oprn ;evaluate operand
- jr nz,asm??u ;error - bad first operand
- ld de,oprn01
- call opnv ;save operand value and key
- ld a,(delim)
- cp ','
- jr nz,asm085 ;need comma for two operands
- call prsr ;extract second operand
- jp m,asm??s ;error - comma with no second operand
- cp ','
- jp z,asm??s ;illegal line termination
- call oprn ;evaluate operand
- jr nz,asm??u ;error - bad second operand
- ld de,oprn02
- call opnv ;save second operand value and key
- asm085: xor a
- ld c,a
- asm090: ld hl,zopcpt ;opcode name pointer table
- ld b,0
- add hl,bc ;index into table
- ld a,(ikey) ;fetch opcode key value
- cp (hl) ;check for match
- jr nz,asm095 ;
- inc h ;point to first operand table
- ld de,oprn01 ;address of first operand key value
- call opnm ;check validity
- jr nz,asm095 ;no match - next
- ld b,a ;save modified key value
- inc h ;point to second operand table
- ld de,oprn02 ;address of second operand key value
- call opnm
- jr z,ibld ;match - attempt final resolution
- asm095: inc c ;bump index
- jr nz,asm090 ;nz - check more
- asm??u: ld a,'U' ;error
- jp asm???
-
-
-
-
- ibld: ld hl,objbuf ;object code temp buffer
- ld e,a ;save second operand key
- ld a,(hl) ;check first byte of object buffer
- and a ;null?
- ld a,c ;instruction key to accumulator regardless
- ld c,e ;save second operand modified key
- jr z,ibld00 ;z - not ix or iy instruction
- inc hl ;point to byte two of object code
- ibld00: cp 40h
- jr c,ibld55 ;c - 8080 instruction
- cp 0a0h
- jr nc,ibld10 ;nc - not ed instruction
- ld (hl),0edh ;init byte one of object code
- inc hl
- cp 80h ;check which ed instruction we have
- jr c,ibld55 ;c - this is exact object byte
- add a,20h ;add bias to obtain object byte
- jr ibld55
- ibld10: cp 0e0h
- jr nc,ibld20
- add a,20h ;8080 type - range 0c0h to 0ffh
- jr ibld55 ;object byte built
- ibld20: cp 0e8h
- jr c,ibld50 ;8 bit reg-reg arithmetic or logic
- cp 0f7h ;check for halt disguised as ld (hl),(hl)
- jr nz,ibld30
- ld a,76h ;halt object code
- jr ibld55
- ibld30: cp 0f8h
- jr nc,ibld50 ;8 bit reg-reg load
- ld d,a ;temp save instruction key value
- ld a,(objbuf)
- and a ;check for previously stored first object byte
- ld a,d
- ld (hl),0cbh ;init byte regardless
- inc hl
- jr z,ibld40 ;z - not ix or iy instruction
- inc hl ;bump object code pointer - this is four byter
- ibld40: add a,0a8h ;add bias for comparison purposes
- cp 98h
- jr c,ibld50 ;c - shift or rotate instruction
- rrca
- rrca
- and 0c0h ;this is skeleton for bit instuctions
- jr ibld55
- ibld50: add a,a ;form skeleton
- add a,a
- add a,a
- add a,80h
- ibld55: ld (hl),a ;store object byte
- xor a
- or c ;second operand need more processing?
- ld de,oprn02
- call nz,rslv ;resolve second operand
- jp nz,asm??v ;error - invalid operand size
- ld de,oprn01
- ld a,b
- and a ;first operand resolved?
- call nz,rslv ;more work to do
- jp nz,asm??v ;error - invalid operand size
- ld a,(ikey)
- sub 67 ;org directive?
- jr nz,ibld60
- ld d,(hl)
- dec hl
- ld e,(hl)
- ex de,hl
- jp asm000 ;z - org directive
- ibld60: ld de,objbuf
- jr c,ibld70 ;c - instruction nc - directive
- ld b,a ;number of bytes for defb or defw or ddb
- inc de ;point past erroneous assembled opcode
- inc de
- sub 3 ;test for ddb
- jr c,ibld75 ;c - must be defb or defw
- dec a
- jr nz,ibld65 ;nz - must be ddb
- ld d,(hl) ;must be equ
- dec hl
- ld e,(hl)
- ld hl,(isympt) ;fetch pointer to entry in symbol table
- ld a,h
- or l
- jp z,asm??u ;error - no label on equ statement
- ld (hl),d
- dec hl
- ld (hl),e ;store value of symbol in symbol table
- ld c,6
- call spaces
- ld a,d
- call othxsp
- ld a,e
- call othxsp
- jp asm005 ;ready for next input
- ibld65: dec b ;set count of object bytes to 2
- ld c,(hl) ;exchange hi and lo order bytes for ddb
- dec hl
- ld a,(hl)
- ld (hl),c ;new hi order
- inc hl
- ld (hl),a ;new hi order replaces old lo order
- jr ibld75
- ibld70: call zlen00 ;compute length of instruction in bytes
- ld b,c ;b - number of bytes of object code
- ibld75: ld hl,(asmbpc)
- call outadr ;re-display current location counter
- ibld80: ld a,(de) ;move from scratch object buffer
- ld (hl),a ;into address pointed to by location counter
- inc hl
- inc de
- call othxsp ;display each object code byte
- djnz ibld80
- ibld90: ld (asmbpc),hl
- jp asm005 ;next input from user
-
-
-
-
- opnm: ld a,(de) ;key value computed by operand routine
- xor (hl) ;compare with table operand table entry
- ret z ;true match of operand key values
- xor (hl) ;restore
- add a,a ;86 all no operand key values (0ffh)
- ret m
- ld a,(hl) ;fetch table entry
- and 7fh ;sans paren flag for comparison purposes
- cp 1bh ;check table entry 8 bit - 16 bit - $ rel ?
- jr c,opnm00 ;c - none of the above
- ld a,(de) ;fetch computed key
- xor (hl) ;compare with paren flags
- ret m ;error - paren mismatch
- ld a,(de) ;fetch key once more
- and 7fh ;remove paren flag
- cp 17h ;computed as 8 bit - 16 bit - $ rel?
- jr z,opnm40 ;so far so good
- ret ;
- opnm00: cp 19h ;check for 8 bit reg
- jr nc,opnm20 ;8 bit register match
- cp 18h ;table says must be hl - ix - iy
- ret nz ;computed key disagrees
- ld a,(de) ;fetch computed key
- and 7 ;computed as hl - ix - iy ?
- ret nz ;no
- opnm10: ld a,(de) ;fetch computed key
- xor (hl)
- ret m ;error - paren mismatch on hl - ix - iy
- jr opnm40
- opnm20: ld a,(de) ;fetch computed key of 8 bit reg
- and a ;
- jr nz,opnm30 ;nz - not (hl)
- dec a ;error - 8 bit (hl) missing parens
- ret
- opnm30: cp 8 ;test user entered valid 8 bit reg
- jr c,opnm40 ;c - ok
- and a ;test if no carry caused by paren flag
- ret p ;error - this is not 8 bit reg with parens
- and 7 ;psuedo 8 bit reg: (hl) (ix) (iy)?
- ret nz ;no
- opnm40: ld a,(hl) ;fetch table entry
- and 7fh
- sub 18h ;make values 18 thru 1f relative zero
- cp a ;zero means match
- ret
-
- rslv: dec a
- jr z,rslv00 ;z - 8 bit reg (bits 0-2 of object byte)
- dec a
- jr nz,rslv20 ;nz - not 8 bit reg (bits 3-5 of object byte)
- dec a ;make neg to indicate shift left required
- rslv00: ld c,a
- ld a,(de) ;fetch computed operand key
- and 07 ;lo three bits specify reg
- xor 6 ;create true object code bits
- inc c ;test if bits 0-2 or bits 3-5
- jr nz,rslv10 ;nz - 0 thru 2
- add a,a
- add a,a
- add a,a
- rslv10: or (hl) ;or with skeleton
- ld (hl),a ;into scratch object buffer
- cp a ;set zero - no error
- ret
- rslv20: inc de ;point to low order of operand value
- ld c,(hl) ;c - current skeleton (if needed)
- inc hl ;bump object code buffer pointer
- dec a
- jr nz,rslv30 ;nz - not relative jump
- ex de,hl ;save object code pointer in de
- ld a,(hl)
- inc hl
- ld h,(hl)
- ld l,a ;hl - operand value computed by xval
- ld a,b
- ld bc,(asmbpc) ;current location counter
- inc bc
- inc bc
- sbc hl,bc ;calculate displacement from current counter
- ex de,hl ;de - displacement hl - object code pointer
- ld b,a ;restore b reg
- ld a,e ;lo order displacement
- inc d ;test hi order
- jr z,rslv25 ;must have been ff (backward displacement)
- dec d
- ret nz ;error - hi order not zero or ff
- cpl ;set sign bit for valid forward displacement
- rslv25: xor 80h ;toggle sign bit
- ret m ;error - sign bit disagrees with upper byte
- ld (hl),e ;store displacement object byte
- cp a ;set zero flag - no errors
- ret
- rslv30: dec a
- jr nz,rslv40 ;nz - not 8 bit immediate
- ld a,36h ;test for reg indirect - (hl),nn
- cp c
- jr nz,rslv35
- ld a,(objbuf) ;test first object byte
- cp c
- jr z,rslv35 ;z - (hl),nn
- inc hl ;must be (ix+index),nn or (iy+index),nn
- rslv35: ld a,(de) ;move lo order operand value to object buffer
- ld (hl),a
- inc de
- ld a,(de) ;test hi order
- and a ;
- ret z ;z - must be 0 thru +255
- inc a ;error if not -1 thru -256
- ret
- rslv40: dec a
- jr nz,rslv50 ;nz - not 16 bit operand
- ld a,(de) ;move both bytes of operand to object buffer
- ld (hl),a
- inc hl
- inc de
- ld a,(de) ;byte two
- ld (hl),a
- cp a ;set zero flag - no errors of course
- ret
- rslv50: dec a ;test restart instruction or bit number
- jr nz,rslv60 ;nz - bit or interrupt mode number
- ld a,(de) ;check restart value specified
- and 0c7h ;betweed 0 and 38h?
- ret nz ;error
- ld a,(de) ;fetch lo order operand value
- or 0c7h ;or with instruction skeleton
- dec hl
- ld (hl),a ;rewind object code pointer
- inc de
- ld a,(de) ;check hi order operand value
- and a ;error if not zero
- ret
- rslv60: dec hl ;rewind object code buffer pointer
- ld a,(de)
- and 0f8h ;ensure bit number in range 0 - 7
- ret nz ;error
- ld a,(ikey) ;fetch opcode key value
- sub 13h ;is this bit number of interrupt mode number?
- ld a,(de) ;fetch operand value regardless
- jr nz,rslv70 ;nz - bit number
- ld (hl),46h
- and 03 ;im 0?
- ret z
- ld (hl),56h
- dec a ;im 1?
- ret z
- ld (hl),5eh
- dec a ;error if not im 2
- ret
- rslv70: add a,a ;shift bit number left three
- add a,a
- add a,a
- or (hl) ;or with skeleton
- ld (hl),a
- cp a ;indicate no error
- ret
-
-
-
- oprn: ld bc,22 ;count of reserved operand
- oprn00: ld de,prsbf ;buffer contains operand
- ld a,(hl) ;last character of operand in parse buffer
- sub ')'
- jr nz,oprn20 ;not paren
- ld (hl),a ;remove trailing paren - replace with null
- ld a,(de) ;check first character of parse buffer
- sub '('
- ret nz ;error - unbalanced parens
- ld (de),a ;remove leading paren - replace with null
- inc de ;point to next character in parse buffer
- oprn20: ld hl,zopnm ;index into reserved operand name table
- ld a,c
- add a,a ;index times two
- add a,l
- ld l,a
- jr nc,oprn25
- inc h
- oprn25: ld a,(de) ;from parse buffer
- call ixlt ;translate to upper case for compare
- cp (hl) ;versus table entry
- inc de
- jr nz,oprn70 ;no match - check next
- ld a,(de) ;check second character
- call ixlt ;translate to upper case
- and a ;if null - this is one character reg name
- jr nz,oprn30
- ld a,' ' ;for comparison purposes
- oprn30: inc hl ;bump table pointer
- sub (hl)
- jr nz,oprn70 ;no match - check next
- inc de ;have match - bump buffer pointer
- or b ;
- ret nz ;nz - mreg calling
- ld a,c ;check index value
- and 07
- jr nz,oprn80 ;not hl ix iy - check for residue
- ld a,(de)
- call oprtor ;check for expression operator
- jr nz,oprn85 ;no operator but not end of operand
- ld a,ix.. or iy.. ;special ix iy hl processing
- and c ;test for index reg
- jr z,oprn35 ;z - must be hl
- and 10h ;transform index into 0ddh or ofdh
- add a,a
- add a,0ddh ;a - first byte of index reg opcode
- oprn35: ld c,a ;temp save first object byte
- ld hl,objbuf
- xor (hl)
- jr z,oprn40 ;z - first operand matches second
- cp c
- ret nz ;illegal ix iy hl combination
- ld a,(oprn01)
- and a ;test if index reg was first operand
- jr nz,oprn40
- dec a ;error - hl illegal as second
- ret
-
-
- oprn40: ld (hl),c ;init first byte of object code
- ld a,(prsbf)
- and a ;check for previously removed parens
- ld a,c
- ld c,0
- jr nz,oprn80 ;no parens - no indexed displacement
- and a ;check for ix or iy indexed instruction
- jr z,oprn80 ;z - not index reg instruction
-
- sbc hl,hl ;clear hl
- ld a,(de) ;index reg displacement processing
- and a ;test for default displacement
- call nz,xval ;not zero - evaluate
- jr nz,oprn85 ;nz - displacement in error
- ld c,00
- ld a,l
- ld (objbuf+2),a ;displacement always third byte
- inc h ;check upper byte of index value
- jr z,oprn50 ;must have been 0ffh
- dec h
- ret nz ;error - index not -128 to +127
- cpl
- oprn50: xor 80h ;check sign bit
- ret m ;bit on - index out of range
- cp a ;no error - set zero flag
- ret
- oprn70: dec c ;decrement reserved operand table index
- jp m,oprn85 ;m - not a reserved operand
- dec de ;rewind parse buffer pointer
- jp oprn20 ;next table entry
- oprn80: ld a,(de) ;check for end of parse buffer
- and a
- ret z ;found end of line null
- oprn85: ld de,prsbf ;rewind to start of input
- xor a
- or b
- ret nz ;nz - this was mreg calling
- sbc hl,hl ;clear hl
- call xval ;evaluate operand
- ld c,17h ;assume numeric operand found
- ret
-
-
- xval: ld a,(de) ;check first char of parse buffer
- and a
- jr nz,xval00
- inc de ;bump past previously removed paren
- xval00: ld (mexp),hl ;init expression accumulator
- xor a
- ld (base10),a ;clear upper digit decimal accumulator
- sbc hl,hl ;clear hl
- ld (fndsym),hl ;clear symbol found flag
- ld (pass2),hl
- xval05: ld a,(de) ;char from parse buffer
- call ixlt ;translate to upper case
- ld c,a ;save character
- inc de ;bump parse buffer pointer
- cp '0' ;check for valid ascii hex digit
- jr c,xval25
- cp ':'
- jr c,xval15
- cp 'A'
- jr c,xval25
- cp 'G'
- jr nc,xval25
- xor a ;check number entered flag (b reg sign bit)
- or b
- jp m,xval10 ;m - this was not first char
- ld a,(symflg) ;check if symbol table present in memory
- and a
- xval10: ld a,c ;input character back to accumulator
- jp p,xval25 ;p - have symbol table or invalid hex digit
- sub 7
- xval15: sub '0' ;ascii hex to hex nibble
- add a,a ;shift left five - hi bit of nibble to carry
- add a,a
- add a,a
- add a,a
- add a,a
- ld c,4 ;loop count
- xval20: adc hl,hl ;hl left into carry - rotate carry into hl
- adc a,a ;next bit of nibble into carry
- dec c
- jr nz,xval20
- ld (base10),a ;store what was shifted left out of hl
- ld a,80h ;set sign of b - number entered flag
- or b
- ld b,a
- jr xval05 ;next character
-
- xval25: call oprtor ;have expression operator?
- jr z,xval30
- ld a,(pass2)
- and a
- ret nz
- ld a,(pass2+1)
- and a
- jp z,xval35
- ret
-
- xval30: xor a
- or b ;check number entered flag
- ld a,c ;restore unmodified input character to a
- jp nz,xval90 ;nz - take care of previous operator
- and a ;end of line null?
- ret z ;
- ld b,c ;this operator was first char of parse buffer
- jr xval05 ;extract what follows this leading operator
-
- xval35: ld a,c ;recover character
- cp '#' ;decimal processing?
- jr nz,xval50 ;nz - not decimal
- ld a,b ;check number entered flag
- xor 80h ;toggle
- ret m ;error - pound sign with no number
- ld b,a
- push bc
- push de
- ex de,hl ;save hex number in de
- ld hl,base10
- ld a,6
- cp (hl) ;check ten thousands digit
- jr c,xval40 ;error - obviously greater than 65535
- rrd ;nibble to accumulator
- inc hl
- ld (hl),d ;store hex number in temp buffer
- inc hl
- ld (hl),e ;lo order hex number
- dec hl ;point back to upper byte
- ld e,a
- xor a
- ld d,a ;de - hex nibble
- call bcdx ;convert hi order byte
- jr nz,xval40 ;nz - error detected during conversion
- inc hl ;bump to lo byte to convert
- call bcdx
- ex de,hl ;hl - converted value
- xval40: pop de
- pop bc
- jr z,xval65 ;z - no errors detected
- ret
-
-
-
- xval50: cp quote ;ascii literal processing
- jr nz,xval60 ;nz - not quote
- ex de,hl ;
- ld e,(hl) ;fetch literal from buffer
- inc hl
- cp (hl) ;trailing quote found?
- jr z,xval55 ;found
- ld d,e ;make literal just fetch hi order of operand
- ld e,(hl) ;fetch new literal as lo order
- inc hl
- cp (hl) ;trailing quote?
- ret nz ;error - more than two chars between quotes
- xval55: ex de,hl ;de - parse buffer ptr hl - operand
- inc de ;bump past trailing quote
- jr xval65
-
-
- xval60: dec de ;point to start of operand in parse buffer
- ld (pass2),de
- call fsym ;search symbol table
- jp z,xval62 ;symbol found
- ld a,(de)
- inc de
- cp '$' ;check for pc relative expression
- jp nz,xval61
- ld hl,(asmbpc) ;current location value is expression value
- jr xval65
- ;symbol not found - retry evaluation process
- ;with pass2 flag set. now token must be a
- ;valid hex digit or error
- xval61: ld de,(pass2)
- ld a,b
- or 80h ;set sign in b - valid digit detected which
- ;tells xval this must be hex number
- ld b,a
- sbc hl,hl ;clear hex number accumulator
- jp xval05
- xval62: ld a,(maxlen) ;point to last byte of sym table entry
- or l
- ld l,a
- ld a,(hl) ;hi order symbol address
- dec hl
- ld l,(hl) ;lo order
- ld h,a
- xval65: ld a,b ;check number entered flag
- and a
- ret m ;error - numbers entered previous to symbol
- xor 80h ;toggle flag
- ld b,a
- ld a,(de) ;check char following symbol name in buffer
- ld c,a ;make it new current character
- inc de
- jp xval30
-
-
-
-
-
- xval90: ld c,a ;temp save operator
- ld a,80h ;toggle number entered flag
- xor b
- ret m ;return nz - consecutive operators
- ld b,c ;new on deck operator
- cp '-' ;test last operator
- push de ;save buffer pointer
- jr nz,xval95 ;nz - addition
- ex de,hl
- sbc hl,hl ;clear
- sbc hl,de ;force current value neg by subtraction from 0
- xval95: ex de,hl
- ld hl,(mexp) ;fetch accumulated operand total
- add hl,de ;add in current
- pop de ;restore buffer pointer
- ld a,b ;check operator that got us here
- and a ;end of line null?
- jp nz,xval00 ;no -
- ret ;operand processing complete
-
-
-
- fsym:
- ld hl,(06) ;de - buffer hl - symbol table
- fsym00: ld a,(maxlen)
- and l
- ld c,a
- ld a,b ;temp save
- ld b,0
- ex de,hl ;de - symbol table ptr hl - parse buffer
- sbc hl,bc ;rewind parse buffer to start of symbol
- ex de,hl ;de - parse buffer hl - symbol table pointer
- ld b,a ;restore b reg
- ld a,(maxlen)
- or l
- ld l,a
- inc hl ;next block of symbol table
- ld a,(hl) ;first character of symbol name
- dec a
- ret m ;end of table
- ld a,(maxlen)
- dec a
- ld c,a ;chars per symbol
- fsym10: ld a,(de) ;fetch char from buffer
- call oprtor
- jr nz,fsym20 ;nz - not operator or end of line null
- ld a,(hl)
- and a ;null means end of symbol name in symbol table
- jr nz,fsym00
- ld (fndsym),hl ;set symbol found flag nz -
- ret
- fsym20: cp (hl)
- jr nz,fsym00
- inc hl
- inc de
- dec c
- jr nz,fsym10
- ld (fndsym),hl ;set symbol found flag nz -
- fsym30: ld a,(de)
- call oprtor
- ret z
- inc de
- jr fsym30
-
-
-
- isym: call fsym ;search for symbol in table
- jr z,isym00 ;z - symbol found
- ld a,(hl) ;test for empty slot in table
- and a
- ret nz ;symbol table full
- ld (symflg),a ;indicate non-empty symbol table
- isym00: ld a,(maxlen) ;rewind point to start of table entry
- ld c,a
- cpl
- and l
- ld l,a
- ex de,hl ;de - pointer to start of symbol
- ld hl,prsbf
- ld b,0 ;move symbol from parse buffer to table
- dec c
- ldir
- ld hl,(asmbpc) ;fetch value of symbol
- ex de,hl ;hl - pointer to address storage
- ld (hl),e ;lo order current location into table
- inc hl
- ld (hl),d ;upper byte
- xor a
- ret
- page
- ;******************************************************************************
- ;*
- ;* prsr: command line parse routine
- ;*
- ;* prsr will extract one argument from the input buffer (inbf) and
- ;* write it into the parse buffer (prsbf). an argument is treated
- ;* as starting with the first non-delimeter character encountered
- ;* in the input buffer and ends with the next delimeter found.
- ;* all intervening characters between the two delimeters are
- ;* treated as the argument and are moved to prsbf.
- ;*
- ;* as each character is extracted from inbf a zero is written back
- ;* to replace it. thus a program which needs to extract multiple args
- ;* need not save pointers in between calls since prsr is trained
- ;* to strip leading delimeters while looking for the start of an
- ;* argument:
- ;*
- ;* delimeters: null, space, comma
- ;*
- ;* exit: de - starting address of parse buffer
- ;* b - sign bit: set if unbalanced parens, else sign reset
- ;* bits 6-0: number of chars in the parse buffer
- ;* a - actual delimter char which caused to terminate
- ;* f - zero flag set if no error
- ;* quoflg - set equal to ascii quote if at leeat one quote found
- ;*
- ;* error exit: f - zero flag reset
- ;*
- ;******************************************************************************
-
- prsr: xor a
- ld (quoflg),a ;clear quote flag
- ld hl,prsbf ;start of parser scratch buffer
- ld b,prsbfz ;buffer size
- ld c,b
- prsr10: ld (hl),0 ;clear parse buffer to nulls
- inc hl
- djnz prsr10
- ld hl,prsbf ;start of parse buffer
- ld de,inbf ;start of input buffer
- ld c,inbfl ;max size of input buffer
- prsr20: ld a,(de) ;from input buffer
- ex de,hl
- ld (hl),0 ;erase as we pick from input buffer
- ex de,hl
- dec c ;decrement buffer size tally
- ret m ;error - end of input buffer reached
- inc de ;bump input buffer pointer
- call zdlm00 ;check for delimeter
- jr z,prsr20 ;delimeter found - continue search
- ld (parenf),a
- ld c,nprsbf-prsbf ;parse buffer size
- prsr30: ld (hl),a
- and a
- jr z,prsr60 ;end of line null always ends parse
- cp quote ;quote?
- jr nz,prsr50
- ld (quoflg),a
- ld a,b ;quote found - toggle flag
- xor 80h
- ld b,a
- prsr50: dec c ;decrement buffer size tally
- ret m ;error - end of parse buffer reached
- ld a,(de) ;next char from input buffer
- ex de,hl
- ld (hl),0 ;clear as we remove
- ex de,hl
- inc de
- inc b ;bumping character count tests quote flag
- call p,zdlm ;only look for delimeters if quote flag off
- inc hl ;bump parse buffer pointer
- jr nz,prsr30
- dec hl
- prsr60: ld de,prsbf ;return pointing to start of parse buffer
- ld (delim),a
- ret ;zero flag set - no errors
-
-
-
- asm??l: ld a,'L'
- jr asm???
- asm??o: ld a,'O'
- jr asm???
- asm??p: ld a,'P'
- jr asm???
- asm??s: ld a,'S'
- jr asm???
- asm??t: ld a,'T'
- jr asm???
- asm??v: ld a,'V'
-
- asm???: ld (asmflg),a
- call cret
- ld hl,(asmbpc)
- call outadr
- ld de,m????
- call print
- jp asm010
-
-
- zdlm: cp ','
- ret z
- zdlm00: and a
- ret z
- cp tab
- ret z
- cp ' '
- ret
-
- oprtor: cp '+'
- ret z
- cp '-'
- ret z
- and a
- ret
-
-
-
- opnv: ex de,hl ;de - operand value hl - operand key storage
- ld a,(prsbf) ;check first byte of parse buffer
- and a ;if null - paren was removed
- ld a,c ;key value to accumulator
- jr nz,opnv00 ;nz - no paren
- or 80h ;found null - set paren flag
- opnv00: ld (hl),a ;store key value
- inc hl
- ld (hl),e ;lo order operand value
- inc hl
- ld (hl),d ;hi order
- ret
-
-
- page
- ;******************************************************************************
- ;*
- ;* zlen: determine the number of bytes in a z80 instruction
- ;*
- ;*
- ;* entry point zlen00: used to return instruction length.
- ;*
- ;* de: address of instruction
- ;*
- ;* return: b: z - inline instruction (next pc will be pc plus length)
- ;* nz - pc modifying instruction such as call, jump, or ret
- ;* (see hl below)
- ;* c: number of bytes in this instruction.
- ;* de: preserved
- ;* hl: next pc following the execution of the instruction
- ;* pointed to by de.
- ;*
- ;******************************************************************************
-
- zlen00: ld a,(de) ;fetch first byte of op code
- cp 0cbh ;test for shift/bit manipulation instruction
- ld bc,02
- ret z ;10-4 this is a cb and length is always 2
- cp 0edh ;test for fast eddie
- jr nz,zlen15 ;
- inc de ;fetch byte two of ed instruction
- ld a,(de)
- dec de ;restore pointer
- ld hl,z80ed ;ed four byter table
- ld c,z80edl ;length
- cpir
- ld c,4 ;assume ed four byter
- ret z ;correct assumption
- ld c,2 ;set length for return - if not 2 must be 4
- cp 45h ;test for retn
- jr z,zlen10
- cp 4dh ;test for reti
- ret nz ;non-pc modifying two byte ed
- zlen10: ld a,0c9h ;treat as ordinary return instruction
- jp zlen80
- zlen15: cp 0ddh ;check for dd and fd index reg instructions
- jr z,zlen20
- cp 0fdh
- jr nz,zlen40
- zlen20: inc de ;fetch byte two of index reg instruction
- ld a,(de)
- dec de ;restore pointer
- cp 0e9h ;check for reg indirect jump
- jr nz,zlen30 ;
- inc b ;reg indirect jump - set pc modified flag nz
- ld a,(de) ;recheck for ix or iy
- ld hl,(ixreg) ;assume ix
- cp 0ddh
- ret z ;correct assumption
- ld hl,(iyreg)
- ret
- zlen30: ld hl,z80fd ;check for dd or fd two byter
- ld c,z80fdl
- cpir
- ld c,2 ;assume two
- ret z
- ld hl,z80f4 ;not two - try four
- ld c,z80f4l
- cpir
- ld c,4 ;assume four
- ret z ;correct assumption
- dec c ;must be three
- ret
- zlen40: and 0c7h ;check for 8 bit immediate load
- cp 06
- ld c,2 ;assume so
- ret z
- dec c ;assume one byte op code
- ld a,(de)
- cp 3fh
- jr c,zlen50 ;opcodes 0 - 3f require further investigation
- cp 0c0h ;8 bit reg-reg loads and arithmetics do not
- ret c
- zlen50: ld hl,z803 ;check for three byter
- ld c,z803l
- cpir
- jr nz,zlen60 ;nz - not three
- ld hl,z803s ;established three byter - test conditional
- ld c,z803cl
- cpir
- ld c,3 ;set length
- ret nz ;nz - three byte inline instruction
- ld hl,z803s
- ld c,z803sl ;now weed out jumps from calls
- cpir
- ld c,3
- ld b,c ;set pc modified flag - we have call or jump
- ex de,hl
- inc hl
- ld e,(hl)
- inc hl
- ld d,(hl) ;de - address from instruction
- ex de,hl
- dec de
- dec de ;restore instruction pointer
- jr z,zlen55 ;z - this is a call
- cp jp ;test for unconditional jump
- jr nz,zlen85
- ret
- zlen55: ld a,(wflag) ;test for no subroutine trace flag
- and a ;zero means no sub tracing
- ld b,a ;clear for return - if sub trace off
- ret z ;subroutine trace off - return with b reg 00
- ;so bp is set at next inline instruction
- dec b
- jr nz,zlen58
- ld a,b
- or h
- ret z
- zlen58: ld a,(de) ;recover call object byte
- ld b,c ;set nz - pc modifying instruction
- cp 0cdh ;unconditional call??
- jr nz,zlen85 ;zlen85 - set secondary breakpoint if tracing
- ret
-
- zlen60: ld hl,z802
- ld c,z802l ;test for two byter
- cpir
- jr nz,zlen70 ;not two
- ld hl,z802c ;test for relative jump
- ld c,z802cl
- cpir
- ld c,2 ;in any case length is two
- ret nz ;nz - not relative jump
- ld h,b ;clear
- inc b ;set pc modified flag nz
- inc de ;fetch relative displacement
- ld a,(de)
- ld l,a
- add a,a ;test forward or backward
- jr nc,zlen65 ;p - forward
- dec h ;set hl negative
- zlen65: add hl,de ;compute distance from instruction
- inc hl ;adjust for built in bias
- dec de ;restore pointer
- ld a,(de) ;fetch first byte of instruction
- cp 18h ;uncondtional jump?
- jr nz,zlen85 ;conditional - set secondary bp if tracing
- ret
- zlen70: ld hl,z801 ;check for return instruction
- ld c,z801l
- cpir
- ld c,1 ;length must be 1 in any case
- ret nz
- cp 0e9h
- jr nz,zlen80 ;nz - not jp (hl)
- inc b ;set pc modified flag
- ld hl,(hlreg) ;next pc contained in hlreg
- ret
- zlen80: ld hl,(spreg) ;return instructions hide next pc in stack
- ld b,(hl)
- inc hl
- ld h,(hl)
- ld l,b ;hl - return address removed from stack
- ld b,c ;set b nz - pc modification flag
- cp 0c9h
- ret z ;unconditional return
- zlen85: ld a,(sbps) ;count of special step breakpoints
- and a ;test for zero
- ret z ;zero - monitor is not tracing
- ld a,(bps) ;fetch number of bps currently in effect
- ld b,a ;pass to set breakpoint routine in b reg
- ex de,hl ;de - bp to set
- call brk30 ;set conditional breakpoint
- xor a
- or b
- ld b,0
- ld de,(pcreg) ;for setting inline bp - condition not m
- ret nz ;nz - collision with user bp
- ld hl,sbps
- inc (hl) ;bump count of step bps
- ret
- page
- ;******************************************************************************
- ;*
- ;* pswDsp: display current state of flag register
- ;*
- ;* pswbit: table of bit masks with which to test f reg.
- ;* two byte entry per bit (sign, zero, carry, parity).
- ;*
- ;* pswmap - table of offsets into operand name table featuring a
- ;* two byte entry for each flag bit.
- ;* bit 4 (unused by z80) from pswbit entry is on/off flag
- ;* lo bytes are the off states (p nz nc po).
- ;* hi bytes are the on states (m z c pe).
- ;*
- ;* - current state of flag register is displayed
- ;* - user queried for changes
- ;* - input is parsed and tested for valid flag reg mnemonics
- ;* - if valid mnemonic found flag bit is set or reset accordingly
- ;*
- ;* exit: to z8e for next command
- ;*
- ;******************************************************************************
-
- pswDsp: ld de,3
- ld b,0 ;+ eg 3.3.5a
- psw00: ld hl,pswbit ;table of bit mask for flags
- add hl,de ;
- add hl,de ;index times two
- ld a,e
- neg ;now calculate index into pswmap
- add a,3
- add a,a
- ld c,a
- ld a,(freg) ;fetch current flag of user
- and 0f7h
- and (hl) ;unused bit in flag - ensure it's off
- ld hl,pswmap
- add hl,bc ;pointer to mnemonic is 8 bytes away
- jr z,psw10 ;this is an off bit (nz nc p po)
- inc hl ;on
- psw10: ld c,(hl) ;fetch index into operand name table
- ld hl,zopnm
- add hl,bc ;two bytes per table entry
- add hl,bc
- ld c,2 ;print both chars of mnemonic name
- call printb
- call space
- dec e ;do all four flag bits
- jp p,psw00
- call crlf
- ld a,(lcmd)
-
- ; cp 'J' ;- eg 3.3.5a
- ; ret z ;-
- cp 'P' ;+ Routine can now be called from
- ret nz ;+ elsewhere
-
- call space5
- psw50: call iedtbc
- ret m ;no input
- psw55: call prsr
- ret nz ;parse error - end command
- ld bc,116h ;
- call oprn20 ;check validity of this token
- ld a,c
- ld bc,pswcnt ;number of flag reg mnemonics
- ld hl,pswmap
- cpir ;check table
- jp nz,e??? ;error - nmemonic not found
- ld hl,pswbit ;bit mask table
- add hl,bc
- ld a,(hl) ;fetch mask
- ex de,hl ;
- ld hl,freg ;de - mask ptr hl - user flag ptr
- and 08 ;bit says turn on or off
- ld a,(de) ;new copy of mask
- jr nz,psw60 ;nz - turn on
- cpl
- and (hl) ;and with current user flag
- ld (hl),a ;return flag reg with bit now off
- jr psw55 ;check for more input
- psw60: and 0f7h ;turn off on/off flag (bit 4)
- or (hl)
- ld (hl),a ;now turn on specified bit
- jr psw55
- page
- ;******************************************************************************
- ;*
- ;* movb: move memory
- ;*
- ;* call bcde to fetch destination block address and byte count
- ;* call prsr
- ;* check for head to head or tail to tail move
- ;*
- ;* exit: to z8e for next command
- ;*
- ;******************************************************************************
-
- movb: call bcde ;bc - byte count de - destination hl - source
- jp nz,e??? ;input error ends command
- xor a
- sbc hl,de
- adc a,a
- add hl,de
- add hl,bc
- dec hl
- ex de,hl ;de - address of last byte of source block
- sbc hl,de
- adc a,a
- add hl,de ;hl - original destination address
- ex de,hl
- cp 3
- jr nz,movb00 ;head to head
- ex de,hl
- add hl,bc
- dec hl
- ex de,hl
- lddr
- ret
- movb00: inc hl
- and a
- sbc hl,bc
- ldir
- ret
- page
- ;******************************************************************************
- ;*
- ;* yfil: fill memory
- ;*
- ;* call bcde to get byte count, starting address, and fill byte
- ;*
- ;* exit: to z8e for next command
- ;*
- ;******************************************************************************
-
- yfil: call bcde ;bc - byte count de - fill byte hl - block
- jp nz,e??? ;input error ends command
- ex de,hl
- yfil00: ld hl,argbf
- ld a,(argbc)
- yfil10: ldi
- inc b
- djnz yfil20
- inc c
- dec c
- ret z
- yfil20: dec a
- jr nz,yfil10
- jr yfil00
- page
- ;*********************************************************************
- ;
- ; CUSER Change user routine EG 5 Jan 88
- ;
- ; 10 Jan 88 Added check for bad args
- ;
- ; Uses '>' as command
- ;
- ;*********************************************************************
-
- cuser: call iedtbc
- ret m
- call iarg ; gets user in HL as a hex no
- jp nz,e??? ; don't allow bad (would go to user 0)
- ld a,h
- or a
- jp nz,e??? ; 2 - byte user number?
- ld a,l
- cp 10h
- jr c,cusok ; you can enter user in hex or decimal with '#'
- sub 6 ; else convert to decimal
- cp 10h ; see if still too big
- jp nc,e???
- cusok: ld c,32
- ld e,a
- jp bdos ; change user
-
- ;*******************************************************************
- ;
- ; QEVAL - expression evaluator EG 10 Jan 88
- ;
- ; Uses '?' as command
- ;
- ;*******************************************************************
- qeval: call iedtbc ; get input
- ret m ; none
- call iarg ; Z8E does all the real work
- jp nz,e??? ; check for valid arg
- call crlf
- ld a,h ; see if 1 byte
- or a
- jr nz,qev01 ; 2-byte number
- ld a,l
- call outhex ; hex byte
- ld a,l
- cp 7fh ; see if printable
- ret nc
- cp ' '
- ret c
- ld c,3
- call spaces ; even up with spaces
- ld a,27h ; quote
- call ttyo
- ld a,l ; show char
- call ttyo
- ld a,27h
- jp ttyo
- qev01: jp outadr ; output 2-byte result
-
- ;***********************************************************
- ;
- ; GADR - Get program addr data EG 20 Feb 88
- ;
- ; Uses '#' as command
- ;
- ; Deleted 5/Jan/89 by jrs - unnecessary as L command
- ; with no file name (now) does the same thing.
- ;
- ;************************************************************
- ;gadr: ld hl,(loadn)
- ; ld c,10 ; out-of-memory flag
- ; jp lbin22
- page
- ;------------------------------------------------------------------------------
- ;
- ; Initialise default FCB fields and command line (16 may 87 jrs)
- ;
- ; Calls iedtbc to get command tail
- ; lfcb twice to extract file names
- ;
- ; exit: FCB name fields at 5Ch and 6Ch initialised
- ; Command tail set up at 80h
- ;
- ;------------------------------------------------------------------------------
-
- ifcb: ;(Condensed, improved version - jrs 27 Dec 88)
-
- call iedtbc ;Get command tail
- dec hl ;Point at input buffer length
- push hl ;Save input buffer pointer
- ld hl,fcb5c ;Zero out the default FCB
- ld b,32
- ifcb00: ld (hl),0
- inc hl
- djnz ifcb00
- ld l,fcb5c+1 ;Blank out the two file names
- call iblank
- ld l,fcb5c+17
- call iblank
- pop hl ;Get input buffer pointer
- ld de,80h ;Destination is command line buffer
- ld b,(hl) ;Get input buffer length
- ld a,b ;Load length ready to put in command buffer
- inc b ;Account for the length byte itself
- ifcb02:
- ld (de),a ;Store character in command buffer
- inc de ;Increment pointers
- inc hl
- ld a,(hl) ;Load character from input buffer
- call ixlt ;Translate to upper case
- djnz ifcb02 ;Loop until all copied
- xor a ;Terminate the command buffer properly
- ld (de),a
- call lfcb ;Get a file name (if any)
- jr nz,ifcb12 ;Skip if error
- ld de,fcb5c ;Copy FCB to default FCB at 5ch
- ld hl,fcb
- ld bc,12 ;(only move 12 bytes)
- ldir
- ifcb12:
- call lfcb ;Do second file name (if any)
- ret nz ;Exit now if error
- ld hl,fcb ;Copy file name part of FCB to
- ld de,fcb5c+16 ; second segment of default FCB
- ld bc,12
- ldir
- ret
-
- iblank: ;Blank out 11 bytes at HL
- ld b,11
- ibl00: ld (hl),' '
- inc hl
- djnz ibl00
- ret
-
-
- ; I originally intended that the following code should be used to expand
- ; asterisks in file names but I never invoked it anywhere! Eventually
- ; someone complained and I corrected the omission by adding some code to
- ; the LFCB routine. When I (re)discovered this code I noticed that it was
- ; longer than the code added to LFCB so I commented it out. I am leaving
- ; it here because LFCB was never intended to handle ambiguous file names.
- ; I don't think there is a problem but should there turn out to be some
- ; sort of wierd conflict then it should be easy to activate this little
- ; routine. jrs 27 Dec 88
- ;
- ;iwild: ;Expand asterisks in file names
- ; ld bc,8 ;Enter with HL pointing at FCB+1
- ; call iexp ; i.e. first byte of file name.
- ; ld bc,3
- ;; call iexp
- ;; ret
- ;iexp:
- ; ld a,'*'
- ; cpir
- ; ret nz
- ; inc bc
- ; dec hl
- ;iexp10:
- ; ld (hl),'?'
- ; inc hl
- ; dec c
- ; ret z
- ; jr iexp10
- page
- ;******************************************************************************
- ;*
- ;* lldr: Load file
- ;* User may supply optional load bias if file name ends with comma.
- ;*
- ;* lfcb: Parse input buffer (inbf) and init FCB
- ;*
- ;* Return: z - FCB initialized
- ;* nz - syntax error
- ;*
- ;* lopn: Attempt to open file
- ;*
- ;* Return: nz - file opened
- ;* z - file not found
- ;*
- ;* lmem: Test if sufficient memory available for loading
- ;*
- ;* Return: nc - out of memory
- ;*
- ;* lbin: Loader
- ;*
- ;* Eof found: end command
- ;* Out of memory: query user whether to continue
- ;*
- ;******************************************************************************
-
- lldr: call iedtbc ;Get file name
- jp p,lldr00 ;P - have input in inbf
- ld hl,(loadn)
- ld a,l
- or h
- jp z,e???
- ; ld c,a ;-
- ld c,10 ;+ 3.5.5 jrs 5/jan/89
- jp lbin22
- lldr00: call crlf
- call lfcb ;Init FCB with name and drive
- jp nz,esntx ;nz - syntax error
- ld de,mldg ;Display loading string
- call nprint
- ld de,prsbf
- ld a,(de) ;A - first char of file name
- ld b,a
- call print
- ld a,','
- cp c ;C - terminator following file name (from lfcb)
- ld hl,100h ;Assume no bias
- jr nz,lldr05 ;NZ - no comma means no load bias
- call iarg ;Check for load bias
- jp nz,esntx ;Error - bad argument
- call imem ;Check available memory
- jp nc,emem?? ;Out of memory
- lldr05: ld (loadb),hl ;Save load bias
- ld a,'.' ;Test if file name is period
- sub b
- jr z,lbin ;File name is period - no open needed
- lldr10: call lopn ;Attempt to open file - entry from nint
- jp z,efilnf ;Z - file not found
-
-
- lbin:
- ld hl,(loadb) ;Fetch starting load address
- lbin00: push hl
- ex de,hl
- ld c,26 ;Set CP/M DMA address
- call bdos
- ld de,fcb
- ld c,20 ;CP/M sequential file read
- call bdos
- pop de ;Recover DMA address
- ld hl,80h
- add hl,de ;Compute next DMA address
- ld (cflag),a ;Save EOF indicator as continuation flag
- ld c,a
- and a
- jr nz,lbin20 ;NZ - end of file
- call imem ;Test if memory available to load next sector
- jr c,lbin00 ;C - not out of memory
- lbin20: ex de,hl
- dec hl
- ld (loadn),hl ;End of load address
- lbin22: ld de,mlodm ;Print loaded message
- call nprint
- ex de,hl ;DE - ending address of load
- ld hl,(loadb)
- call outadr ;Display starting address of load
- ex de,hl
- call outadr ;Display ending address
- and a
- sbc hl,de
- inc h
- ld de,mlodpg
- call nprint ;Display pages string
- ld l,a ;zero L reg
- ld a,h ;Hi byte of ending address is number of pages
- cp 100
- jr c,lbin30 ;Less than 100
- ld l,'2'
- sub 200
- jr nc,lbin25 ;Greater than 200
- dec l ;change to ASCII 1
- add a,100 ;Restore actual page count less 100
- lbin25: ld h,a ;Save page count
- ld a,l
- call ttyo
- lbin30: ld d,2fh
- ld a,h
- lbin35: inc d ;Tens and units decimal conversion loop
- sub 10
- jr nc,lbin35
- add a,10 ;Restore remainder
- ld e,a ;Temp save while we print tens
- ld a,d
- inc l
- dec l ;Test L reg
- jr nz,lbin40 ;NZ - ASCII 1 or 2 in L
- cp '0' ;Suppress leading zero - less than 10 pages
- lbin40: call nz,ttyo ;Print tens digit
- ld a,e
- or '0'
- call ttyo ;Print units
- call crlf
- ; xor a ;- eg 3.3.7a Test eof flag
- ; or c ;-
- ld a,c ;+ Test EOF flag
- cp 10 ;+ Was it set by GADR (see 3.3.11)
- jp z,z8e ;+ Exit if so
- or a ;+
- ; jp nz,z8e ;- nz - true eof means file loading complete
- jr nz,z8ej ;+
- ld de,mmem?? ;Print "out of memory" message
- call print
- ld de,mcntu
- call print ;Print continue? prompt
- call inchar
- call ixlt ;Make sure its upper case
- cp 'Y'
- call crlf
- jp z,lbin ;User wants more loading
- z8ej: ;+
- ld c,26 ;+ "Set DMA" function
- ld de,80h ;+ Restore default DMA for user program
- call bdos ;+
- jp z8e ;Next command
-
-
- lfcb: call prsr ;parse input buffer to extract file name
- ld d,a ;save char which terminated file name
- ld a,14
- cp b ;over 14 chars is ng file name
- ret c
- ld c,b ;b and c - byte count of file name
- djnz lfcb00 ;test for only one char in name
- ld a,(prsbf) ;only one - is it period?
- sub '.'
- jr nz,lfcb00
- ld c,d ;return terminator
- ld a,(cflag) ;continuation allowed?
- and a ;let lldr decide
- ret
- lfcb00: ld b,0
- ld a,':' ;check for drive specifier in input
- cpdr
- ld b,c ;b - number of chars preceding colon
- ld c,d ;return terminator in c
- ld de,fcb
- ld a,0
- jr nz,lfcb10 ;nz - no colon
- dec b
- ret nz ;syntax error - more than one char
- ld a,(hl) ;fetch drive specifier
- call ixlt
- ld (hl),a ;back to parse buffer as upper case
- sub 40h ;make name into number
- inc hl
- lfcb10:
- ld (de),a ;store drive number in fcb
- ld a,' '
- ld b,11 ;clear file name in fcb to spaces
- lfcb20: inc de
- ld (de),a
- djnz lfcb20
- ld b,8 ;max chars allowed in file name
- ld de,fcbnam
- lfcb30: call lfcb90
- ret m ;error - too many chars in file name
- ld b,3 ;max chars allowed in file type
- ld de,fcbtyp
- and a
- ret z ;z - no file type after all
-
-
-
- lfcb90: inc hl ;Bump buffer pointer
- ld a,(hl)
- and a ;Test for null at end of file name
- ret z ;Null found - nothing more to parse
- call ixlt
- ld (hl),a ;Translate parse buffer to upper case
- cp '.'
- ret z ;Period found - move file type into FCB
-
- ; --- Added 4 Dec 88 --- jrs
- cp '*' ;Expandable wildcard?
- jr z,lfcb95
- ; --- end of added code ---
- dec b ;Dec max chars allowed
- ret m ;Error if name or extension is too long
- ; or a character follows an asterisk
- ld (de),a ;Upper case only into FCB
- inc de
- jr lfcb90
- ; --- Added 4 Dec 88 --- jrs
- lfcb95:
- ld a,'?'
- lfcb96:
- ld (de),a
- inc de
- djnz lfcb96
- jr lfcb90
- ; --- end of added code ---
- lopn:
- ld hl,fcbnam ;test for file name present
- ld a,(hl)
- cp ' '
- ret z ;space found means not file
- ;; dec hl
- ;; ld a,(hl) ;drive specifier
- ;; and a ;test for default drive
- ; jr z,lopn00 ;z - default means no selection required
- ; dec a ;select drive
- ; ld e,a
- ; ld c,14
- ; call bdos
- lopn00: ld de,fcb
- ld b,nfcb-fcbext
- ld hl,fcbext ;clear remainder of fcb
- lopn10: ld (hl),0
- inc hl
- djnz lopn10
- ld c,15
- call bdos ;tell bdos to open file
- inc a ;test open return code
- ret ;nz - open ok
-
- imem: ex de,hl ;de - next load address
- ld a,d
- ld hl,07 ;ptr to prt to start of z8e
- cp (hl)
- ex de,hl
- ret c ;c - not out of memory
- ex de,hl
- ret ;de - last address loaded plus one
-
- esntx: ld de,msntx ;print syntax error
- jr eprint
-
- emem??: ld de,mmem?? ;print out of memory
- call nprint
- jr eprint
-
- efilnf: ld de,mfilnf ;print file not found
-
- eprint: call nprint
- jp z8e
- page
- ;*****************************************************************************
- ;*
- ;* write memory segment to disk command
- ;*
- ;*****************************************************************************
-
- writ: call iedtbc ;fetch line of input
- ret m ;no input -
- call bldf ;build fcb with first arg in buffer
- jr nz,esntx ;oops - syntax error
- ld a,(delim) ;check char that terminated file name
- and a
- jr nz,writ10 ;nz - not null means user entered addresses
-
- ld de,(loadb) ;use default begin and end address of the last
- ld hl,(loadn) ;file loaded
- jr writ30
- writ10: call iarg ;get address
- jp nz,e??? ;invalid address
- ex de,hl
- cp ' ' ;space terminator
- jp nz,e??? ;anything but is error
- writ20: call iarg ;get end address
- jp nz,e???
- writ30: ld (endw),hl ;save address of where to end writing
- ex de,hl
- ld c,3
- call spaces
- call outadr
- ex de,hl
- ld c,6
- call spaces
- writ40: call bwrite
- ld hl,127
- add hl,de
- ld b,6
- writ50: call bksp
- djnz writ50
- call outadr
- inc hl
- ex de,hl
- ld hl,(endw)
- sbc hl,de
- jr nc,writ40
- jp closef
-
-
-
- ;******************************************************************************
- ;*
- ;* find: locate string in memory
- ;*
- ;* call iarg - get starting address of seach
- ;*
- ;* call in00 - get match data concatenating multiple arguments
- ;* into a single string
- ;*
- ;* addresses at which matches found displayed 8 per line.
- ;* search continues until end of memory reached
- ;* user may cancel search at any time by hitting any key.
- ;*
- ;* exit: to z8e for next command
- ;*
- ;******************************************************************************
-
- find: call iedtbc
- ret m ;m - no input
- call iarg ;extract starting address of search
- jp nz,e??? ;error
- ex de,hl ;save starting address of search in de
- find00: call in00 ;extract search string concatenating multiple
- ;arguments
- jp nz,e??? ;error - output command prompt
- xor a
- ld (lines),a ;clear crlf flag
- ex de,hl ;starting address of search - hl
- ld de,argbf ;argument stored here
-
- ld bc,(fndsym)
- ld a,c
- or b ;symbol found?
- jp z,find40 ;no
-
- ex de,hl ;hl - argument buffer
- ld b,(hl) ;reverse order of the two bytes for symbols
- inc hl
- ld a,(hl)
- ld (hl),b
- dec hl
- ld (hl),a
- ex de,hl
-
- find40: ld bc,(argbc) ;number of bytes to look for
- call crlf
- find50: call srch ;do the search
- jr nz,find60 ;not found
- call outadr ;display address where match found
- ld a,(lines)
- dec a ;carriage return after 8 addresses displayed
- ld (lines),a
- and 7
- call z,crlf
- call ttyq ;user requesting abort?
- cp cr
- ret z ;abort - return to z8e
- find60: inc hl ;point to next address at which to start search
- add hl,bc ;ensure we won't hit end of memory by adding
- ;in string size
- ret c ;impending end of memory
- sbc hl,bc ;restore pointer
- jr find50
-
- srch: push bc
- push de
- push hl
- srch00: ld a,(de)
- cpi
- jp nz,srch10 ;no match
- inc de
- jp pe,srch00 ;tally not expired - check next
- srch10: pop hl
- pop de
- pop bc
- ret
- page
- ;******************************************************************************
- ;*
- ;* verify: verify two blocks of data are identical
- ;*
- ;* enter: de - starting address of block 1
- ;*
- ;* call bcde to get address of block 2 and byte count
- ;*
- ;* mismatch: block 1 address and byte are displayed
- ;* block 2 address and byte are displayed
- ;* console intrrogated - any input terminates verify
- ;*
- ;* exit: to z8e for next command
- ;*
- ;******************************************************************************
-
- verify: call bcde ;get block 2 address and byte count
- jp nz,e???
- ex de,hl
- verf00: ld a,(de) ;byte from block 1
- xor (hl) ;versus byte from block two
- jr z,verf10 ;match - no display
- call newlin
- ld a,(de)
- call othxsp ;display block 1 data
- call space
- call outadr ;display block two address
- ld a,(hl)
- call outhex ;display results of xor
- call ttyq ;check input status
- cp cr
- ret z
- verf10: inc hl ;bump block 1 pointer
- inc de ;bump block 2 pointer
- dec bc ;dec byte count
- ld a,b
- or c
- jr nz,verf00
- ret
- page
- ;******************************************************************************
- ;*
- ;* xreg: display machine state
- ;*
- ;* regptr: table contains offsets to names in operand name table.
- ;* sign bit set indicates prime register.
- ;*
- ;* regmap: table contains offsets to reg contents table (regcon)
- ;* sign bit ignored (used by rgst command).
- ;*
- ;* regcon: table of register contents.
- ;*
- ;* exit: make current pc current disassembly location counter.
- ;* set bit 6 of disassembly flag byte (zasmfb)
- ;* jump to zasm30 to disassemble current instruction.
- ;*
- ;******************************************************************************
-
- xreg: call cret
- ld bc,0 ;init reg index
- xreg00: call xreg05 ;display reg name and contents
- inc c
- ld a,c
- cp 8
- call z,crlf
- ld a,c
- cp 0ch
- ld b,0
- jr nz,xreg00
- ld a,(lcmd)
- cp 'J' ;animated command in effect?
- ret z ;z - no disassembly required
- ld hl,(pcreg)
- ld (zasmpc),hl
- ; jp zasm30 ;- eg 3.3.5b
- call zasm30 ;+
- jp pswDsp ;+
-
- xreg05: ld hl,regptr ;map of reg name pointers
- ld d,b
- add hl,bc
- ld a,(hl) ;extract pointer
- and 7fh ;strip sign for name indexing
- ld e,a
- ld b,(hl) ;save copy of offset - need sign later
- ld hl,zopnm ;register name table
- add hl,de
- add hl,de ;two bytes per entry
- ld a,(hl)
- call ttyo ;display character one
- inc hl
- ld a,(hl)
- cp ' ' ;is second character a space?
- jr nz,xreg10
- ld a,'C' ;replace space - this is pc
- xreg10: call ttyo ;display second character
- xor a
- or b ;now test sign
- jp p,xreg20 ;sign not set - not prime reg
- ld a,27h ;display quote
- call ttyo
- xreg20: ld a,':'
- call ttyo
- ld hl,regmap ;map of pointers to reg contents
- add hl,de
- ld a,(hl)
- jp p,xreg30 ;p - not prime reg
- add a,8 ;prime contents 8 bytes past non-prime
- xreg30: and 7fh ;ignore sign
- ld e,a
- ld hl,regcon ;start of register contents storage
- add hl,de
- ld d,(hl) ;hi order contents
- dec hl
- ld e,(hl)
- ex de,hl
- call outadr ;display contents
- ret
-
- page
- ;******************************************************************************
- ;*
- ;* zasm
- ;*
- ;* the disassembler is divided into two routines:
- ;*
- ;* zasm - computes the instruction key value and finds the opcode nmemonic
- ;* opn - uses the key value to determine the number of operands and
- ;* displays the operands.
- ;*
- ;* entered: de - starting address to disassemble
- ;*
- ;* zasm maps the 695 z80 instrucions into 256 key values.
- ;* the instruction key value becomes the index into the
- ;* opcode name pointer table (zopcnm), the first operand table
- ;* (zopnd1), and the second operand table (zopnd2).
- ;*
- ;* disassembly is done in user specified block sizes if the
- ;* disassembly count evaluates to a number between 1 and 255. if
- ;* the count is greater than 255 the block is disassembled and the
- ;* the command terminates.
- ;*
- ;*
- ;* zasm15 - start of the disassembly loop
- ;* zasmpc - address of the instruction being disassembled
- ;* zasmfb - disassembly flag byte
- ;* zmflag - flag indicating directive processing (defb and defw)
- ;*
- ;* bit 6 - xreg calling
- ;* bit 5 - asmblr calling
- ;* bit 0 - write to disk flag
- ;*
- ;*
- ;*
- ;******************************************************************************
-
-
- zasm:
- call iedtbc
-
- ; ret m ;- eg 3.3.2
- jp p,zasm0 ;+ Skip if arguments supplied, otherwise ...
- ld b,0 ;+ Signal no file write
- ld hl,16 ;+ Assume 16 lines of code
- ld (zasmwt),hl ;+
- ld (zasmct),hl ;+
- jr zasm06 ;+
- zasm0: ;+
- call iarg
- jp nz,e???
- ex de,hl
- call iarg ;read in block size
- ld b,a ;save delimeter
- jr z,zasm00
- ld hl,1 ;change zero count to one
- zasm00: xor a
- or h
- jr z,zasm05
- sbc hl,de
- jp c,e??? ;error - start address greater than end
- add hl,de
- zasm05: ld (zasmct),hl ;save as permanent block count
- ld (zasmwt),hl ;save as working tally
- ex de,hl ;hl - current instruction pointer
- ld (zasmpc),hl
- zasm06: ;+ eg 3.3.2
- call crlf
- ld a,b ;check command line delimeter
- ld (dwrite),a ;save as write to disk flag:
- ;z - no write nz - write
- and a
- call nz,bldf ;not end of line - build fcb
- jp nz,esntx
-
- zasm08: ld de,zasmbf ;start of disassembly buffer
-
- zasm10: ld (zasmio),de ;init pointer
-
- zasm15: ld de,(zasmpc) ;fetch address to disassemble
- call zlen00 ;calculate length
- ex de,hl
-
- ;loop back here for interactive disassembly -
- ;user requests format change. c reg:
- ; 6 and 7 off: disassemble as code
- ; 6 on: hex defb
- ; 7 on: hex defw or ascii defb
-
- zasm18: call outadr ;display instruction address
- ld de,zmflag
- ld a,c ;save instruction length and format bits
- ld (de),a
- and 3fh
- ld b,a ;b - length
- ld c,a ;c - ditto
- zasm20: ld a,(hl)
- call othxsp ;display object code
- inc hl
- djnz zasm20
- ld a,c ;number of object bytes
- dec a
- xor 3
- ld b,a ;calculate space padding
- add a,a
- add a,b
- add a,2
- ld b,a
- zasm25: call space
- djnz zasm25
- ld (zasmnx),hl ;store address of next instruction
- and a ;clear carry
- sbc hl,bc ;point to first byte in instruction
- zasm30: ex de,hl ;de - current instruction pointer
- ld hl,(zasmio) ;buffer address storage
- ld a,(maxlin)
- ld b,a ;line length based on max symbol size
- zasm35: ld (hl),' ' ;space out buffer
- inc hl
- djnz zasm35
- ld a,b
- ld (opnflg),a
- ld (hl),cr ;append crlf
- inc hl
- ld (hl),lf
- call fadr ;find address match
- ld hl,(zasmio)
- jr nz,zasm40 ;nz - no table or not found
- call xsym
- ld (hl),':'
- ld de,(zasmpc)
- zasm40: ld hl,zmflag ;check interactive disassembly flag
- ld a,(hl) ;sign bit tells all
- and a
- jp p,zasm42 ;bit off - not interactive
- ld b,6dh ;test for defb
- sub 82h
- jr z,zasm90
- xor a ;must be defw
- dec b
- jr zasm90
- zasm42: ld a,(de) ;first byte of op code
- ld hl,op1000 ;table of z80 specific opcodes
- ld c,4
- zasm45: cpir ;check for fd dd ed or cb
- jr z,zasm55 ;z - found
- zasm50: cp 40h
- jr c,zasm90 ;opcode range 0 - 3f
- ld b,0e0h ;
- cp 0c0h ;
- jr nc,zasm90 ;opcode range c0 - ff
- cp 80h
- jr nc,zasm85 ;opcode range 80 - bf
- ld b,0f8h ;
- cp 76h ;test for halt instruction
- jr nz,zasm85 ;opcode range 40 - 7f
- ld a,0ffh ;set halt instruction key value to 0f7h
- jr zasm90
- zasm55: inc de
- ld a,(de) ;byte two of multi-byte instruction
- dec c ;test for ed instruction
- jr nz,zasm65 ;nz - not an ed
- cp 80h
- jr nc,zasm60 ;opcode range ed 40 - ed 7f
- cp 40h
- jr nc,zasm90 ;legal
- ld a,09fh
- jr zasm90 ;map to question marks
- zasm60: ld b,0e0h ;set bias
- cp 0c0h ;test for illegal ed
- jr c,zasm90 ;legal
- ld a,0bfh ;map to question marks
- jr zasm90 ;opcode range ed a0 - ed bb
-
-
- zasm65: inc c
- jr z,zasm80 ;z - cb instruction
- cp 0cbh ;fd or dd - check for cb in byte two
- jr nz,zasm70
- inc de ;fetch last byte of fdcb or ddcb
- inc de
- ld a,(de)
- rrca
- jr c,zasm75
- and 3
- cp 3
- jr nz,zasm75 ;error
- ld a,(de)
- jr zasm80
- zasm70: ld a,(zmflag)
- sub 3
- ld a,(de)
- jr nz,zasm50
- ld hl,z80f3
- ld c,z80f3l
- cpir
- jr z,zasm50
- zasm75: ld a,09fh
- jr zasm90
- zasm80: cp 40h ;test type of cb instruction
- ld b,0e8h
- jr c,zasm85 ;opcode range cb 00 - cb 3f (shift)
- rlca
- rlca
- and 03 ;hi order bits become index
- ld b,0f0h
- jr zasm90 ;opcode range cb 40 - cb ff
- zasm85: rrca
- rrca
- rrca ;bits 3-5 of cb shift yield key
- and 07h
- zasm90: add a,b ;add in bias from b reg
- ld c,a ;c - instruction key value
- xor a
- ld b,a
- ld hl,zopcpt ;opcode name pointer table
- add hl,bc ;index into table
- ld l,(hl) ;fetch opname index
- ld h,a
- add hl,hl
- add hl,hl ;index times four
- ld de,zopcnm ;op code name table
- add hl,de
- ex de,hl ;de - pointer to opcode name
- ld hl,(zasmio) ;buffer pointer storage
- ld a,c
- ld (zasmkv),a ;opcode key value
- ld a,(maxlen)
- ld c,a
- inc c ;set label length based on max size
-
- ld a,(lcmd) ;if xreg use compressed output format
- cp 'X'
- jr z,zasm92
- cp 'S' ;step needs compressed format
- zasm92: add hl,bc
- ld c,4
- ex de,hl ;de - buffer hl - opcode name pointer
- ldir
- inc bc ;one space after opcode for compressed format
- jr z,zasm95
- ld c,4 ;four spaces for true disassembly
- zasm95: ex de,hl ;hl - buffer pointer
- add hl,bc ;start of operand field in buffer
- ld a,(zasmkv) ;save the instruction key value
- cp 09fh
- jr nz,zasm99
- ld de,(zasmpc)
- ld a,(zmflag)
- ld b,a
- zasm97: ld a,(de)
- ld c,d
- call zhex
- dec b
- jp z,opn020
- ld (hl),','
- inc hl
- ld d,c
- inc de
- jr zasm97
- zasm99: ld de,zopnd1 ;table of first operands
- add a,e
- ld e,a ;instant offset
- ld a,d
- adc a,b
- ld d,a
- ld a,(de)
- inc a
- jr z,opn040 ;no operands
-
- page
- ;******************************************************************************
- ;*
- ;* - operand processing -
- ;*
- ;* enter: b - zero (process first operand)
- ;* c - instruction key value
- ;*
- ;* instruction key value is used to fetch operand key value:
- ;*
- ;* operand key value is in the range 0 - 1fh
- ;* operand key value interpretted as follows:
- ;*
- ;* 0 - 17h use as index to fetch literal from operand
- ;* name table (sign bit set - parens required)
- ;*
- ;* 18 - 1fh operand requires processing - use as index
- ;* into oprerand jump table which is located
- ;* immediately after name table
- ;*
- ;* 0ffh no operand
- ;*
- ;* operand key value jump table routines: (buffer address in de)
- ;*
- ;*
- ;* entry point key action
- ;*
- ;* opn100 18h relative jump
- ;* opn200 19h convert 8 bit operand to hex
- ;* opn300 1ah convert 16 bit operand to hex
- ;* opn400 1ch register specified in instruction
- ;* opn600 1dh hl/ix/iy instruction
- ;* opn700 1eh mask rst operand from bit 3-5 of rst instruction
- ;* opn800 1fh bit number is specified in bits 3-5 of op code
- ;*
- ;* exit: to zasm15 to continue block disassembly
- ;*
- ;******************************************************************************
-
- opn: dec a ;save operand key value
- jp p,opn010
- ld (hl),'('
- inc hl
- opn010: ex de,hl ;de - buffer address
- ld b,a
- add a,a ;operand key value times two
- opn012: ld hl,zopnm ;base of operand name/jump table
- add a,l ;index into table
- ld l,a
- jr nc,opn014
- inc h ;account for carry
- opn014: ld a,1fh
- and b
- cp zopnml ;test if processing required
- jr c,opn015 ;c - operand is a fixed literal
- ld a,(hl) ;fetch processing routine address
- inc hl
- ld h,(hl) ;
- ld l,a ;hl - operand processing routine
- jp (hl) ;geronimoooooooo
- opn015: ldi ;first byte of operand literal
- inc bc ;compensate for ldi
- ex de,hl ;hl - buffer
- ld a,(de)
- cp ' ' ;test for space as byte two of literal
- jr z,opn020 ;ignore spaces appearing in byte two
- ld (hl),a
- inc hl ;bump buffer pointer
- opn020: ld a,b ;operand key value
- cp 80h ;test for closed paren required
- jr c,opn030 ;c - none required
- ld (hl),')'
- inc hl
- opn030: ld a,(opnflg) ;get flag byte
- xor 0ffh ;toggle operand number
- ld (opnflg),a ;
- jr z,opn040 ;z - just finished number two
- ld a,(zasmkv) ;get op code key value
- ld de,zopnd2 ;index into operand2 table
- add a,e
- ld e,a
- jr nc,opn035
- inc d
- opn035: ld a,(de) ;get operand2 key value
- inc a
- jr z,opn040 ;z - no second operand
- ld (hl),',' ;separate operands with comma in buffer
- inc hl
- jr opn
- opn040: ld hl,(zasmio) ;rewind buffer pointer
- ld a,(maxlin)
- ld c,a
- opn041:
- ld a,(case)
- and a
- jr z,opn043 ;Upper case requested - no need to convert
- ;reg names [ras 19 Sep 85]
- opn042: ld a,(hl)
- and a ;if sign bit on then no case conversion
- call p,ilcs
- and 7Fh ;in case we fell thru
- ld (hl),a
- inc hl
- dec c
- jr nz,opn042
- opn043: ;correct jmp from opn041 4-9-85
- ld a,(maxlin)
- cp 30
- jr z,opn044
- ld a,44 ;allow 16 comment chars
- opn044:
- ld c,a ;number of chars to print (omit crlf)
- ld hl,(zasmio)
- ld a,(lcmd)
- cp 'J' ;j command
- ret z ;end of the line for full screen animation
- call printb ;print buffer
- inc hl ;point past crlf to next 32 byte group
- inc hl
- ex de,hl
- ld a,(lcmd) ;jettison all commands except z
- cp 'X'
- jp z,crlf
- cp 'A'
- jp z,crlf
- cp 'S'
- jp z,crlf
- xor a
- ld (zasmf),a
- ld hl,(zasmct) ;check disassembly count
- dec hl
- ld a,h
- or l ;test for count expired
- jp nz,opn060 ;nz - this is not a count of one so this is not
- ;interactive disassebly
-
- call ttyi ;check input command letter for interactive
- call ixlt ;force upper case
- ld (zasmf),a
- cp 'C' ;code?
- call z,cret ;if user wants code return cursor to start of
- ;line and disassemble again
- jp z,zasm15
- ld c,82h ;assume defw
- cp 'D'
- jr z,opn045 ;defw - 082h
- dec c ;assume ascii defb
- cp 'A'
- jr z,opn045 ;ascii defb - 081h
- cp 'B'
- jr nz,opn046 ;none of the above
- ld c,0c1h ;hex defb - 0c1h
- opn045: call cret
- ld hl,(zasmpc)
- jp zasm18
-
- ;zasmf - 0 means this is block disassembly
- ; - nz means char entered during
- ; interactive mode was not c d a or b.
-
- opn046: cp ';' ;check if user wants to insert comments
- jr nz,opn060 ;nz - user does not want to add comment
-
- call ttyo ;echo semicolon
- dec de
- dec de ;point to carriage return
- ld a,' '
- ld (de),a ;clear crlf from buffer
- inc de
- ld (de),a
- inc de
- call write ;end of buffer - write if required
- ld b,29
- ld a,(maxlin)
- sub 30
- jp z,opn048
- dec de
- ld b,16
- xor a
- opn048: ld c,a
- push bc
- push de ;save disassembly buffer pointer
- ld d,a
- call iedt03
- pop de
- pop bc
- ld a,b ;recover max size of comment
- dec hl
- ld b,(hl) ;number actually entered
- sub b
- ld c,a ;trailing spaces
- inc hl
- ex de,hl ;de - input buffer hl - disassembly buffer
- ld (hl),';'
- inc hl
- opn049: dec b ;pre-test count
- jp m,opn050
- ld a,(de) ;first char of input
- inc de
- ld (hl),a ;into disassembly buffer
- inc hl
- jr opn049
- opn050: dec c
- jp m,opn055
- ld (hl),' '
- inc hl
- jr opn050
- opn055: ld (hl),cr
- inc hl
- ld (hl),lf
- inc hl
- ex de,hl
- jp opn065
-
- opn060:
- ld a,(maxlin)
- cp 30 ;test for 6 chars in label
- jp z,opn065 ;z - buffer point ok
- ld a,64-46 ;bump buffer pointer to next 64 byte chunk
- add a,e
- ld e,a
- jp nc,opn065
- inc d
-
- opn065: call write ;check if write to disk flag in effect
-
- call crlf
- ld (zasmio),de ;save new buffer pointer
- ld hl,(zasmwt) ;check disassembly count
- xor a
- or h ;less than 256?
- jr z,opn080 ;less - this is tally
- ld bc,(zasmnx) ;fetch next disassembly address
- sbc hl,bc ;versus requested end address
- jr c,opn095 ;c - end
- add hl,bc ;restore next disassembly address
- jr opn085 ;more
- opn080: dec hl
- ld a,h
- or l
- jr nz,opn085 ;nz - more
- ld hl,(zasmct) ;fetch permanent block size
- ld a,(zasmf)
- and a
- call z,ttyi ;query user - more?
- cp cr ;return means end
- jr z,opn095
- jr opn090
- opn085:
- call ttyq
- cp cr
- jr z,opn095 ;nz - terminate disassembly
- opn090:
- ld (zasmwt),hl ;restore count
- ld hl,(zasmnx) ;next instruction pointer
- ld (zasmpc),hl ;make current
- jp zasm15 ;disassemble next instruction
-
- opn095: ld a,(dwrite) ;writing to disk?
- and a
- ret z
- ld a,eof ;
- ld (de),a ;set eof
- ld de,zasmbf
- call write
-
-
-
- closef: ld de,fcb ;close file
- ld c,16
- jp bdos
-
-
-
- write: push bc
- push hl
- ld hl,nzasm ;address of end of disassembly buffer
- and a
- sbc hl,de
- jr nz,wrt10 ;not end of buffer
- ld de,zasmbf ;need to rewind buffer pointer
- ld a,(dwrite) ;test write to disk flag
- and a
- call nz,bwrite ;nz - writing to disk
- wrt10: pop hl
- pop bc
- ret
-
-
-
- bwrite: push bc ;bdos write routine
- push de
- push hl
- ld c,26 ;set dma address
- call bdos
- ld de,fcb
- ld c,21
- call bdos ;write buffer
- ;+ eg 3.3.7b
- ld c,26 ;+ "Set DMA" function
- ld de,80h ;+ Restore default DMA for user program
- call bdos ;+
- pop hl
- pop de
- pop bc
- ret
-
-
-
- bldf: call lfcb ;initialize fcb
- ret nz ;error - invalid file name
- call lopn
- jr z,bldf00 ;no file - create one
- ld de,fcb
- ld c,19 ;file exists - delete it
- call bdos
- bldf00: ld de,fcb ;create new file
- ld c,22
- call bdos ;if no file create one
- xor a
- ret
-
- page
-
- opn100: ld hl,(zasmpc)
- inc hl
- ld a,(hl) ;fetch relative displacement
- ld c,a
- inc c
- add a,a ;test sign for displacement direction
- ld b,0
- jr nc,opn105
- dec b ;produce zero for forward - ff for back
- opn105: add hl,bc ;adjust pc
- ex de,hl ;de - instruction ptr hl - buffer
- call fadr
- call z,xsym
- jp z,opn040 ;symbol found
- ; ld (hl),'$' ;- eg 3.3.4a
- ; inc hl ;-
- ; ld a,c ;-
- ; inc a ;-
- ld b,0
- ; cp 82h ;-
- ; jp opn610 ;- convert displacement to ascii
- jp opn316 ;+
-
- opn200: call zmqf ;check for interactive disassembly
- jr nc,opn205 ;sign off - not interactive
- add a,a ;shift out bit 6
- ld a,(hl)
- jr c,opn215 ;on - must be hex defb
- call zascii ;user wants ascii - check validity
- jr nz,opn215 ;nz - untable to convert to ascii
- jp opn020
- opn205: call zndx ;check for ix or iy instruction
- ex de,hl ;buffer back to de
- jr nz,opn210 ;nz - not ix or iy
- inc hl
- inc hl ;must be ld (ix+ind),nn
- opn210: inc hl ;
- ld a,(hl) ;fetch object byte
- jr z,opn215 ;no conversion of ix and iy displacements
- ;to ascii
- ld a,(zasmkv) ;check for in or out instruction
- cp 0b3h
- jr z,opn215 ;no conversion of port addresses to ascii
- cp 0bbh
- jr z,opn215
- ld a,(hl)
- call zascii
- jp z,opn020
- opn215: ex de,hl
- ld a,(de)
- cp 10 ;decimal number?
- jr nc,opn220 ;no - convert to hex
- call zhex20 ;86 the leading zero and trailing h
- jp opn020
- opn220: call zhex ;do hex to asii conversion
- ld (hl),'H' ;following 8 bit hex byte
- inc hl
- jp opn020
-
- opn300: call zmqf
- jr c,opn315 ;c - this is defw
- call zndx
- ex de,hl ;de - buffer hl - instruction pointer
- jr nz,opn310 ;nz - not ix or iy
- inc hl
- opn310: inc hl
- opn315: ld a,(hl) ;fetch lo order 16 bit operand
- inc hl
- ld h,(hl) ;hi order
- ld l,a
- ex de,hl ;de - 16 bit operand hl - buffer
- call fadr
- call z,xsym
- jp z,opn020 ;symbol found
- opn316: ;+ eg 3.3.4b
- ld a,d ;convert hi order to hex
- ld c,a ;save spare copy
- call zhex
- ld a,e
- ld d,a
- call zhex10
- xor a
- or c
- jr nz,opn320
- ld a,d
- cp 10
- jp c,opn020
- opn320: ld (hl),'h'
- inc hl
- jp opn020
-
- opn400:
- call zndx
- jr nz,opn410 ;nz - not ix or iy instruction
- inc de
- ld a,(de)
- cp 0cbh ;check for indexed bit instruction
- jr nz,opn410
- inc de ;byte of interest is number four
- inc de
- opn410: ld a,01 ;check low bit of operand key value
- and b
- ld a,(de) ;fetch op code
- jr nz,opn500 ;nz - index 01bh
- rra ;register specified in bits 0-5
- rra
- rra
- opn500: and 007 ;register specified in bits 0-2
- xor 006 ;from the movie of the same name
- jp nz,opn010 ;nz - not hl or ix or iy
- ld a,(zasmpc)
- xor e ;test if pc was incremented
- ld (hl),'(' ;set leading paren
- inc hl
- ld b,080h ;set sign bit - closed paren required
- ex de,hl ;de - buffer
- jp z,opn012
-
-
-
- opn600:
- call zndx ;determine if ix or iy
- jr z,opn605 ;z - must be ix of iy
- ld a,80h
- and b
- jp opn010
- opn605:
- ;+Fix display of IX/IY when upper case is set
- push af ;+Adapted from patch by George Havach (3.5.7)
- ld c,0DFh ;+Upper case mask
- ld a,(case) ;+See if upper or lower case
- or a ;+
- jr z,opn606 ;+Skip if upper case, otherwise
- ld c,0FFh ;+ adjust mask
- opn606: ;+
- ld a,'i' ;+First character
- and c ;+Select case
- ; ld (hl),'i' ;-Set first character
- ld (hl),a ;+Set first character
- inc hl
- pop af ;+Second character
- adc a,'x' ;Carry determines x or y (from zndx)
- and c ;+Select case
- ld (hl),a
- inc hl
- ld a,80h ;Test for parens
- and b
- jp z,opn030 ;z - not indexed instruction
- inc de
- ld a,(de) ;fetch second byte of instruction
- cp 0e9h ;test for jp (ix) or jp (iy)
- jp z,opn020 ;output closed paren
- inc de
- ld a,(de) ;fetch displacement byte
- cp 80h ;test sign
- opn610: ld (hl),'+' ;assume forward
- jr c,opn620 ;c - forward
- neg ;force positive
- ld (hl),'-'
- opn620: inc hl ;bump buffer pointer
- and 7fh ;strip sign
- call zhex ;convert to hex
- ld a,9
- cp d
- jp nc,opn020
- ld (hl),'h'
- inc hl
- jp opn020 ;output closed paren
-
-
-
-
- opn700: ld hl,(zasmpc)
- ld a,(hl) ;fetch restart instruction
- ex de,hl ;de - buffer hl instruction pointer
- and 38h
- call zhex ;convert restart number to ascii
- ld (hl),'H'
- jp opn020
-
-
-
- opn800: call zndx
- jr nz,opn810 ;nz - not ddcb or fdcb instruction
- inc de
- inc de
- inc de ;
- ld a,(de) ;byte 4 of ix or iy bit instruction
- jr opn820
- opn810: cp 10h ;weed out interrupt mode instructions
- ld a,(de) ;second byte of instruction regardless
- jr nz,opn820 ;nz - cb bit instruction
- xor 046h ;
- jr z,opn830 ;z - interrupt mode zero
- sub 8
- opn820: rra
- rra
- rra
- and 07 ;leave only bit number
- opn830: call zhex20 ;convert to ascii
- jp opn030
- page
- ;******************************************************************************
- ;*
- ;* disassembler utility subroutines
- ;*
- ;* zndx: determines if fd dd ed or cb instruction
- ;* caller uses returned values on an individual basis
- ;*
- ;* z - dd fd
- ;* nz - neither of the above
- ;* current instruction pointer bumped if cb or ed instruction
- ;*
- ;* zhex: convert to byte in the accumulator to ascii with leading zero
- ;* store in buffer
- ;* d - reg destroyed
- ;*
- ;* zhex10: no leading zero permitted
- ;* zhex20: convert lo order nibble only
- ;*
- ;******************************************************************************
-
- zndx: ld hl,(zasmpc) ;fetch current instruction pointer
- ex de,hl ;de - instruction pointer hl - buffer
- ld a,(de)
- add a,-0fdh ;iy check
- ret z
- sub 0ddh-0fdh ;ix check
- ret z
- cp 10h ;ed check
- jr z,zndx00
- cp 0eeh ;cb check
- ld a,0 ;clear
- ret nz
- zndx00: inc de ;cb or ed - bump instruction pointer
- cpl
- and a ;ensure nz set
- cpl
- ret
-
-
-
- zhex: ld d,a
- cp 0a0h ;test byte to convert
- jr c,zhex00 ;starts with decimal digit - 86 the lead zero
- ld (hl),'0'
- inc hl
- jr zhex10
- zhex00: cp 10
- jr c,zhex20
- zhex10: rrca
- rrca
- rrca
- rrca
- and 0fh
- add a,90h
- daa
- adc a,40h
- daa ;a - ascii digit
- ld (hl),a
- inc hl
- ld a,d ;lo nibble conversion
- zhex20: and 0fh
- add a,90h
- daa
- adc a,40h
- daa
- ld (hl),a
- inc hl
- ret
-
-
-
- zmqf: ld hl,zmflag ;check interactive disassembly flag
- ld a,(hl)
- ld (hl),0 ;clear regardless
- ld hl,(zasmpc) ;fetch current disassembly address
- add a,a ;check sign - on means interactive
- ret
-
-
- zascii: cp ' '
- ret c
- and a
- ret m
- cp 7fh ;rubout?
- jr z,zasc10
- cp quote
- jr nz,zasc20
- zasc10: and a ;set nz - conversion not done
- ret
- zasc20: ex de,hl
- ld (hl),quote ;defb - quoted character
- inc hl
- or 80h ;hi bit on - no case conversion for this guy
- ld (hl),a
- inc hl
- ld (hl),quote
- cp a
- ret
-
-
-
- fadr: push bc
- push hl
- ld hl,(06) ;fetch top of tpa - start of symbol table
- ld bc,(maxlen)
- add hl,bc ;point to start of symbol name
- inc hl
- fadr00: ld a,(hl) ;first byte of symbol name
- dec a ;check validity
- jp m,fadr30 ;end of table
- add hl,bc
- ld a,(hl) ;fetch hi order address from table
- cp d
- jp nz,fadr10
- dec hl
- ld a,(hl)
- inc hl
- cp e
- jp z,fadr20
- fadr10: inc hl
- jp fadr00
- fadr20: ex de,hl ;return pointer in de
- ld a,c
- cpl
- and e
- ld e,a
- xor a
- fadr30: pop hl
- pop bc
- ret
-
- xsym:
- ld a,(maxlen)
- dec a
- ld c,a
- xsym00: ld a,(de)
- and a
- ret z
- ld (hl),a
- inc hl
- inc de
- dec c
- jr nz,xsym00
- ret
- page
- ;******************************************************************************
- ;*
- ;* bcde: query user for 3 arguments: source address
- ;* destination address
- ;* byte count
- ;*
- ;* used by move, verify, and yfil routines
- ;*
- ;* return: bc - byte count
- ;* de - destination
- ;* hl - source pointer
- ;* z - no errors
- ;*
- ;* nz - no input entered
- ;* - untable to evaluate argument
- ;* - destination address < source
- ;*
- ;******************************************************************************
-
- bcde: call iedtbc
- ret m ;no input is treated as error
- call iarg ;read in starting block address
- ret nz
- ex de,hl
- call iarg
- ret nz
- sbc hl,de ;end - start = byte count - 1
- ret c
- ld b,h
- ld c,l
- inc bc
- call in00 ;read in destination block address
- ret nz
- ex de,hl ;set regs right
- ret
-
- page
- ;******************************************************************************
- ;*
- ;* console i/o routines
- ;*
- ;* "physical" i/o routines: ttyi - keyboard input
- ;* ttyo - console output
- ;* ttyq - console status
- ;*
- ;* logical input routines: inchar - input character processing
- ;* control characters echoed with ^
- ;*
- ;* logical output routines: crlf - output carriage return/line feed
- ;* cret - output carriage return only
- ;* space - output space
- ;* spaces - output number of spaces in passed in c
- ;* outhex - output hex byte in a
- ;* othxsp - output hex byte in a followed by space
- ;* outadr - output 16 bit hex value in hl followed
- ;* by space - hl preserved
- ;* print - output string - address in de
- ;* string terminated by null
- ;* printb - output string - address in hl
- ;* byte count in c
- ;* end at first null
- ;*
- ;******************************************************************************
-
- if ASMB
- ttyq:
- else
- ttyq::
- endif
- push bc
- push de
- push hl
- ld c,11
- call bdos
- and a
- ld c,6
- ld e,0ffh
- call nz,bdos
- pop hl
- pop de
- pop bc
- and 7fh
- ret
-
- if not compact
- org ttyq+32
- endif
-
- if ASMB
- ttyi:
- else
- ttyi::
- endif
- push bc
- push de
- push hl
- if ASMB
- ttyi00:
- else
- ttyi00::
- endif
- ld c,6
- ld e,0ffh
- call bdos
- and 7fh
- jr z,ttyi00
- pop hl
- pop de
- pop bc
- ret
-
- if not compact
- org ttyi+32
- endif
-
- if ASMB
- ttyo:
- else
- ttyo::
- endif
- push af
- push bc
- push de
- push hl
- ttyo00:
- and 7Fh ;+ eg 3.3.1 (but this instruction will be
- ; patched during initialisation
- ; according to value stored at
- ; coMask: [3.4])
- ld e,a
- if jterm ;My terminal uses tab as cursor position
- ld c,6 ;lead-in and I don't want the bdos to expand
- else ;the tab to a string of spaces.
- ld c,2
- endif
- call bdos
- pop hl
- pop de
- pop bc
- pop af
- ret
-
- if not compact
- org ttyo+32
- endif
-
- inchar: call ttyi
- cp ctlc
- jp z,00
- cp cr
- ret z
- cp tab
- ret z
- cp lf
- ret z
- cp bs
- ret z
- cp ctlx
- ret z
- cp ' '
- jr nc,ttyo
- push af
- ld a,'^'
- call ttyo
- pop af
- xor 40h
- call ttyo
- xor 40h
- ret
-
-
- ilcs: cp 'A'
- ret c
- cp 'Z'+1
- ret nc
- or 20h
- ret
-
-
-
- ixlt: cp 'a'
- ret c
- cp 'z'+1
- ret nc
- sub 20h
- ret
-
- page
- crlf: ld a,lf
- call ttyo
- cret: ld a,cr
- jp ttyo
-
- othxsp: call outhex
-
- space: ld a,' '
- jp ttyo
-
- space5: ld c,5
-
- spaces: call space
- dec c
- jr nz,spaces
- ret
-
-
-
- newlin: call crlf
- ex de,hl
- call outadr
- ex de,hl
- ret
-
-
- outadr: ld a,h
- call outhex
- ld a,l
- call othxsp
- jr space
-
-
-
- outhex: push af
- call binx
- call ttyo
- pop af
- call binx00
- jp ttyo
-
-
-
- binx: rrca
- rrca
- rrca
- rrca
- binx00: and 0fh
- add a,90h
- daa
- adc a,40h
- daa
- ret
- page
- ilin: push bc
- push de
- ld b,inbfsz
- ld c,0
- call in
- pop de
- pop bc
- ret
-
-
- istr: push bc
- push de
- ld b,1
- ld c,' '
- call iedt
- pop de
- pop bc
- ret
-
-
- ;resume input after reading in one char
-
- irsm: push bc
- push de
- ld b,inbfsz-1 ;max input size less one char already read in
- ld c,' ' ;this is terminator char
- ld d,1 ;preset byte count
- ld a,d
- ld (strngf),a ;set nz - this is string function
- ld hl,inbf+1 ;init buffer pointer
- call iedt05
- xor a
- ld (strngf),a ;this is no longer string function
- or d
- call p,in00
- pop de
- pop bc
- ret
-
-
-
- in: call iedt
- ret m
- in00: xor a
- ld (argbc),a
- ld hl,argbf
- ld (argbpt),hl
- in10: call iarg
- ret nz
- and a
- jr nz,in10
- ret
-
-
-
- iarg: push bc
- push de
- call parg
- ld a,(delim)
- pop de
- pop bc
- ret
- page
- parg: call prsr ;extract next argument
- ret nz ;parse error
- ld a,(quoflg) ;test for ascii literal
- and a
- jr z,parg10 ;quote character not found
- xor a
- or b ;test for balanced quotes
- ret m ;error - unbalanced quotes
- ld a,(de) ;first character of parse buffer
- sub quote
- jr nz,parg50 ;invalid literal string but may be expression
- ;involving a literal
- ld l,b ;l - character count of parse buffer
- ld h,a ;clear
- add hl,de ;
- dec hl ;hl - pointer to last char in parse buffer
- ld a,(hl) ;
- sub quote ;ensure literal string ends with quote
- jr nz,parg50
- ld (hl),a ;clear trailing quote
- ld c,b ;c - character count of parse buffer
- ld b,a ;clear
- dec c ;subtract the quote characters from the count
- dec c
- dec c ;extra dec set error flag nz for '' string
- ret m ;inform caller of null string
- inc c ;c - actual string length
- ld a,c ;spare copy
- inc de ;point to second character of parse buffer
- ld hl,(argbpt) ;caller wants evaluated arg stored here
- ex de,hl
- ldir
- ex de,hl
- dec hl
- ld e,(hl)
- dec hl
- ld d,(hl)
- inc hl
- inc hl ;point to where to store next arg
- dec a ;argument length 1?
- jr nz,parg00
- ld d,a
- parg00: ld c,a
- inc c ;account for increment
- ld a,(argbc) ;fetch current argument byte counter
- add a,c
- jr parg90
- parg10: call mreg ;check for register specified
- jr nz,parg50 ;nz - invalid register name
- ld a,c
- add a,a
- jr c,parg60 ;sign bit reset - 16 bit register pair
- parg50: ld hl,00
- ld b,l
- ld de,prsbf ;reinit starting address of parse buffer
- call xval
- jr z,parg70
- ret
- parg60: ld a,(hl)
- dec hl
- ld l,(hl)
- ld h,a
- ld a,(prsbf) ;check paren flag for indirection
- and a
- jr nz,parg65 ;nz - parens not removed
- inc de ;bump past trailing null
- ld a,(hl)
- inc hl
- ld h,(hl)
- ld l,a
- parg65: ld b,80h
- call xval
- ret nz
- parg70: ex de,hl
- ld hl,(argbpt)
- ld a,(argbc)
- inc d
- dec d
- jr z,parg80
- ld (hl),d
- inc hl
- inc a
- parg80: ld (hl),e
- inc hl
- inc a
- parg90: ld (argbc),a
- ld (argbpt),hl
- ex de,hl
- xor a
- ret
- page
- outbyt: ld b,a ;save spare copy
- call othxsp ;hex - display
- call space
- ld a,b ;display byte in ascii
- call asci ;display ascii equivalent
- ld c,3
- jp spaces ;solicit input three spaces right
-
- byte: call istr
- ld a,(inbfnc) ;number of chars in input buffer
- dec a ;test for input buffer count of zero
- inc de ;assume zero - examine next
- ret m ;no input means examine next
- dec de ;incorrect assumption
- ld a,(inbf) ;check first char of input buffer
- cp '.'
- ret z ;period ends command
- cp '=' ;new address?
- jr nz,byte10
- xor a ;clear equal sign so prsr ignores it
- ld (inbf),a
- call irsm ;fetch new address to examine
- jr nz,byte30 ;error
- ld a,(inbfnc)
- sub 2
- jr c,byte30 ;c - error - equal sign was only char of input
- ex de,hl ;return new address in de
- scf ;ensure nz set for caller - no replacement data
- ;was entered
- sbc a,a
- ret
- byte10: cp '^' ;
- jr nz,byte15 ;nz - not up arrow means need more input
- dec de ;dec current memory pointer
- scf ;set nz - no replacement data entered
- sbc a,a
- ret
- byte15: call irsm ;resume input from console
- ret z ;no errors on input
- ld a,(inbfnc) ;check number of chars input
- and a
- jr z,byte ;none - user hit control x or backspaced to
- ;beginning of buffer
- byte30: call e???
- scf
- sbc a,a ;set nz - no replacement
- ret
- page
- ;******************************************************************************
- ;*
- ;* bdos function 10 replacement to make romming this program easier since
- ;* only two console i/o routines (ttyi and ttyo) are required. this
- ;* routine supports backspace, line delete, and tab expansion.
- ;*
- ;* all input stored in input buffer inbf.
- ;*
- ;*
- ;* iedtbc: solicit console for new input and initialize b and c registers
- ;* for max size and input and no special line terminator.
- ;*
- ;*
- ;* iedt: solicit console for new input using non-default byte count for
- ;* buffer or non-standard terminator.
- ;*
- ;* called: b - max number of characters to receive
- ;* c - special terminator other than carriage return
- ;*
- ;*
- ;* iedt00: resume input - used by routines which call iedt with a buffer
- ;* count of 1 to check for special character as the first char
- ;* received (such as exam looking for period).
- ;*
- ;* called: b - max number of characters to receive
- ;* c - special terminator other than carriage return
- ;*
- ;******************************************************************************
-
-
- iedtbc: ld b,inbfsz
- xor a
- ld c,a
- ld (strngf),a
- iedt: xor a
- ld d,inbfsz
- ld hl,inbf
- iedt00: ld (hl),a
- inc hl
- dec d
- jr nz,iedt00
- ld (argbc),a ;init number of arguments tally
- ld hl,argbf
- ld (argbpt),hl ;init pointer to start of buffer
- iedt03: ld hl,inbf ;start of input buffer
- ld (quoflg),a
- iedt05: call inchar ;read char from console
- ld (trmntr),a ;assume line terminator until proven otherwise
- cp cr ;end of line?
- jp z,iedt90 ;z - end (jr changed to jp: eg 3.3.8a)
- ld e,a
- cp quote
- ld a,(quoflg)
- jr nz,iedt10
- xor quote
- ld (quoflg),a
- ld a,quote
- jr iedt60
- iedt10: and a ;quote flag on?
- ld a,e ;recover input character
- jr z,iedt15 ;off - check terminator
- ld a,(lcmd)
- call ixlt
- cp 'R'
- ld a,e
- jr nz,iedt20
- iedt15: cp c ;compare with auxiliary terminator
- jr z,iedt90 ;z - end
- iedt20: cp tab
- jr nz,iedt35 ;nz - not tab check backspace
- iedt25: call space ;space out until char position mod 8 = zero
- ld (hl),a ;store space in buffer as we expand tab
- inc hl
- inc d
- ld a,7
- and d
- jr nz,iedt25
- ld (hl),0 ;set end of line null
- jr iedt70
- iedt35: ld e,1 ;assume one backspace required
- cp bs
- jr z,iedt40 ;z - correct assumption
- cp ctlx ;erase line?
- jr nz,iedt60 ;nz - process normal input character
-
- xor a ;+ eg 3.3.8b
- or d ;+ See if ^X with empty buffer
- jp z,z8e ;+ Abandon current command if so
-
- ld e,d ;backspace count is number of chars in buffer
-
- jr iedt50 ;+
-
- iedt40: xor a ;test if already at beginning of buffer
- or d
- jr z,iedt05 ;z - at beginning so leave cursor as is
- iedt50: call bksp ;transmit bs - space - bs string
- dec d ;sub one from input buffer count
- dec hl ;rewind buffer pointer on notch
- ld a,(hl) ;check for control characters
- ld (hl),0
- cp quote ;check for backspacing over a quote
- jr nz,iedt55
- ld a,(quoflg) ;toggle quote flag so we keep track of balance
- ;factor
- xor quote
- ld (quoflg),a
- jr iedt58
- iedt55: cp ' '
- call c,bksp ;c - control char requires extra bs for caret
- iedt58: dec e ;dec backspace count
- jr nz,iedt50 ;more backspacing
- ld a,(strngf) ;string function flag on?
- and a
- jr z,iedt05 ;off - get next input char
- xor a ;did we backspace to start of buffer?
- or d ;test via character count
- jr nz,iedt05 ;not rewound all the way
- ld (inbfnc),a ;set a zero byte count so caller knows
- dec d ;something is fishy
- ret
- iedt60: ld (hl),a ;store char in inbf
- inc hl ;bump inbf pointer
- ld (hl),0 ;end of line
- inc d ;bump number of chars in buffer
- iedt70: ld a,d ;current size
- sub b ;versus max size requested by caller
- jp c,iedt05 ;more room in buffer
- iedt90: ld hl,inbfnc ;store number of characters received ala
- ;bdos function 10
- ld (hl),d
- inc hl ;point to first char in buffer
- dec d ;set m flag if length is zero
- ret ;sayonara
-
-
-
-
- bksp: call bksp00
- call space
- bksp00: ld a,bs
- jp ttyo
-
-
- asci: and 7fh ;Convert contents of accumulator to ascii
- if hazeltine ;Hazeltine terminal?
- cp tilde ; check for tilde or del
- jr nc,asci00 ; yes - translate to '.'
- else ;Non-hazeltine terminal
- cp del ; check for del
- jr z,asci00 ; yes - translate to '.'
- endif ;Any terminal - other characters
- cp 20h ; check for control character
- jp nc,ttyo ; no - output as is
- asci00: ; yes - translate to '.'
- ; if hazeltine
- ld a,'.' ;Non-printables replaced with dot
- ; else
- ; ld a,tilde ;Non-printables replaced with squiggle
- ; endif
- jp ttyo
-
-
-
- bcdx: call bcdx00
- ret nz
- bcdx00: rld
- ex de,hl
- add hl,hl
- ld b,h
- ld c,l
- add hl,hl
- add hl,hl
- add hl,bc
- ld c,a
- ld a,9
- cp c
- ret c
- xor a
- ld b,a
- add hl,bc
- ex de,hl
- adc a,a
- ret
-
-
-
- nprint: call crlf
- print: ld a,(de)
- and a
- ret z
- call ttyo
- inc de
- jr print
-
-
- printb: ld a,(hl)
- and a
- ret z
- call ttyo
- inc hl
- dec c
- jr nz,printb
- ret
-
-
-
- home: ld bc,00
-
-
- ;----------------------------------------------------------------------------
- ;
- ; xycp: Cursor-positioning routine.
- ;
- ; Two versions are supplied and either can be selected during
- ; assembly according to the setting of ATERM.
- ;
- ; aterm equ TRUE Selects ANSI screen driver
- ; aterm equ FALSE Selects default screen driver
- ;
- ; In either case, this routine is invoked with the row in B and
- ; the column in C.
- ;
- ;----------------------------------------------------------------------------
-
- if ASMB
- xycp:
- else
- xycp::
- endif
-
- if aterm
-
- ; ANSI screen driver - jrs - 27 May 87
- ; Tested and corrected 29 Dec 88 - jrs
-
- push de
- push hl
- inc b ;Add 1 to row and column
- inc c
- push bc
-
- ld a,1Bh ;Send ESC
- call ttyo
- ld a,'[' ;Send [
- call ttyo
- pop bc ;Send row (Y) coordinate
- push bc
- ld a,b
- call xycp00
- ld a,';' ;Send ;
- call ttyo
- pop bc ;Send column (X) coordinate
- push bc
- ld a,c
- call xycp00
- ld a,'H' ;Send H
- call ttyo
-
- pop bc
- pop hl
- pop de
- ret
-
- xycp00:
- ex af,af'
- xor a
- ex af,af'
- xycp10:
- ex af,af'
- inc a
- ex af,af'
- sub 10
- jr nc,xycp10
- ex af,af'
- dec a
- jr z,xycp20
- add a,'0'
- call ttyo
- xycp20:
- ex af,af'
- add a,'0'+10
- call ttyo
- ret
-
- else
-
- ; Default screen driver - ras
-
- push bc ;Enter with row in b and column in c
- push de
- push hl
- ld hl,mxycp
- ld a,(row) ;Add in row offset
- add a,b
- ld b,a ;Save row character
- ld a,(column) ;Add column bias
- add a,c
- ld c,a
- ld e,(hl) ;Number of chars in cursor addressing string
- xycp00:
- inc hl
- ld a,(hl)
- call ttyo
- dec e
- jr nz,xycp00
- ld a,(rowb4?)
- and a
- jr nz,xycp10
- ld a,b
- ld b,c
- ld c,a
- xycp10:
- ld a,b
- call ttyo
- ld a,c
- call ttyo
- pop hl
- pop de
- pop bc
- ret
-
- endif
-
- if not compact ;..then leave room for patching
- org xycp+128 ; the object code
- endif
-
- nrel: ;end of relocatable code
- page
-
- zopnm:
- defb 'HL'
- defb 'A '
- defb 'H '
- defb 'L '
- defb 'D '
- defb 'E '
- defb 'B '
- defb 'C '
- ix.: defb 'IX'
- defb 'SP'
- defb 'P '
- defb 'R '
- defb 'I '
- defb 'AF'
- defb 'BC'
- defb 'DE'
- iy.: defb 'IY'
- defb 'Z '
- defb 'NC'
- defb 'NZ'
- defb 'PE'
- defb 'PO'
- defb 'M '
- defb 'PC'
-
- ix.. equ (ix.-zopnm)/2 ;relative position - ix
- iy.. equ (iy.-zopnm)/2 ; iy
-
- zopnml equ ($-zopnm)/2
-
- zopjtb equ $-nrel ;nrel to jump table bias for loader
-
- zoprjt:
- defw opn600 ;18 - hl/ix/iy test
- defw opn400 ;19 - register specified in bits 0-2
- defw opn400 ;1a - register specified in bits 3-5
- defw opn100 ;1b - relative jump
- defw opn200 ;1c - nn
- defw opn300 ;1d - nnnn
- defw opn700 ;1e - restart
- defw opn800 ;1f - bit number
-
- zasmio: defw zasmbf
-
- zopjtl equ ($-zoprjt)/2 ;length of operand jump table
-
- jtcmd:
- defw ifcb ; i
- defw asmblr ; a
- defw usym ; u
- defw nprt ; n
- defw jdbg ; j
- defw zasm ; z
- defw exam ; e
- defw rgst ; r
- defw go ; g
- defw yfil ; y
- defw movb ; m
- defw verify ; v
- defw pswDsp ; p
- defw break ; b
- defw cbreak ; c
- defw find ; f
- defw hsym ; h
- defw step ; s
- defw obreak ; o
- defw lldr ; l
- defw dump ; d
- defw qprt ; q
- defw xreg ; x
- defw kdmp ; k
- defw writ ; w
- defw cuser ; >
- defw qeval ; ?
- ; defw gadr ; #
- cmd:
- ; defb '#?>WKXQDLOSHFCB'
- defb '?>WKXQDLOSHFCB'
- defb 'PVMYGREZJNUAI'
- ncmd equ $-cmd ;number of commands
-
- bpemsg:
- defb '*ERROR*'
- bpmsg:
- defb '*BP* @ '
- defb 0
- prompt:
- defb '*',' ',bs,0
-
- mrrow: defb '=','>' ;backspaces taken out
- defb 00
-
- m????: defb '??'
- m??: defb ' ?? '
-
-
- asmflg: defb ' '
- defb 0
-
- lcmd: defb ' '
- em???: defb ' ??'
- defb 0
-
- mldg:
- defb 'Loading: '
- defb 0
-
- mfilnf:
- defb 'File Not Found'
- defb cr,lf,00
-
-
- mlodm:
- defb 'Loaded: '
- defb 0
- mlodpg:
-
- defb 'Pages: '
- defb 0
-
- msntx:
- defb 'Syntax Error'
- defb cr,lf,0
-
- mmem??: defb 'Out Of Memory'
- defb 0
-
- mcntu: defb ' - Continue? '
- defb 0
-
- mireg:
- defb 'IR: '
- defb 0
- page
-
- z80fd: defb 009h,019h,02bh
- defb 023h,029h,039h,0e1h
- defb 0e3h,0e5h,0e9h,0f9h
- z80fdl equ $-z80fd
-
- z80f4: defb 021h,022h,02ah,036h,0cbh
- z80f4l equ $-z80f4
-
-
- z801: defb 0c0h,0e9h,0c9h,0d8h
- defb 0d0h,0c8h,0e8h,0e0h
- defb 0f8h,0f0h
- z801l equ $-z801
-
-
- z802: defb 036h,0c6h,0ceh,0d3h
- defb 0d6h,0dbh,0deh,0e6h
- defb 0eeh,0f6h,0feh
- z802c: defb 018h,038h,030h
- defb 028h,020h,010h
- z802l equ $-z802
- z802cl equ $-z802c
-
-
- z80r:
- z803: defb 001h,011h,021h,022h
- defb 02ah,031h,032h,03ah
-
- z803s: defb 0cdh
- defb 0dch,0d4h,0cch,0c4h
- defb 0ech,0e4h,0fch,0f4h
-
- z803sl equ $-z803s ;number of call instructions
-
- z803c: defb 0c3h
- defb 0dah,0d2h,0cah,0c2h
- defb 0eah,0e2h,0fah,0f2h
-
- z803l equ $-z803 ;number of 3 byte instructions
- z803cl equ $-z803s ;number of 3 byte pc mod instructions
-
- z80ed: defb 043h,04bh,053h
- defb 05bh,073h,07bh
-
- z80edl equ $-z80ed
-
- z80rl equ $-z80r ;number relocatable z80 instructions
-
- z80f3:
- defb 034h,035h,046h,04eh
- defb 056h,05eh,066h,06eh
- defb 070h,071h,072h,073h
- defb 074h,075h,077h,07eh
- defb 086h,08eh,096h,09eh
- defb 0a6h,0aeh,0b6h,0beh
- z80f3l equ $-z80f3
- page
- ;***********************************************************************
- ;*
- ;*
- ;*
- ;*
- ;*
- ;***********************************************************************
-
- org ($+3) and 0fffch
- zopcpt:
- defb 022h,01ch,01ch,015h ;nop ld ld inc 00 - 03
- defb 015h,00ch,01ch,031h ;inc dec ld rlca 04 - 07
- defb 010h,000h,01ch,00ch ;ex add ld dec 08 - 0b
- defb 015h,00ch,01ch,036h ;inc dec ld rrca 0c - 0f
- defb 00eh,01ch,01ch,015h ;djnz ld ld inc 10 - 13
- defb 015h,00ch,01ch,02fh ;inc dec ld rla 14 - 17
- defb 01bh,000h,01ch,00ch ;jr add ld dec 18 - 1b
- defb 015h,00ch,01ch,034h ;inc dec ld rra 1c - 1f
- defb 01bh,01ch,01ch,015h ;jr ld ld inc 20 - 23
- defb 015h,00ch,01ch,00bh ;inc dec ld daa 24 - 27
- defb 01bh,000h,01ch,00ch ;jr add ld dec 28 - 2b
- defb 015h,00ch,01ch,00ah ;inc dec ld cpl 2c - 2f
- defb 01bh,01ch,01ch,015h ;jr ld ld inc 30 - 33
- defb 015h,00ch,01ch,03ah ;inc dec ld scf 34 - 37
- defb 01bh,000h,01ch,00ch ;jr add ld dec 38 - 3b
- defb 015h,00ch,01ch,004h ;inc dec ld ccf 3c - 3f
-
-
- defb 014h,026h,039h,01ch ;in out sbc ld ed 40
- defb 021h,02dh,013h,01ch ;neg retn im ld
- defb 014h,026h,001h,01ch ;in out adc ld
- defb 022h,02ch,022h,01ch ;.... reti ... ld
- defb 014h,026h,039h,01ch ;in out sbc ld
- defb 022h,022h,013h,01ch ;... ... im ld
- defb 014h,026h,001h,01ch ;in out adc ld
- defb 022h,022h,013h,01ch ;... ... im ld
- defb 014h,026h,039h,022h ;in out sbc ...
- defb 022h,022h,002h,037h ;... ... ... rrd
- defb 014h,026h,001h,022h ;in out adc ...
- defb 044h,045h,046h,032h ;defb* defw* ddb* rld
- defb 043h,047h,039h,01ch ;org* equ* sbc ld ed 70
- defb 022h,022h,022h,022h ;... ... ... ...
- defb 014h,026h,001h,01ch ;in out adc ld
- defb 022h,022h,022h,022h ;... ... ... ... ed 7f
-
-
- defb 01fh,008h,018h,028h ;ldi cpi ini outi
- defb 022h,022h,022h,022h ;... ... ... ...
- defb 01dh,006h,016h,027h ;ldd cpd ind outd
- defb 022h,022h,022h,022h ;... ... ... ...
- defb 020h,009h,019h,025h ;ldir cpir inir otir
- defb 022h,022h,022h,022h ;... ... ... ...
- defb 01eh,007h,017h,024h ;lddr cpdr indr otdr
- defb 022h,022h,022h,044h ;... .... .... defb*
-
-
- defb 02bh,029h,01ah,01ah ;ret pop jp jp c0 - c3
- defb 003h,02ah,000h,038h ;call push add rst c4 - c7
- defb 02bh,02bh,01ah,022h ;ret ret jp ... c8 - cb
- defb 003h,003h,001h,038h ;call call adc rst cc - cf
- defb 02bh,029h,01ah,026h ;ret pop jp out d0 - d3
- defb 003h,02ah,03eh,038h ;call push sub rst d4 - d7
- defb 02bh,011h,01ah,014h ;ret exx jp in d8 - db
- defb 003h,022h,039h,038h ;call ... sbc rst dc - df
- defb 02bh,029h,01ah,010h ;ret pop jp ex e0 - e3
- defb 003h,02ah,002h,038h ;call push and rst e4 - e7
- defb 02bh,01ah,01ah,010h ;ret jp jp ex e8 - eb
- defb 003h,022h,03fh,038h ;call ... xor rst ec - ef
- defb 02bh,029h,01ah,00dh ;ret pop jp di f0 - f3
- defb 003h,02ah,023h,038h ;call push or rst f4 - f7
- defb 02bh,01ch,01ah,00fh ;ret ld jp ei f8 - fb
- defb 003h,022h,005h,038h ;call ... cp rst fc - ff
-
- defb 000h,001h,03eh,039h ;add adc sub sbc
- defb 002h,03fh,023h,005h ;and xor or cp
-
-
- defb 030h,035h,02eh,033h ;rlc rrc rl rr
- defb 03bh,03ch,022h,03dh ;sla sra ... srl
- defb 022h,040h,041h,042h ;... bit res set
-
-
- defb 022h,022h,022h,012h ;... ... ... halt
-
-
- defb 01ch,01ch,01ch,01ch ;ld ld ld ld
- defb 01ch,01ch,01ch,01ch ;ld ld ld ld
-
- page
- ;****************************************************************************
- ;*
- ;* table of first operands
- ;*
- ;****************************************************************************
-
- zopnd1:
- defb 0ffh,00eh,08eh,00eh ;00 - 03
- defb 006h,006h,006h,0ffh ;04 - 07
- defb 00dh,018h,001h,00eh ;08 - 0b
- defb 007h,007h,007h,0ffh ;0c - 0f
- defb 01bh,00fh,08fh,00fh ;10 - 13
- defb 004h,004h,004h,0ffh ;14 - 17
- defb 01bh,018h,001h,00fh ;18 - 1b
- defb 005h,005h,005h,0ffh ;1c - 1f
- defb 013h,018h,09dh,018h ;20 - 23
- defb 002h,002h,002h,0ffh ;24 - 27
- defb 011h,018h,018h,018h ;28 - 2b
- defb 003h,003h,003h,0ffh ;2c - 2f
- defb 012h,009h,09dh,009h ;30 - 33
- defb 098h,098h,098h,0ffh ;34 - 37
- defb 007h,018h,001h,009h ;38 - 3b
- defb 001h,001h,001h,0ffh ;3c - 3f
-
- defb 006h,087h,000h,09dh ;40 - 43
- defb 0ffh,0ffh,01fh,00ch ;44 - 47
- defb 007h,087h,000h,00eh ;48 - 4b
- defb 0ffh,0ffh,0ffh,00bh ;4c - 4f
- defb 004h,087h,000h,09dh ;50 - 53
- defb 0ffh,0ffh,01fh,001h ;54 - 57
- defb 005h,087h,000h,00fh ;58 - 5b
- defb 0ffh,0ffh,01fh,001h ;5c - 5f
- defb 002h,087h,000h,0ffh ;60 - 63
- defb 0ffh,0ffh,0ffh,0ffh ;64 - 67
- defb 003h,087h,000h,0ffh ;68 - 6b
- defb 01ch,01dh,01dh,0ffh ;6c - 6f defb defw ddb
- defb 01dh,01dh,000h,09dh ;70 - 73 org equ
- defb 0ffh,0ffh,0ffh,0ffh ;74 - 77
- defb 001h,087h,000h,009h ;78 - 7b
- defb 0ffh,0ffh,0ffh,0ffh ;7c - 7f
-
- defb 0ffh,0ffh,0ffh,0ffh ;a0 - bf
- defb 0ffh,0ffh,0ffh,0ffh ;a4 - a7
- defb 0ffh,0ffh,0ffh,0ffh ;a8 - ab
- defb 0ffh,0ffh,0ffh,0ffh ;ac - af
- defb 0ffh,0ffh,0ffh,0ffh ;b0 - b3
- defb 0ffh,0ffh,0ffh,0ffh ;b4 - b7
- defb 0ffh,0ffh,0ffh,0ffh ;b8 - bb
- defb 0ffh,0ffh,00fh,0ffh ;bc - bf
-
- defb 013h,00eh,013h,01dh ;c0 - c3
- defb 013h,00eh,001h,01eh ;c4 - c7
- defb 011h,0ffh,011h,0ffh ;c8 - cb
- defb 011h,01dh,001h,01eh ;cc - cf
- defb 012h,00fh,012h,09ch ;d0 - d3
- defb 012h,00fh,01ch,01eh ;d4 - d7
- defb 007h,0ffh,007h,001h ;d8 - db
- defb 007h,0ffh,001h,01eh ;dc - df
- defb 015h,018h,015h,089h ;e0 - e3
- defb 015h,018h,01ch,01eh ;e4 - e7
- defb 014h,098h,014h,00fh ;e8 - eb
- defb 014h,0ffh,01ch,01eh ;ec - ef
- defb 00ah,00dh,00ah,0ffh ;f0 - f3
- defb 00ah,00dh,01ch,01eh ;f4 - f7
- defb 016h,009h,016h,0ffh ;f8 - fb
- defb 016h,0ffh,01ch,01eh ;fc - ff
-
-
- defb 001h,001h,019h,001h ;8 bit logic and arithmetic
- defb 019h,019h,019h,019h ;
-
-
- defb 019h,019h,019h,019h ;shift and rotate
- defb 019h,019h,019h,019h ;
- defb 0ffh,01fh,01fh,01fh ;bit - res - set
-
- defb 0ffh,0ffh,0ffh,0ffh ;filler
-
- defb 01ah,01ah,01ah,01ah ;8 bit load
- defb 01ah,01ah,01ah,01ah ;
-
- page
- ;***********************************************************************
- ;*
- ;* table of second operands
- ;*
- ;***********************************************************************
-
-
- zopnd2:
- defb 0ffh,01dh,001h,0ffh ;00 - 03
- defb 0ffh,0ffh,01ch,0ffh ;04 - 07
- defb 00dh,00eh,08eh,0ffh ;08 - 0b
- defb 0ffh,0ffh,01ch,0ffh ;0c - 0f
- defb 0ffh,01dh,001h,0ffh ;10 - 13
- defb 0ffh,0ffh,01ch,0ffh ;14 - 17
- defb 0ffh,00fh,08fh,0ffh ;18 - 1b
- defb 0ffh,0ffh,01ch,0ffh ;1c - 1f
- defb 01bh,01dh,018h,0ffh ;20 - 23
- defb 0ffh,0ffh,01ch,0ffh ;24 - 27
- defb 01bh,018h,09dh,0ffh ;28 - 2b
- defb 0ffh,0ffh,01ch,0ffh ;2c - 2f
- defb 01bh,01dh,001h,0ffh ;30 - 33
- defb 0ffh,0ffh,01ch,0ffh ;34 - 37
- defb 01bh,009h,09dh,0ffh ;38 - 3b
- defb 0ffh,0ffh,01ch,0ffh ;3c - 3f
-
-
- defb 087h,006h,00eh,00eh ;40 - 43
- defb 0ffh,0ffh,0ffh,001h ;44 - 47
- defb 087h,007h,00eh,09dh ;48 - 4b
- defb 0ffh,0ffh,0ffh,001h ;4c - 4f
- defb 087h,004h,00fh,00fh ;50 - 53
- defb 0ffh,0ffh,0ffh,00ch ;54 - 57
- defb 087h,005h,00fh,09dh ;58 - 5b
- defb 0ffh,0ffh,0ffh,00bh ;5c - 5f
- defb 087h,002h,000h,0ffh ;60 - 63
- defb 0ffh,0ffh,0ffh,0ffh ;64 - 67
- defb 087h,003h,000h,0ffh ;68 - 6b
- defb 0ffh,0ffh,0ffh,0ffh ;6c - 6f
- defb 0ffh,0ffh,009h,009h ;70 - 73
- defb 0ffh,0ffh,0ffh,0ffh ;74 - 77
- defb 087h,001h,009h,09dh ;78 - 7b
- defb 0ffh,0ffh,0ffh,0ffh
-
- defb 0ffh,0ffh,0ffh,0ffh ;a0 - bf
- defb 0ffh,0ffh,0ffh,0ffh ;a4 - a7
- defb 0ffh,0ffh,0ffh,0ffh ;a8 - ab
- defb 0ffh,0ffh,0ffh,0ffh ;ac - af
- defb 0ffh,0ffh,0ffh,0ffh ;b0 - b3
- defb 0ffh,0ffh,0ffh,0ffh ;b4 - b7
- defb 0ffh,0ffh,0ffh,0ffh ;b8 - bb
- defb 0ffh,0ffh,00fh,0ffh ;bc - bf
-
- defb 0ffh,0ffh,01dh,0ffh ;c0 - c3
- defb 01dh,0ffh,01ch,0ffh ;c4 - c7
- defb 0ffh,0ffh,01dh,0ffh ;c8 - cb
- defb 01dh,0ffh,01ch,0ffh ;cc - cf
- defb 0ffh,0ffh,01dh,001h ;d0 - d3
- defb 01dh,0ffh,0ffh,0ffh ;d4 - d7
- defb 0ffh,0ffh,01dh,09ch ;d8 - db
- defb 01dh,0ffh,01ch,0ffh ;dc - df
- defb 0ffh,0ffh,01dh,018h ;e0 - e3
- defb 01dh,0ffh,0ffh,0ffh ;e4 - e7
- defb 0ffh,0ffh,01dh,000h ;e8 - eb
- defb 01dh,0ffh,0ffh,0ffh ;ec - ef
- defb 0ffh,0ffh,01dh,0ffh ;f0 - f3
- defb 01dh,0ffh,0ffh,0ffh ;f4 - f7
- defb 0ffh,018h,01dh,0ffh ;f8 - fb
- defb 01dh,0ffh,0ffh,0ffh ;fc - ff
-
- defb 019h,019h,0ffh,019h ;8 bit logic and arithmetic
- defb 0ffh,0ffh,0ffh,0ffh ;
-
- defb 0ffh,0ffh,0ffh,0ffh ;shift and rotate
- defb 0ffh,0ffh,0ffh,0ffh ;
- defb 0ffh,019h,019h,019h ;bit - res - set
-
- defb 0ffh,0ffh,0ffh,0ffh
-
- defb 019h,019h,019h,019h ;8 bit load
- defb 019h,019h,019h,019h
- page
-
- ;***********************************************************************
- ;*
- ;* table of op code names
- ;*
- ;***********************************************************************
-
-
- zopcnm:
- defb 'ADD ADC AND CALL'
- defb 'CCF CP CPD CPDR'
- defb 'CPI CPIRCPL DAA '
- defb 'DEC DI DJNZEI '
- defb 'EX EXX HALTIM '
- defb 'IN INC IND INDR'
- defb 'INI INIRJP JR '
- defb 'LD LDD LDDRLDI '
- defb 'LDIRNEG NOP OR '
- defb 'OTDROTIROUT OUTD'
- defb 'OUTIPOP PUSHRET '
- defb 'RETIRETNRL RLA '
- defb 'RLC RLCARLD RR '
- defb 'RRA RRC RRCARRD '
- defb 'RST SBC SCF SLA '
- defb 'SRA SRL SUB XOR '
- defb 'BIT RES SET ORG '
- defb 'DEFBDEFWDDB EQU '
-
-
-
-
- op1000:
- defb 0fdh,0ddh,0edh,0cbh
-
-
-
- pswbit: defb 10001000b ;minus
- defb 10000000b ;positive
- defb 00001100b ;even parity
- defb 00000100b ;odd parity
- defb 01001000b ;zero
- defb 01000000b ;not zero
- defb 00001001b ;carry
- defb 00000001b ;no carry
-
- pswmap: defb 18,07,19,17,21,20,10,22
- pswcnt equ $-pswmap
-
-
- regmap:
- defb 87h,01h,07h,06h,05h,04h
- defb 03h,02h,95h,93h,91h,18h
- defb 19h,81h,83h,85h,97h
-
- regptr:
- defb 0dh,0eh,0fh,00h
- defb 8dh,8eh,8fh,80h
- defb 0ah,09h,08h,10h
-
- siotbl: defb 0f5h,0f7h
-
- symflg: defb 0ffh ;symbol table flag 00 - table present
- ; ff - no table
-
- bsiz: ;dump block size storage
- bsizlo: defb 0 ; lo order
- bsizhi: defb 1 ; hi order
- blkptr: defw 100h ;dump block address
-
- loadb: defw 100h ;z8e load bias for lldr command
- loadn: defw 00 ;end of load address
-
- asmbpc: ;next pc location for assembly
- zasmpc: defw 100h ;next pc location for disassemble
- ;default at load time: start of tpa
- zasmfl: defw 00 ;first disassembled address on jdbg screen
-
-
- from:
- oprn01:
- rlbias:
- lines:
- exampt:
- endw:
- zasmnx: defb 0 ;address of next instruction to disassemble
- oprx01: defb 0
- bias:
- biaslo:
- zasmct: defb 0 ;disassembly count
- biashi:
- oprn02: defb 0
- oprx02:
- zasmwt: defw 0 ;disassembly count - working tally
- opnflg: defb 0 ;00 - operand 1 ff - operand 2 zasm
- ;and input character storage for interactive
- ;disassembly
- quoflg: defb 0
- wflag: defb 0ffh ;trace subroutine flag: nz - trace subs
- ; z - no trace
-
- nstep:
- nstepl: defb 0
- nsteph: defb 0
-
- sbps: defb 0 ;number of step breakpoints
- bps: defb 0 ;number of normal breakpoints
-
- zmflag: defb 0
- zasmf: defb 0
- execbf: ;execute buffer for relocated code
- jlines:
- parenf:
- nument: defb 0 ;number of digits entered
- delim: defb 0 ;argument delimeter character
- defb 0
- base10: defb 0
- jmp2jp: defb 0
- jmp2: defb 0
- dwrite:
- cflag: defb 0
-
- ikey:
- zasmkv:
- jmp: defb 0
- mexp:
- jmplo: defb 0
- strngf:
- jmphi: defb 0
- timer:
- first: defb 0
- regtrm: defb 0
- trmntr: defb 0
- isympt: defw 0
-
- jropnd:
- pass2: defw 0
-
- fndsym: defw 0
-
- if ASMB
- maxlen:
- else
- maxlen::
- endif
- defw 14
-
- maxlin: defw 62
-
- fwndow: defb 00
-
- nlmask: defb 00
-
- if ASMB
- case:
- else
- case::
- endif
- defb 0ffh ;flag to indicate case of output
- ;nz - lower z - upper
-
- jstepf: defb 0ffh ;00 - screen is intact, if user wants j
- ; single step no need to repaint screen,
- ; just move arrow.
- ;01 - user wants single-step j command
- ;else - j screen corrupted by non-j command
-
- lastro: defb 03
-
- if ASMB
- rowb4?:
- else
- rowb4?::
- endif
- if jterm ;my terminal uses xy addressing
- defb 0
- else ;most others use yx
- defb 1
- endif
-
- if ASMB
- mxycp:
- else
- mxycp::
- endif
- if jterm
- defb 1,9 ;jrs special (Datapoint 8227)
- else
- if aterm
- defb 4,ESC,'[2J'
- else
- defb 2,1bh,'=' ;ADM 3a in "standard" version
- defb 0,0,0,0,0,0,0,0
- endif
- endif
-
- xyrow: defb 0
- xycol: defb 0
-
- if ASMB
- row:
- else
- row::
- endif
- if jterm ;my terminal uses no bias for
- defb 0 ;cursor coordinates
- else
- defb ' ' ;bias for most other terminals
- endif
- if ASMB
- column:
- else
- column::
- endif
- if jterm ;see above
- defb 0
- else
- defb ' '
- endif
-
- wnwtab: defw 0
- wnwsiz: defw 0
-
- port: defw 0
-
- brktbl: defs (maxbp+2)*3
- psctbl: defs maxbp*2
-
-
- regcon:
- afreg:
- freg: defb 00
- defb 00
- bcreg: defw 00
- dereg: defw 00
- hlreg: defw 00
- afpreg: defw 00
- bcpreg: defw 00
- depreg: defw 00
- hlpreg: defw 00
- pcreg:
- pcregl: defb 00
- pcregh: defb 01
- spreg: defw 00
- ixreg: defw 00
- iyreg: defw 00
-
- regsiz equ $-regcon
-
- rreg: defb 00
- ireg: defb 00
-
-
- fstart: defw 0
- argbc: defw 0
- argbpt: defw argbf
-
- regsav equ $ ;storage for register contents in between bps
- ;while jdbg is in control
-
- window equ regsav+regsiz ;memory window save area
-
- argbsz equ 62
-
- argbf: defs argbsz
-
- fcb equ argbf+argbsz-36 ;cp/m file control block
- fcbnam equ fcb+1 ;start of file name in fcb
- fcbtyp equ fcbnam+8 ;start of file type in fcb
- fcbext equ fcbtyp+3 ;current extent number
- nfcb equ $ ;last byte of fcb plus one
-
- gpbsiz equ 164 ;size of general purpose buffer
-
- symbuf:
- objbuf: ;object code buffer
- rept gpbsiz
- defb 0
- endm
- inbfsz equ gpbsiz/2
- inbfmx equ objbuf+4 ;input buffer - max byte count storage
- inbfnc equ inbfmx+1 ; - number chars read in
- inbf equ inbfnc+1 ; - starting address
- inbfl equ inbfsz-1 ; - last relative position
- ninbf equ inbf+inbfl ; - address of last char
-
- prsbfz equ gpbsiz/2
- prsbf equ inbf+inbfsz ;parse buffer - starting address
- lprsbf equ prsbf+prsbfz-1 ; - last char of parse buf
- nprsbf equ lprsbf+1 ; - end address plus one
-
- nzasm equ $ ;end of disassembly buffer
- zasmbf equ nzasm-128 ;start of disassembly buffer
-
- defs 40
- stack:
- nmem equ ((($+255) and 0ff00h)-z8eorg) and 0ff00h
- ; was (256*(($+255)/256)-z8eorg) and 0ff00h
-
- if M80
- .list ;enable printer output for symbol table
- endif
- end