TITLE Monitor Program ; Magnum Z80 monitor ; Micro Design Associates ; 11/82 coded by Lynn E. Diel ; modified by D. Wallen & D. Delwood ; 08/13/83 added magnum boot routine ; 08/13/83 changed help display ; 09/30/83 modified boot routine for 5/8 switch ; 10/20/83 removed above ; 10/20/83 added separate 5/8 boot routines - changed help to reflect it ; 10/20/83 moved stack back to 0100h ; 10/20/83 boot routines pre-read the bios to find loading address ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Equates for program ; Standard console port's for V-44 Magnum ; CONS EQU 3 ;console status port COND EQU 2 ;console data port TBE EQU 80H ;transmitter buffer empty mask RDA EQU 40H ;receiver data available mask STPR EQU 100h ;location of stack DESTIN EQU 0f800H ;monitor after shadow ZERO EQU 00000H ;shadow address ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Command Summary ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; 8 boots system from 8 inch drive ; 5 boots system from 5 1/4 inch drive ; D adr1 adr2 Display memory (HEX & ASCII) ; F adr1 adr2 dd Fill memory ; G Go and execute ; H HELP menu ; I PP Input from a port ; M adr1 adr2 adr3 Block move ; O PP DD Output to a port ; P Program memory ; S adr1 adr2 Byte search ; T adr1 adr2 Test memory (destructive) ; W adr1 adr2 dd dd Word search ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ;.phase 0f800h ; include to make ROM .Z80 START: LD SP,STPR ;Set up stack for first call SIGNON: LD HL,MESG ;load signon message CALL PRSTR ;let user know BEG: LD SP,STPR ;This will reset stack each pass CALL CRLF LD A,']' ;load prompt CALL COUT ;print it LD A,'>' ;load prompt CALL COUT ;print it CALL CIN ;check keyboard PUSH AF ;save it on the stack CALL SPCE ;separate prompt from function POP AF ;restore character CP 35H ;if 5 JP Z,BOOT5 ;then boot 5 inch disk CP 38H ;if 8 JP Z,BOOT8 ;then boot 8 inch disk AND 5Fh ;Convert character to upper case CP 44H ;if D CALL Z,DISP ;display memory (HEX & ASCII) CP 46H ;if F CALL Z,FILL ;fill memory CP 47H ;if G CALL Z,EXEC ;go and execute CP 48H ;if H JP Z,HELP ;display help screen CP 49H ;if I CALL Z,PINP ;input from a port CP 4DH ;if M CALL Z,MOVB ;move a block of memory CP 4FH ;if O CALL Z,POUT ;output to a port CP 50H ;if P CALL Z,PGM ;program memory CP 53H ;if S CALL Z,SEARCH ;byte search memory CP 54H ;if T CALL Z,TMEM ;test memory (destructive) CP 57H ;if W CALL Z,SEARCH ;word search JP BEG ;start over ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Execute routine ; 'G' address or 'J' address ; ; HL-->address to transfer control to ; DE-->start of Monitor ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; EXEC: CALL BINHEX ;fetch address from keyboard EX DE,HL ;move it to HL LD DE,START ;load DE with start address PUSH DE ;store it on top of stack JP (HL) ;jump to address --> HL ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; HEX to binary routine ; convert up to 4 HEX digits to binary ; ; On exit the following registers are set up ; HL--> starting address ; DE--> ending address ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; HEX2: CALL BINHEX ;get starting address CALL BINHEX ;get ending address RET ;return to callet ; BINHEX: LD C,4 ;C contains # of character to be read BINH0: LD HL,0 ;zero all sixteen bits BINH1: CALL CIN ;fetch a byte CP 20H ;if a space JR Z,EXCHNG ;then swap CP 30H ;if less than or equal to zero JP C,BEG ;then start over BINH2: CP 3AH ;if greater than or equal to 9 CALL NC,ALPH ;then convert to HEX ADD HL,HL ;shift bits ADD HL,HL ;to left ADD HL,HL ;via the ADD ADD HL,HL ;instruction SUB 48 ;minus the ascii bias CP 10 ;if character is greater than or equal JR C,ALP1 ;then convert to HEX SUB 7 ;minus the Alpha bias ; ALP1: ADD A,L ;add low byte to accumulator LD L,A ;stor it in 'L' DEC C ;bump the address counter negativly JR NZ,BINH1 ;if less than 4, then keep reading EXCHNG: EX DE,HL ;swap HL=start / DE=end ; SPCE: LD A,20H ;load a space ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Character output routine ; stack contains character to be outputed ; standard Magnum V-44 IO's ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; COUT: PUSH AF ;save character before getting status ; CLOP: IN A,(CONS) ;is the transmitter buffer empty? CPL ;invert status for positive logic AND 01H ;test TBE JR NZ,CLOP ;if transmitter full, then check it again POP AF ;restore the character OUT (COND),A ;display it to the world RET ;to whom calleth ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Prints a string to console device ; HL--> Message to be displayed ; '$' used as end of string indicator ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PRSTR: LD A,(HL) ;move cahracter to be outputed in Acc CP 24H ;use '$' as End of String delimiter RET Z ;if EOS then return CALL COUT ;else keep sending INC HL ;bump message pointer to next character JR PRSTR ;loop until completed ; ; * * * * * * * ; Bar routine is used for the separation of ; HEX and ASCII during dump routine ; * * * * * * * ; BAR: LD A,07CH ;load the vertical bar '|' JR COUT ;display it ; ;* * * * * * * * * * * * ; Colon routine ; Prints a colon after address ;* * * * * * * * * * * * ; COLON: LD A,03AH ;load a colon ':' JR COUT ;display it to user ; ;* * * * * * * * * * * * ; Carriage return & Line feed Routine ; Outputs a 0Dh and a 0Ah ;* * * * * * * * * * * * ; CRLF: LD A,0DH ;load a carriage return CALL COUT ;execute it LD A,0AH ;load a line feed JR COUT ;move down one line ; ALPH: CP 41H ;if character is < than or = to 'A' JP C,BEG ;then start over AND 5FH ;else convert it to upper case CP 47H ;if character is > than or = to 'H' JP NC,BEG ;then start over RET ;else accept the character ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Read console routine ; Wait until a key is pressed ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; CIN: IN A,(CONS) ;fetch console status CPL ;invert for positive logic AND 02H ;check Reciever Data Available flag JR NZ,CIN ;if reset then check again IN A,(COND) ;fetch character from console AND 7FH ;strip off parity CP 03 ;if control 'C' JP Z,BEG ;then abort command CP 08H ;if a backspace (control 'H') JR Z,BCKSPC ;then send console a backspace JR COUT ;else echo character to screen ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Read from console ; Wait if only a single key is selected ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; CIN1: IN A,(CONS) ;fetch console status CPL ;convert to positive logic AND 02H ;check Reciever Data Available flag RET NZ ;if reset, then return IN A,(COND) ;else fetch the character AND 7FH ;strip off parity CP 03 ;if control 'C' JP Z,BEG ;then abort RET ;else return to caller ; ;* * * * * * * * * * * * ; BACKSPACE ROUTINE ;* * * * * * * * * * * * ; BCKSPC: LD A,08H ;load a backspace character CALL COUT ;execute it INC C ;bump digit counter JR CIN ;continue at console input ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; SCROLL ROUTINE ( space bar start / stop ) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; PAUSE: CALL CIN1 ;check console and return here CP 20H ;if not a space RET NZ ;then continue ; PLOOP: CALL CIN1 ;ckeck console and return here CP 20H ;if not a space JR NZ,PLOOP ;then wait until it is RET ;also return ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Memory test routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; TMEM: CALL HEX2 ;fetch start and ending address LD BC,0B6D9H ;load BC with 'worst' case HEX value ; MEMLP: CALL RNDOM ;fetch a random number PUSH BC ;save 'worst' case PUSH HL ;save start address PUSH DE ;save ending address ; TLOP: CALL RNDOM ;get a random number LD (HL),B ;load it into a memory cell CALL BUMP ;check if start address = end address JR NZ,TLOP ;no then loop until they do POP DE ;reload end address POP HL ;reload start address POP BC ;reload 'worst' case HEX number PUSH HL ;put start addr back PUSH DE ;put end addr back ; RLOP: CALL RNDOM ;get a random number LD A,(HL) ;fetch the memory cell's contents CP B ;are the equal ? ? ? CALL NZ,ERROR ;no, then print error CALL BUMP ;else see if finished JR NZ,RLOP ;no, then loop PUSH AF ;else CALL CIN1 ;check for a control 'C' LD HL,TMSG ;load pass completed CALL PRSTR ;tell user POP AF ;recover the data POP DE ;reload end address POP HL ;reload start address JR MEMLP ; ;* * * * * * * * * * * * ; Random number generator routine ;* * * * * * * * * * * * RNDOM: LD A,B ;get seed number AND 0B4H ;mask bits AND A ;clear carry flag JP PE,RNDM1 ;if even parity, exit SCF ;set carry flag ; RNDM1: LD A,C ;load second half of seed number RLA ;rotate carry bit in LD C,A ;load new seed number LD A,B ;fetch first seed number RLA ;rotate carry bit in LD B,A ;load new seed number RET ;return with new random number in BC ; ;* * * * * * * * * * * * ; Print out ERROR routine ; Prints address & check for pause ;* * * * * * * * * * * * ; PTAD: CALL CRLF ;print a carriage return, line feed CALL PAUSE ;test for wait command LD A,H ;fetch high address CALL PT2 ;display address LD A,L ;fetch low address CALL PT2 ;display it CALL COLON ;separate addr & error with a ':' CALL SPCE ;and a space RET ;return to caller ; ERROR: PUSH AF ;save character read CALL PTAD ;display error address LD A,B ;fetch data written CALL PT2 ;display it CALL SPCE ;separate with a space PUSH HL ;save error address POP HL ;restore error address POP AF ;restore actual character read ; ;* * * * * * * * * * * * ; Routine to print two bytes to console ;* * * * * * * * * * * * ; PT2: PUSH AF ;save data CALL BINH ;convert it POP AF ;restore data JR BINL ;exit at binary low ; BINH: RRA ;move bits right RRA RRA RRA ; BINL: AND 0FH ;mask off upper bits ADD A,48 ;add ASCII offset CP 03AH ;if character < than or = to 9 JP C,COUT ;then display it ADD A,7 ;else add HEX offset JP COUT ;and display it ; ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Display memory contents with HEX and ASCII ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; DISP: CALL HEX2 ;fetch start and ending address ; DISP1: LD C,16 ;load for 16 HEX characters CALL PTAD ;print address for each line PUSH HL ;save address PUSH DE ;save end address ; LP2: LD A,(HL) ;fetch cells contents CALL PT2 ;display it CALL SPCE ;separate with a space ; LP3: INC HL ;bump pointer to next cell DEC C ;decrement column counter JR NZ,LP2 ;loop until 16 digits are displayed ; ASCD: POP DE ;restore end address POP HL ;restore current address LD C,16 ;load for 16 ASCII characters CALL BAR ;separate HEX and ASCII CALL SPCE ;with a vertical bar and space LP4: LD A,(HL) ;fetch cells contents CP 07FH ;if it's the low order DELETE char JR Z,LP4A ;then print a period '.' CP 0FFH ;if it's the high order DELETE char JR Z,LP4A ;then print a period '.' AND 60H ;strip off all control characters JR NZ,NCTRL ;exit if not a control character LP4A: LD A,2EH ;load a period '.' CALL COUT ;display it JR LP5 ;continue at loop 5 ; NCTRL: LD A,(HL) ;fetch cell's contents AND 7FH ;strip off parity CALL COUT ;display it ; LP5: CALL BUMP ;bump pointers RET Z ;return to caller if finished DEC C ;bump column pointer JR NZ,LP4 ;loop until finished CALL SPCE ;separate ASCII chracters with CALL BAR ;a space and vertical bar JR DISP1 ;repeat ; ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Program Memory Routine ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; PGM: CALL BINHEX ;fetch start address EX DE,HL ;move start address to HL CALL CRLF ;do a carriage return and line feed ; PGLP: CALL PTAD ;print the current address LD A,(HL) ;fetch the memory cell CALL PT2 ;print the cell's contents LD A,2DH ;load a dash '-' CALL COUT ;print the de-limiter ; PGLP1: CALL CIN ;fetch a character from the console CP 20H ;if a space JR Z,CON2 ;then leave cell alone ! ! ! CP 0DH ;if not a carriage return JR NZ,CON1 ;then continue on DEC HL ;else move pointer back one count JR PGLP ;loop until user exits ; CON1: EX DE,HL ;store address in DE LD HL,0 ;zero HL for conversion LD C,2 ;load a 2 count CALL BINH1+3 ;convert to HEX LD (HL),E ;store it in the memory cell ; CON2: INC HL ;bump address pointer JR PGLP ;loop until user exits ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Compare HL and DE (start & ending address) and bump counter ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; BUMP: LD A,E ;get low byte or end address SUB L ;subtract low byte of current address JR NZ,BMP1 ;if end is > than start then bump LD A,D ;else fetch high byte of end address SBC A,H ;if start = end set carry flag ; BMP1: INC HL ;bump current addres pointer by one RET ;return to caller ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Fill memory routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; FILL: CALL HEX2 ;fetch start and ending address PUSH HL ;save start address LD C,2 ;load a 2 count CALL BINH0 ;fetch the data to be used EX DE,HL ;swap start and end EX (SP),HL ;restore HL POP BC ;restore B ; FLOOP: LD (HL),C ;load it into the memory cell CALL BUMP ;are we through yet ? ? ? ? RET Z ;yes, then return to caller JR FLOOP ;no, then continue on ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Search memory routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; SEARCH: PUSH AF ;save command character CALL HEX2 ;read start and end address PUSH HL ;save start address LD C,2 ;load a 2 count CALL BINH0 ;read in 2 characters from console EX DE,HL ;move character to be found into HL LD B,L ;store it in B POP HL ;restore start address POP AF ;restore command character CP 'S' ;if it's a single byte search continue PUSH AF ;save command again JR Z,CONT ;carry on PUSH HL ;save start address LD C,2 ;load a 2 count CALL BINH0 ;read in 2 characters from console EX DE,HL ;move character to be found into HL LD C,L ;save it in C POP HL ;restore start address CONT: LD A,(HL) ;fetch first memory cell CP B ;is it equal to byte 1 JR NZ,SKIP ;no, then skip it POP AF ;restore command cahracter CP 'S' ;is it a two byte search PUSH AF ;save command character JR Z,SRCH1 ;yes, then it's a single byte search INC HL ;bump start address by one LD A,(HL) ;fetch contents of next memory cell DEC HL ;move start address back one CP C ;is it equal to byte 2 JR NZ,SKIP ;no, then skip it SRCH1: INC HL ;else bump memory pointer by one LD A,(HL) ;fetch nect memory cell DEC HL ;move address pointer back again CALL ERROR ;print address and contents SKIP: CALL BUMP ;does start = end ? JR NZ,CONT ;no, then keep looking POP AF ;yes, then restore command RET ;and return to caller ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Output to a port routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; POUT: LD C,2 ;load a 2 count CALL BINH0 ;get Port number from console LD C,2 ;load 2 more counts CALL BINH0 ;get data (port-L, data-E) LD D,L ;store port number in 'D' LD HL,STPR-30H ;HL--> where the out table resides LD (HL),0C9H ;store a return DEC HL ;HL--> next location to be loaded LD (HL),D ;store the port number DEC HL ;HL--> next location to be loaded LD (HL),0D3H ;store the out command LD A,E ;load data to be sent JP (HL) ;output acc and return to monitor ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Input from a port routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; PINP: LD C,2 ;load 2 counts CALL BINH0 ;get Port number from console LD HL,STPR-30H ;HL--> where input table is stored LD M,0C9H ;leave a return there DEC HL ;HL--> to next location to be loaded LD (HL),E ;leave port number there DEC HL ;HL--> to next location to be loaded LD (HL),0DBH ;leave a input command there CALL STPR-32H ;go to new routine JP PT2 ;print the data it found ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Block move routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; MOVB: LD B,A ;save command CALL HEX2 ;get start and end address PUSH HL ;save start address CALL BINHEX ;convert it EX DE,HL ;swap start and end EX (SP),HL ;store end on top of stack ; MLOOP: LD C,(HL) ;fetch byte to be moved EX (SP),HL ;fetch the 'MOVE TO' address LD A,B ;fetch command CP 4DH ;if move memory command JR Z,NEXCH ;then continue else exchange LD A,(HL) ;fetch byte two EX (SP),HL ;save 'MOVE TO' address LD (HL),A ;save it at new address EX (SP),HL ;reload 'MOVE TO' address ; NEXCH: LD (HL),C ;fetch next character INC HL ;bump start address EX (SP),HL ;fetch 'MOVE TO' address CALL BUMP ;if start = end JP Z,BEG ;then return to monitor JR MLOOP ;else loop until finished ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Help message ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; HELP: LD HL,HLPMSG ;load help menu CALL PRSTR ;display it JP BEG ;return to beginning of monitor ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; boot routine ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; base equ 0d0h rdystat equ 07h+base wait equ 06h+base brdset equ 04h+base datreg equ 03h+base secreg equ 02h+base trkreg equ 01h+base cmdport equ 00h+base status equ 00h+base restcmd equ 00bh ; restore command rdmsec equ 094h ; read multiple sector command nullcmd equ 0d0h ; force interrupt 0 - null command inch8 equ 05fh ; no precomp+8inch+side0+ddens+nodrive inch5 equ 01fh ; no precomp+5inch+side0+ddens+nodrive cdisk equ 04 ; current default drive number location iobyte equ 03 ; iobyte stsec equ 1 ; starting sector tmpbuf equ 10h ; small buffer for initial work: 0010-00ffh bstart equ tmpbuf+80h+3fh ; address of actual bios start bend equ tmpbuf+80h+3bh ; address of length of pure bios code boot5: ld b,inch5 ; get proper generic board setup byte jp boot boot8: ld b,inch8 ; get proper generic board setup byte boot: ld hl,bootpmt ; "drive (a,b,c,d): " call PRSTR call CIN ; a <-- input res 5,a ; upper case cp 'A' ; A --> drive 0 jr nz,try1 res 0,b jr tryx try1: cp 'B' ; B --> drive 1 jr nz,try2 res 1,b jr tryx try2: cp 'C' ; C --> drive 2 jr nz,try3 res 2,b jr tryx try3: cp 'D' ; D --> drive 3 jr nz,boot res 3,b tryx: sub 'A' ; a: 0~3 ld (cdisk),a ; cdisk <-- boot disk ld a,b ld (iobyte),a ; iobyte <-- board setup byte ; note: warm entry to this point assumes CDISK and IOBYTE are defined bwarm: ld a,(iobyte) ; get board setup byte out (brdset),a ; set up the board biosg1: ld a,restcmd ; restore drive out (cmdport),a call busywt ld hl,80h+45h ; read in id block and bios including bmap ld de,tmpbuf ; read into temp buffer in low memory ld a,stsec ; starting sector call dskrd cp 0 ; test for error jr z,ok ld hl,boter1 ; "pre-read err" call prstr jr biosg1 ok: ld hl,(bstart) ; calculate id-block/bios starting address ld de,80h sbc hl,de ex de,hl ; destination = start - 128 ld hl,(bend) ; calculate byte count ld bc,80h add hl,bc ; byte count = end + 128 ld a,stsec call dskrd ; read in id-block/bios cp 0 ; test for error jr z,fini ld hl,boter2 ; "bios read err" call prstr jr ok fini: ld hl,(bstart) ; crank up the bios jp (hl) ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; multiple sector disk read ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; entry - hl = Byte Count ; de = DEstination ; a = sector number to start reading ; exit - a = error code dskrd: out (secreg),a ; set sector ld b,5 ; count 5 index pulses dskrd1: in a,(status) ; look for hole bit 1,a jr z,dskrd1 dskrd2: in a,(status) ; look for no hole bit 1,a jr nz,dskrd2 djnz dskrd1 ; end of loop di ;\ ld a,rdmsec ; \ out (cmdport),a ; > rsync: out (wait),a ; / in a,(datreg) ; \ ld (de),a ; \ inner read loop inc de ; / dec hl ; / ld a,l ; \ or h ; > jp nz,rsync ; / in a,(status) ;/ and 9ch ; mask for bits 7,4,3,2 clear: push af ;\ ld a,0d8h ; > force a null interrupt out (cmdport),a ;/ call busywt ld a,0d0h out (cmdport),a pop af ret busywt: push af ld b,10 ;\ clr10: djnz clr10 ;/ bwtest: in a,(status) ;> wait till controller is not busy bit 0,a ;\ jr nz,bwtest ;/ pop af ret cr equ 13 lf equ 10 bell equ 7 tab equ 9 bootpmt: db cr,'Drive? (a,b,c,d):$' boter1: db cr,lf,"pre-read err$" boter2: db cr,lf,"bios read err$" MESG: DB cr,lf,lf,lf DB 'micro design associates',cr,lf DB ' magnum monitor',lf,lf,cr,'$' HLPMSG: DB cr,lf,lf db '5 boot 5 1/4 inch disk drive ' db '8 boot 8 inch disk drive',cr,lf,lf DB 'D adr1 adr2 Dump memory ' DB 'M adr1 adr2 adr3 Block move',cr,lf DB 'F adr1 adr2 dd Fill memory ' DB 'O nn dd Port output',cr,lf DB 'G addr Go ' DB 'P addr Program memory',cr,lf DB 'H Display this list ' DB 'S adr1 adr2 dd Byte search',cr,lf DB 'I nn Port input ' DB 'T adr1 adr2 Memtest',cr,lf DB ' ' DB 'W adr1 adr2 dd dd Word search',cr,lf,'$' TMSG: DB cr,lf,'Pass',36 ; ;LENGTH EQU $-RELOC ; END START