home *** CD-ROM | disk | FTP | other *** search
- ; WORM.ASM ver 2.1 (revised 10/9/81)
- ;
- ;Jim Eccleston July 19 1980 - program originally written
- ;
- ;Keith Petersen, W8SDZ, October 9, 1981 - fixed bug which
- ; caused program to print one trap error at start.
- ; Added REPORT conditional assembly so addresses
- ; won't be reported unless there is an error.
- ; Added equates for console ports.
- ;
- ;Allen Mar August 8, 1980 - added 'label + offset'
- ; so COM file can be generated without DDT.COM
- ; Thanks to Bill Precht and Ward Christensen
- ; who used it in his 'PMMIBYE2' remote CP/M
- ; program...
- ;
- ;************************************************************************
- ;* *
- ;* W O R M T E S T *
- ;* *
- ;* A serious flaw exists in most memory test routines when *
- ;* applied to Z-80 systems. A board can be tested for hours *
- ;* and never drop a bit, then when it's loaded with a program *
- ;* fail instantly. The problem is that access timing on a *
- ;* Z-80 instruction fetch (the M-1 cycle) is significantly *
- ;* more critical than on a simple read cycle. No matter how *
- ;* fancy a normal memory test gets, it never makes demands *
- ;* on memory speed that an actual program does. The only way *
- ;* to check this memory for full speed operation is to *
- ;* actually run a program in it. Wormtest does just that. *
- ;* vide The M-1 Worm. P.C. July 73 *
- ;* *
- ;************************************************************************
- ;
- ;The first few lines relocate the program down to low memory
- ;There are two parts to the test program. The larger portion
- ;consists of service routines, but the Worm itself consists of
- ;a short 12 byte routine that upon initialization breaks away
- ;from the main body and crawls up through memory space giving a
- ;running travelogue as he goes. If he stops talking, you know
- ;something bad happened, and where. The Worm acts as the main
- ;program loop. It manipulates two test bytes and calls two sub-
- ;routines. One of the subroutines reports the location of the
- ;worm and detects and reports any errors in the test bytes. The
- ;other subroutine shifts the Worm up in memory one location and
- ;adjusts the return to begin execution for another loop. There
- ;are seven instruction fetches per loop, with the data manipulation
- ;instructions in complementary pairs to ensure full speed testing
- ;on both ones and zeroes. The instruction RST 7 is embedded in
- ;the Worm in non-executable locations as traps in case a memory
- ;error causes the program counter to get out of sync. The Worm
- ;leaves behind a slime-trail of FF's as it travels. Any execution
- ;of a trap is reported and the trap subroutine attempts to return
- ;execution back to the worm. The error reports indicate which data
- ;byte was bad and what the erroneous value was. A "D" indicates
- ;that bits were dropped, while a "P" indicates that bits were
- ;picked. A trap error is flagged by a "T" followed by the address.
- ;Upon execution the Worm will immediately start reporting its
- ;location (by address). Bad memory will trash the program or
- ;else trigger the error reports. No memory looks like a string
- ;of FF's and a sequential string of traps will be reported.
- ;When ROM is hit, execution of the ROM program will begin,
- ;so if you have the Morrows Disk Controller you will know
- ;your memory is ok when the system re-boots.
- ;
- stport equ 20h ;console status port
- txrdy equ 04h ;console putput mask
- daport equ 21h ;console data port
- ;
- report equ 0 ;<--make non-zero for address reporting
- ;
- org 0100h
- ;
- ; Move routine relocates WORM program down to 08H
- ;
- start lxi d,dest ;Destination address
- lxi h,source ;Source address
- mvi b,pend-source+1 ;Number of bytes to move
- ;
- loop mov a,m ;Get byte
- stax d ;Put byte
- inx h ;Bump up source adr.
- inx d ;Bump up destination adr.
- dcr b ;Decrease byte count
- jnz loop ;Do again if not zero count
- lxi sp,stack ;Set up stack pointer
- lxi b,data ;Set up data pointer
- jmp worm+1
- ;
- dest equ 08h ;destination
- ;
- source equ $
- offset equ dest-source ;reloc amount
- ;
- stwrm equ $+offset ;Start of relocated code (08h)
- dw 0ffffh
- dw 0ffffh
- dw 0ffffh
- dw 0ffffh ;Rst 7s
- ;
- movwrm equ $+offset
- pop h ;Get address of worm + 1
- mov d,h ;Duplicate address in d
- mov e,l ;and e regs.
- dcx d ;Set DE to last address of worm
- mvi b,0ch ;Set length of worm
- ;
- getwrm equ $+offset
- ldax d ;;Get byte of worm
- mov m,a ;Move it up one location
- dcx d ;Adjust pointers
- dcx h
- dcr b
- mov a,b
- cpi 00
- jnz getwrm
- lxi b,data ;Restore data pointer
- inx h ;HL to start of worm
- inx h
- pchl ;Return to worm
- rst 7 ;RST 7
- ;
- rptadr equ $+offset
- cpi 0ffh ;Check for dropped bit error
- jnz errdrp
- mov a,b
- cpi 00h ;Check for picked bit error
- jnz errpik
- jmp rptad2 ;Show the address
- rst 7
- rst 7 ;Trap
- ;
- trap equ $+offset
- mvi a,54h ;Print a "T"
- call output
- mvi a,20h ;Print a " "
- call output
- pop h ;Recover address
- dcx h ;Adjust address
- call adout ;Print the address
- inx h ;Adjust address
- pchl ;Return
- ;
- rptad2 equ $+offset
- pop h ;Recover address
- ;
- if report
- call adout ;Print address
- endif
- ;
- if not report
- nop ! nop ! nop ;Don't print address
- endif
- ;
- inx h ;Adjust return address
- inx h
- inx h
- pchl ;Return
- ;
- errdrp equ $+offset
- mvi b,44h ;Show it's dropped bit(s)
- jmp errprt ;Print error message
- ;
- errpik equ $+offset
- mvi b,50h ;Show it's picked bit(s)
- ;
- errprt equ $+offset
- mov c,a ;Save error data
- mvi a,2ah ;Print "*"
- call output
- mvi a,20h ;Print " "
- call output
- mov a,b ;Print type of error
- call output
- mvi a,20h ;Print " "
- call output
- mov a,c ;Get error data
- call bowcl ;Print and end line
- jmp rptad2 ;Now try for address and return
- ;
- adout equ $+offset
- push h ;Save address
- mov a,h
- call bytout ;Its nybble time
- mov a,l
- call bowcl ;Same with cr/lf
- pop h ;Restore address
- ret
- ;
- bytout equ $+offset
- push psw ;Save A
- rrc ;Shift nybble
- rrc
- rrc
- rrc
- call nybout ;Nybble out 1
- pop psw ;Restore A
- call nybout ;Nybble out 2
- ret
- ;
- bowcl equ $+offset
- call bytout
- mvi a,0Dh ;C/R time
- call output
- mvi a,0Ah ;LF time
- call output
- ret
- ;
- nybout equ $+offset
- ani 0fh ;Strip high nibble
- cpi 0ah ;Divide alpha v numeric
- jm isnum ;If numeric
- adi 07h ;Add alpha offset
- isnum equ $+offset
- adi 30h ;Add numeric offset
- call output
- ret
- ;
- ;************************************************
- ;* Insert Your DIRECT Console Output Call Here *
- ;* unless you want to use cp/m calls till crash *
- ;************************************************
- ;
- output equ $+offset
- push b ;save bc
- push psw ;save character
- ;
- lp equ $+offset
- in stport ;get console status
- ani txrdy ;ready for character?
- jz lp ;no, loop and wait
- pop psw ;get character
- out daport ;output to console
- pop b ;restore bc
- ret
- ;
- data equ $+offset
- db 00
- ;
- ds 20
- stack equ $+offset-1
- ;
- worm equ $+offset
- rst 7 ;Trap
- ldax b ;Move data to A; start of worm
- push psw ;Push test data onto stack
- mvi a,0ffh ;Move second test byte to A
- pop b ;Pop first test byte into B
- rst 5 ;call "rptadr"
- rst 7 ;Trap
- rst 7
- rst 7
- nop ;"rptadr" return location
- rst 2 ;call "movwrm"
- ;
- pend equ $ ;program end
- ;
- end 0100h