title Assembler/Dissasembler segment for DDTZ. ; MUST be integral # of pages. MUST be first segment linked. ; ; 88/04/25 Modified to use 64180 op codes. DDT Version 27. ; 2.7 DO NOT mix with earlier main system. LXI X and LXI Y ; now assemble. Most undocumented ops disassemble cbf. ; 87/07/11 Minor change so that MOV disassembles correctly when ; 2.6 run on 8080 (or under v20-80 under MSDOS). cbf. ; 86/02/12 Corrected to allow assembly of push/pop inx/dcx x/y ; still accepts faulty operands ldax h, ldax sp, etc. ; but any correction will cause DDTY (z80 false) to swell ; by another 256 bytes. This IS a crude assembler. cbf. ; cseg entry disassem; a=aflag entry assemble; pcnt just called entry keep; code file entry begin, .bdos; for overlay checks ; ; Main system routines useable by assembler/disassembler extrn dblblk, blank, couta, crlf extrn qbrk, csta, nextch, skipblks extrn t4hx, t2hx, tstr; a,f extrn qdelim; flags extrn getline; a,f,b,c,d,e extrn pcnt; a,f,d,e,h,l. Get params & count extrn nextparm; d,e,h,l extrn rdhex, rdhexc; a:=exit ch, de := value extrn chkop; all. de^ to op, exit hl^ past op extrn err; abort exit to DDT extrn foperate, dos; without disturbing regs. arg a extrn index, indexwd; a,f,h,l extrn casexfr; a,f,h,l + routine extrn sdem, ldem; hl^ =:= de; hl:=hl+2 extrn delesshl; a,f. comparator, unsigned ; extrn codesize, pages; To set relocation data ; ; external data areas used extrn disasmp, dendptr, aflag; for trace display extrn storeptr, exitstk, buff;[16] scratch vars. ; ; read only data from main system extrn opkind, zopkind; set by chkop extrn z80flg; set if running on Z80 extrn unloaded; memory not yet loaded ; true equ -1 false equ not true z80 equ true; false strips z80 code tfcb equ 05ch defdma equ 080h ; ; Transfers around system on startup. Overwritten later ; The next module should be the main program. begin: jmp ddtbgn; overlayed by serial no. ; ; Following for loader information. overlayed by serial no. dw codesize + (ddtbgn-begin) db pages + (ddtbgn-begin)/256 ; place connecter at bdos equiv locn .bdos: jmp $-$; becomes bdos connector ; assemble: dcr a; main system has just called pcnt jnz err; need exactly 1 param call nextparm shld disasmp ; " " ; Master assembly loop assm: lxi h,buff+4 xra a ! mov m,a; no index register inx h ! mov m,a; mark code buffer empty call crlf lhld disasmp xchg call typepc call blank call getline call skipblks rz; empty line, exit cpi '.' rz; exit call asmln cnc savecd; and advance disasmp jnc assm; no error call crlf mvi a,'?' call couta jmp assm ; if z80 ; Set flags on z80flg qz80: lda z80flg ora a ret endif ; subttl 'Disassembler' ; disassem: sta aflag ora a ! jz dsasm; 0 means do to dendptr lxi h,0ffffh shld dendptr; else set default end inr a ! jnz dsasm; >= 1 means show n lines inr a; -1 means 1 opcode, no header sta aflag; set lines to 1 lhld disasmp xchg push d call chkop; set up pointers, opkind pop d dcx h shld dendptr; point to last byte of opcode inx h; de := disasmp, hl^ next opcode jmp dsasm2 ; ; main disassembly loop dsasm: call qbrk lxi h,aflag mov a,m ora a ! jz dsasm1; using dendptr dcr m rz; lines done dsasm1: lhld dendptr xchg lhld disasmp call delesshl xchg rc; past end marker call craddr mvi c,-10; field size to use call showcd; hl^ next opcode, de^ this opcode ; " " opkind/z80flg set dsasm2: shld disasmp; de := this, disasmp := next lxi h,dsasm push h; set return on stack lxi h,opcd1 ldax d mvi b,ni1 mvi c,'H'; default index reg. id call stbl jz t4chb; all one byte no operand opcodes mvi b,ni2 call stbl jz immops; all immediate to a opcodes mvi b,ni3 call stbl jz wdops; all immediate word opnd opcodes if z80 call qz80 ldax d; was jz dsasm3 ! ldax d; 87/7/11 jz dsasm3 mvi b,ni4 call stbl jz t4chb; one byte z80 only opcodes endif dsasm3: ani 0c0h lxi h,mmov+1 cpi 040h ! jz movops cpi 080h ! jz aritop dsasm4: ldax d ! ani 0c7h; entry for indexed inrdcr sui 4 ! jz inrops dcr a ! jz dcrops dcr a ! jz mviops ldax d ani 0c0h ! jz dsasm6 ldax d ! ani 7 sui 2 ! jz jmpcc sui 2 ! jz callcc sui 3 ! jz rstop ldax d ani 8 ! jnz prefix; leaving cb,d9,dd,ed,fd dsasm5: ldax d ! ani 0c5h; entry for push/pop x/y jmp wdrgs; pop, push ; dsasm6: ldax d ! ani 7 if z80 jz jrops; exaf removed earlier else jz bad endif dsasm7: ldax d ! ani 0fh; entry for inx/dcx x/y dcr a ! jz lxiops inr a ; " " ; one byte opcodes operating on word registers ; a,f,b,h,l wdrgs: lxi h,mstax mvi b,nwdr; stax, ldax, inx, dcx, dad, pop, push call stbl wdrgs2: call t4chb; entry from dadc/dsbc ldax d ani 0ah ! jnz wdrgid; not pop/push ldax d ! ani 030h cpi 030h lxi h,mpsw+1 ! mvi a,3 jz tchars ; " " ; show word register id ; a,f wdrgid: call toreg ani 6 cpi 4 ! jz txrgid cpi 6 ! jnz tregid push h lxi h,msp+1 mvi a,2 call tchars pop h ret ; ; All above exits return to dsasm via stacked return address ; In general, de points to next byte to disassemble, c holds ; an index register specifier (H, X, or Y). When operands ; are listed de is normally destroyed. The z80 only opcodes ; are enable/disabled by the main system Z80FLG variable. The ; system depends on classification of operators by the main ; system CHKOP procedure, which also returns the opcode length. ; ; lxi R opn lxiops: lxi h,mlxi+1 call t4chb call wdrgid call comma jmp wdopnd ; if z80 ; relative jump z80 ops jrops: call qz80 jz bad ldax d lxi h,mdjnz mvi b,njrs call stbl; must succeed call t4chb inx d ! ldax d mov l,a; convert rel to absolute rlc sbb a mov h,a inx d dad d jmp t4hx endif ; ; restart opcode rstop: lxi h,mrst+1 ; " " ; display mnemnonic and middle 3 bits of (a) as digit 0..7 ; a,f,h,l num: call t4chb call toreg adi '0' jmp couta ; ; conditional calls callcc: mvi a,'C' jmp jmpcc1 ; ; conditional jumps jmpcc: mvi a,'J' jmpcc1: call couta call toreg mov l,a ! add a ! add a ! add l; *5 lxi h,mcrtn+2 call index mvi a,2 call tchars call dblblk jmp wdopnd ; ; inr/dcr ops ; a,f,h,l (de on index) inrops: lxi h,minr+1 jmp dcrop1 dcrops: lxi h,mdcr+1 dcrop1: call t4chb if z80 mov a,c cpi 'H' jnz ixdisp endif ; " " lftrid: call toreg jmp tregid ; ; arithmetic immediate ops ; a,f,b,h,l aritop: call aritmn ; " " ; operations on single register. hl point to mnemonic ; a,f bregop: call t4chb ; " " ; show from reg id ; a,f fromrg: ldax d ! ani 7 jmp tregid ; ; get pointer to arithmetic op mnemnonic ; a,f,b,h,l aritmn: lxi h,madd+1 ; " " ; index to mnemonic via hl^ on toreg field mnmix: ldax d ! ani 038h; index by 5*toreg field rrc mov b,a rrc ! rrc; div 8 and mul 5 add b jmp index ; ; immediate to a opcodes ; a,f,d,e immops: call t4chb jmp bopnd ; ; immediate 1 byte operators, with reg. id mviops: lxi h,mmvi+1 ; " " ; Mnemnonic, register, immediate byte value rgiops: call t4chb call lftrid ; " " ; show immediate as 2nd operand ; a,f,d,e imopnd: call comma ; " " ; list byte operand ; a,f,d,e bopnd: inx d ! ldax d jmp t2hx ; ; word ops. hl is opmnem pointer, output 1 word operand ; a,f,d,e,h,l wdops: call t4chb ; " " ; show word operand ; a,f,d,e,h,l wdopnd: inx d xchg call ldem xchg jmp t4hx ; ; move ops ; a,f,h,l movops: call t4chb call lftrid ; " " ; Show source register id. ; a,f source: call comma ldax d ! ani 7 ; " " ; convert a into regid listing ; a,f tregid: push h lxi h,mreg call index mov a,m pop h jmp couta ; ; extract middle bits (to reg id) ; a,f toreg: ldax d ani 38h rrc ! rrc ! rrc ret ; ; write 4 chars from hl^ with trailing blank ; a,f,h,l t4chb: call t4char jmp blank ; ; show code bytes at de^ up with at least one trailing blank. ; Set up opkind, hl := endptr ; -c specifies minimum field to use. ; a,f,b,c,d,e showcd: push b ! push d call chkop pop d ! pop b ; " " ; display code at de^ thru hl-1^, min field -c bytes ; at least one trailing blank ; a,f,b,c dspcd: push d xchg dspcd1: mov a,m call t2hx inx h ! inr c ! inr c mov a,l ! cmp e jnz dspcd1 dspcd2: call blank inr c ! jm dspcd2 xchg pop d ret ; ; crlf, show address de. ; a,f,h,l craddr: call crlf ; " " ; show address de. ; a,f typepc: xchg call t4hx xchg jmp dblblk ; ; output 4 chars from hl^ up ; a,f,h,l t4char: mvi a,4 ; " " ; output a chars from hl^ up ; a,f,h,l tchars: push b mov b,a tchrs1: mov a,m call couta inx h ! dcr b jnz tchrs1 pop b ret ; comma: mvi a,',' jmp couta ; ; search opcode table hl^ for a, max b entries. ; Z flag if found, when hl point to mnemnonic entry ; f,b,h,l stbl: cmp m ! inx h rz inx h ! inx h ! inx h ! inx h dcr b ! jnz stbl dcr b; remove z flag, not found ret ; ; show index register id ; a,f txrgid: mov a,c jmp couta ; ; prefixed z80 ops prefix: if z80 call qz80; (not d9 if z80 running) jz bad lhld disasmp; check for length 1 dcx h call delesshl; if so jz bad; invalid z80 opcode ldax d cpi 0cbh ! jz bitpic cpi 0edh ! jz xtend ; " " ; index register operations, prefix 0ddh/0fdh ani 020h rlc ! rlc ! rlc adi 'X' mov c,a; save index identifier inx d; point to specifier lda zopkind dcr a; type 0 never valid lxi h,ixcase jmp casexfr ; ; ** CAUTION ** locked to main table in DDTZ. Notes from main ixcase: dw dadx; 1 (No 0th value used) 9 19 29 39 dw slixd; 2 lhld shld 22 2a dw dsasm7; 3 inxdcxx 23 2b dw dsasm4; 4 inrdcrx 34 35 dw mvix; 5 mvi m 36 dw movrx; 6 mov rr,m 46 43 56 53 66 63 (76) 7e dw movxr; 7 mov m,e 73 dw movxr; 8 mov h,h, mov m,h 64 74 (64180) dw movxr; 9 mov m,r 70 71 72 (73 74) 75 (76) 77 dw arithx; 10 arith m 86 83 96 9e a6 ae b6 be dw lxiops; 11 lxi h 21 dw bitx; 12 set/res etc cb dw xtix; 13 xthl e3 dw dsasm5; 14 popushx e1 e5 dw xtix; 15 pchl e9 dw xtix; 16 sphl f9 dw bad; 17 extension ed dw undoc; 18 mov rr,e 43 4b 53 5b 63 6b 73 7b dw undoc; 19 mov (retn,reti) 45 4d dw bad; 20 x/y prefixes dd fd dw bad; 21 exaf,nop 0 8 dw bad; 22 jr/djnz (0 8) 10 18 20 28 30 38 dw bad; 23 jmp 0c3 dw bad; 24 call 0cd dw bad; 25 lda sta 32 3a dw bad; 26 ret 0c9 dw bad; 27 rst c7 cf d7 df e7 ef f7 ff dw mvixy; 28 mvi 6 e 16 1e 26 2e (36) 3e dw bad; 29 aritopi c6 ce d6 de e6 ee f6 fe dw bad; 30 j(ccd) c2 ca d2 da e2 ea f2 fa dw bad; 31 c(ccd) c4 cc d4 dc e4 ec f4 fc dw bad; 32 r(ccd) c0 c8 d0 d8 e0 e8 f0 f8 dw bad; 33 lxi 1 11 (21) 31 dw bad; 34 in/out d3 db dw undoc; 35 the rest, all 1 byte ; ; undocumented, except the MVI xh/xl/yh/yl,value opcodes. C is 'X' or 'Y' undoc: call movx ! rnc jmp bad ; aritx: sui 80h ! cmc ! rc; Not original 80..bf ldax d ! ani 7 call hlm ! rc; reject m stc ! rnz; reject other than h/l lxi h,xtraops+1 mov a,c ! cpi 'X' jz aritx1 lxi h,ytraops+1 aritx1: call mnmix jmp bregop ; xinrdcr: lxi h,xidrops+1 mov a,c ! cpi 'X' jz xidr1 lxi h,yidrops+1 xidr1: ldax d ! ani 1 ! mov b,a add a ! add a ! add b; *5 call index jmp inps1; mnem, leftreg output ; ; One register must be h or l, and none may be m movx: ldax d ! ani 0f6h cpi 024h ! jz xinrdcr ldax d ! ani 0c0h sui 040h ! rc jnz aritx ldax d ! call toreg call hlm ! rc; reject m jz movx2; have hl, other must be non h/l ldax d ! ani 7 call hlm ! rc; reject m stc ! rnz; no h/l found jmp movx3 movx2: ldax d ! ani 7 call hlm ! rc; reject m stc ! rz; both h/l found ; " " ; Regs ok, now act like a mov, with appropriate mnemnonic movx3: lxi h,movxops+1 mov a,c ! cpi 'X' jz movx4 lxi h,movxops+6 movx4: jmp movops ; ; check a for h,l,or m. Carry for m, zero for h or l ; a,f hlm: cpi 6 ! stc ! rz; m cpi 4 ! rz; h cpi 5 ! stc ! cmc; z flag for l ret ; ; Undocumented mvi xh/xl/yh/yl,value opcodes (MVIX h/l) mvixy: ldax d; c has 'X' or 'Y', de points to 2nd op byte ani 0f7h cpi 026h ! jnz bad lxi h,mvixops+1 mov a,c ! cpi 'X' jz mvixy1 lxi h,mvixops+6; else MVIY mvixy1: jmp rgiops ; mvix: lxi h,mmvi+1 call t4chb call ixdisp jmp imopnd ; bitx: inx d; past the 0cbh inx d; past the displacement ldax d dcx d ani 7 cpi 6 ! jz bitpic dcx d ! dcx d jmp bad ; slixd: ldax d ani 8 lxi h,msixd+1 jz slixd1 lxi h,mlixd+1 slixd1: mvi a,2 call tchars mov a,c call couta mvi a,'D' call couta call blank jmp wdopnd ; xtix: ldax d lxi h,mxtix mvi b,nxtixs call stbl ; " " mnx: mvi a,3 call tchars jmp txrgid ; movrx: lxi h,mmov+1 call t4chb call lftrid call comma jmp ixdisp ; movxr: lxi h,mmov+1 call t4chb call ixdisp dcx d jmp source ; ; arithmetic indexed immediate ops arithx: call aritmn call t4chb ; " " ; show indexed operand ; a,f,d,e ixdisp: mvi a,'[' call couta call txrgid inx d ! ldax d ora a ! jp ixdp1 mvi a,'-' call couta ldax d ! cma ! inr a jmp ixdp2 ixdp1: mvi a,'+' call couta ldax d ixdp2: call t2hx mvi a,']' jmp couta ; dadx: lxi h,mdad+1 call mnx call blank jmp wdrgid ; ; Prefix 0cbh, bitpicking bitpic: inx d ldax d cpi 040h ! jc sftops ani 0c0h lxi h,mbp mvi b,nbps call stbl; must work mov a,c call num call comma jmp sftop2 ; ; shift operations sftops: ldax d ! ani 038h lxi h,msft mvi b,nsfts call stbl; must work ; " " ; operations on single register. hl points to mnemonic sftop1: call t4chb ; " " ; show from reg id sftop2: mov a,c cpi 'H' ! jz fromrg dcx d ! dcx d jmp ixdisp ; ; extension ops prefix 0edh xtend: inx d ! ldax d lxi h,mtstip+1 cpi 064h ! jz immops lxi h,mtsiop+1 cpi 074h ! jz immops ani 0c7h ! jz in0s; 00, 08, 10, 18, 20, 28, 30, 38 dcr a ! jz out0s; 01, 09, 11, 19, 21, 29, 31, 39 lxi h,mtstp+1; TST sui 3 ! jz inps1; 04, 0c, 14, 1c, 24, 2c, 34, 3c sui 03ch ! jz inps; 040 dcr a ! jz outps; 041 dcr a ! jz dadc; 042 dcr a ! jz xxlds; 043 ldax d ! ani 0cfh lxi h,mmlt+1 sui 04ch ! jz wdrgs2; 04c,05c,06c,07c ldax d lxi h,mxtop mvi b,nxtops call stbl jz t4chb dcx d endif ; " " ; Unidentifiable op codes bad: lxi h,badop+1 mvi a,3 call tchars lhld disasmp; the next opcode marks end mvi c,0; use minimum field jmp dspcd; display de..hl-1 ; if z80 inps: lxi h,minp+1 inps1: call t4chb jmp lftrid ; outps: lxi h,moutp+1 jmp inps1 ; in0s: lxi h,min0p+1 jmp rgiops ; out0s: lxi h,mout0p+1 call t4chb inx d ! ldax d ! dcx d call t2hx call comma jmp lftrid ; ; word add/subtract/mlt with carry dadc: ldax d ! ani 08 lxi h,mdadc+1 jnz wdrgs2 lxi h,mdsbc+1 jmp wdrgs2 ; xxlds: ldax d lxi h,mlsxd mvi b,nlsxds call stbl; must work jmp wdops endif ; subttl 'Symbol Tables' ; ; The order of sections is wired into the assembler code opcd1: db 000h,'NOP ', 007h,'RLC ', 00fh,'RRC ', 017h,'RAL ' db 01fh,'RAR ', 027h,'DAA ', 02fh,'CMA ', 037h,'STC ' db 03fh,'CMC ', 076h,'HLT ', 0c9h,'RET ', 0e3h,'XTHL' db 0e9h,'PCHL', 0ebh,'XCHG', 0f3h,'DI ', 0f9h,'SPHL' db 0fbh,'EI ' ; mcrtn: db 0c0h,'RNZ ', 0c8h,'RZ ', 0d0h,'RNC ', 0d8h,'RC ' db 0e0h,'RPO ', 0e8h,'RPE ', 0f0h,'RP ', 0f8h,'RM ' ncrtns equ ($-mcrtn)/5 ni1 equ ($-opcd1)/5 ; opcd2: db 0c6h,'ADI ', 0ceh,'ACI ', 0d3h,'OUT ', 0d6h,'SUI ' db 0dbh,'IN ', 0deh,'SBI ', 0e6h,'ANI ', 0eeh,'XRI ' db 0f6h,'ORI ', 0feh,'CPI ' ni2 equ ($-opcd2)/5 ; opcd3: db 022h,'SHLD', 02ah,'LHLD', 032h,'STA ', 03ah,'LDA ' db 0c3h,'JMP ', 0cdh,'CALL' ni3 equ ($-opcd3)/5 ; if z80 opcd4: db 008h,'EXAF', 0d9h,'EXX ' ni4 equ ($-opcd4)/5 endif ; madd: db 080h,'ADD ', 088h,'ADC ', 090h,'SUB ', 098h,'SBB ' db 0a0h,'ANA ', 0a8h,'XRA ', 0b0h,'ORA ', 0b8h,'CMP ' nadds equ ($-madd)/5 ; minr: db 004h,'INR ' mdcr: db 005h,'DCR ' nrops equ ($-minr)/5 ; mmvi: db 006h,'MVI ' mmov: db 040h,'MOV ' mrst: db 0c7h,'RST ' ; if z80 mdjnz: db 010h,'DJNZ', 018h,'JR ', 020h,'JRNZ', 028h,'JRZ ' db 030h,'JRNC', 038h,'JRC ' njrs equ ($-mdjnz)/5 endif ; mlxi: db 001h,'LXI ' ; mstax: db 002h,'STAX', 00ah,'LDAX' mdad: db 009h,'DAD ' nwdrxx equ ($-mstax)/5 db 003h,'INX ', 00bh,'DCX ', 0c1h,'POP ', 0c5h,'PUSH' nwdr equ ($-mstax)/5 nwdrxy equ nwdr-nwdrxx ; if z80 ; additional to allow input parsing. not used in disassembly mdadxy: db 009h,'DADY', 009h,'DADX' ndadxys equ ($-mdadxy)/5 ; ; used in disassembly msft: db 000h,'RLCR', 008h,'RRCR', 010h,'RALR', 018h,'RARR' db 020h,'SLAR', 028h,'SRAR', 030h,'SLLR', 038h,'SRLR' nsfts equ ($-msft)/5 ; mbp: db 040h,'BIT ', 080h,'RES ', 0c0h,'SET ' nbps: equ ($-mbp)/5 ; ; additional to allow input parsing, not used in disassembly mxtiy: db 0e3h,'XTIY', 0e9h,'PCIY', 0f9h,'SPIY' nxtiys: equ ($-mxtiy)/5 ; ; used in disassembly mxtix: db 0e3h,'XTIX', 0e9h,'PCIX', 0f9h,'SPIX' nxtixs equ ($-mxtix)/5 ; ; additional to allow input parsing, not used in disassembly msiyd: db 022h,'SIYD', 02ah,'LIYD' nslyds equ ($-msiyd)/5 ; ; used in disassembly msixd: db 022h,'SIXD' mlixd: db 02ah,'LIXD' nslxds equ ($-msixd)/5 ; mlsxd: db 043h,'SBCD', 04bh,'LBCD', 053h,'SDED', 05bh,'LDED' db 063h,'shld', 06bh,'lhld', 073h,'SSPD', 07bh,'LSPD' nlsxds equ ($-mlsxd)/5 ; mdsbc: db 042h,'DSBC' mdadc: db 04ah,'DADC' mmlt: db 04ch,'MLT ' ndadcs equ ($-mdsbc)/5 ; min0p: db 000h,'IN0 ' mout0p: db 001h,'OUT0' mtstp: db 004h,'TST ' minp: db 040h,'INP ' moutp: db 041h,'OUTP' mtstip: db 064h,'TSTI' mtsiop: db 074h,'TSIO' niops equ ($-min0p)/5 ; mxtop: db 044h,'NEG ', 045h,'RETN', 046h,'IM0 ', 047h,'LDIA' db 04dh,'RETI', 04fh,'LDRA', 056h,'IM1 ', 057h,'LDAI' db 05eh,'IM2 ', 05fh,'LDAR', 067h,'RRD ', 06fh,'RLD ' db 076h,'SLP ' db 083h,'OTIM', 08bh,'OTDM', 093h,'OIMR', 09bh,'ODMR' db 0a0h,'LDI ', 0a1h,'CCI ', 0a2h,'INI ', 0a3h,'OTI ' db 0a8h,'LDD ', 0a9h,'CCD ', 0aah,'IND ', 0abh,'OTD ' db 0b0h,'LDIR', 0b1h,'CCIR', 0b2h,'INIR', 0b3h,'OTIR' db 0b8h,'LDDR', 0b9h,'CCDR', 0bah,'INDR', 0bbh,'OTDR' nxtops equ ($-mxtop)/5 mvixops: db 026h,'MVIX', 026h,'MVIY'; undocumented codes movxops: db 040h,'MOVX', 040h,'MOVY' xtraops: db 080h,'ADXR', 088h,'ACXR', 090h,'SUXR', 098h,'SBXR' db 0a0h,'NDXR', 0a8h,'XRXR', 0b0h,'ORXR', 0b8h,'CPXR' ytraops: db 080h,'ADYR', 088h,'ACYR', 090h,'SUYR', 098h,'SBYR' db 0a0h,'NDYR', 0a8h,'XRYR', 0b0h,'ORYR', 0b8h,'CPYR' xidrops: db 024h,'INRX', 025h,'DCRX' yidrops: db 024h,'INRY', 025h,'DCRY' nxyxops equ ($-mvixops)/5 endif badop: db 0ffh,'??= ' ; mreg: db 'BCDEHLMA' if z80 db '[XY' endif nregs equ $-mreg ; mpsw: db 031h,'PSW '; added 1 bit in value msp db 030h,'SP ', 020h,'H '; <