home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
ddjmag
/
ddj8609.arc
/
STEINMAN.SEP
< prev
Wrap
Text File
|
1986-09-30
|
20KB
|
352 lines
INFO $Header: worm.a-v 1.2 86/03/24 01:44:36 jans Exp $
**** The Worm Memory Test ******************************************
* Author: Jan W. Steinman, 2002 Parkside Ct., West Linn, OR 97068.
*
* The Worm memory test has three parts. Init sets up the registers for the
* Worm. The Display Manager interacts with the Worm each pass and periodically
* Displays the Worm's progress. The Worm itself Worms itself through memory,
* from high to low, checking memory against a copy of itself. The Droppings
* form a pattern through memory when the test is complete.
*
* This version runs on the Tektronix 4404 under Uniflex. System dependent code
* is mostly segregated to the Init, Display, Disable and Enable routines. Two
* instructions in the Worm routine are system dependent, for enabling and
* disabling interrupts.
*
* Register usage:
* D0 scratch register.
* D1 scratch register.
* D2 scratch register.
* D3 scratch register.
* D4
* D5 address mask for determining if time to show progress.
* D6 base of memory area under test.
* D7 length of Worm in long words.
* A0 scratch register.
* A1 scratch register.
* A2 scratch register.
* A3 pointer to Display manager for position independent access.
* A4 pointer to permanent Worm image for comparison.
* A5 pointer to crawling Worm image.
* A6
* A7 stack pointer.
*
* These included files contain system definitions and interrupt (signal)
* numbers for the Uniflex operating system. Don't bother to list these.
*
OPT lis
DEFINE (This makes all labels global for debug.)
*
* Set D_MASK with the bits that are zero at each progress report.
*
0000 03FC D_MASK EQU $00003FC Report each boundary passed.
0000 0004 REL_SIZ EQU 4 Relocation is four b per.
0000 8000 MEM_SIZ EQU $2000*REL_SIZ Test a 32K chunk.
0000 0002 DISABLE EQU 2 Trap number for Disable routine.
0000 0003 ENABLE EQU 3 Trap number for Enable routine.
0000 000D CR EQU $0D Carriage return.
0000 000A LF EQU $0A Line feed.
*
* Uniflex will not allow intersection math, so put all the code in the DATA
* section, and don't use TEXT or BSS at all!
*
000000 DATA Assemble into writable data section.
0000 0000 MemBeg EQU *
**** hexadecimalize ******************************************************
* hexadecimalize converts a long word to eight ASCII hexadecimal characters.
* This routine is machine and OS independent. It uses a simple table look-up
* to generate the hexadecimal string.
*
* Entry: d0 -- Long word to be converted to hex.
* a0 -- Pointer to buffer where hex characters will go.
*
* Exit: d2 -- -1. (Just in case someone cares!)
* d0 -- unchanged.
* -8(a0) -- points to eight ASCII characters.
*
* Uses: d3 -- nybble mask: constant $0F.
* d2 -- nybble counter.
* d1 -- current nybble to convert is LSN.
*
000000 3031 3233 3435 CharTab DC.B '0123456789ABCDEF' Where hex characters are.
000010 hexadecimalize
000010 7407 move.l #7,d2 Bytes to make - 1.
000012 760F move.l #$0F,d3 Nybble mask.
000014 E998 HexLoop rol.l #4,d0 Shift the next nybble into the LSN, <--------+
000016 2200 move.l d0,d1 make a copy for masking, |
000018 C283 and.l d3,d1 mask out all but least significant nybble, |
* index into char table and store result. |
00001A 10FB 10E4 move.b CharTab(pc,d1),(a0)+ |
00001E 51CA FFF4 dbra d2,HexLoop Repeat until done, and when done, -----------+
000022 4E75 rts hit the road, Jack. -->
**** Manager *************************************************************
* Manager checks the Worm's progress, and periodically reports to the Display.
* This routine is also entered if an error is encountered.
*
* Entry: d0 -- W_LONGS complement of pass count if error, else -1.
* a1 -- test address pass/fail value.
*
* Exit: via direct jump to Worm at (A5).
*
* Uses: d3, d2, d1, d0, a7, a1, a0
*
* Stack: one level, plus needs of Display.
*
000024 0D57 6F72 6D20 ErrMsg DC.B CR,'Worm reports memory error at '
000042 ErrAddrMsg
000042 3030 3030 3030 DC.B '00000000 on pass '
000053 ErrCountMsg
000053 3030 3030 3030 DC.B '00000000.',CR
0000 0039 E_SIZ EQU *-ErrMsg
00005D 0D57 6F72 6D20 DoneMsg DC.B CR,'Worm tested memory from '
000076 DoneBegAddrMsg
000076 3030 3030 3030 DC.B '00000000 through '
000087 DoneEndAddrMsg
000087 3030 3030 3030 DC.B '00000000 successfully.',CR
0000 0041 D_SIZ EQU *-DoneMsg
00009E 3030 3030 3030 ProgMsg DC.B '00000000',CR
0000 0009 P_SIZ EQU *-ProgMsg
0000A8 00 EVEN (Stay on legal instruction boundary.)
0000A8 4A40 Manager tst.w d0 Was loop exited by error, or countdown?
0000AA 6A30 bpl.s GetErrMsg Error, go report it. -----------------------+
0000AC BC8D cmp.l a5,d6 Countdown, so are we done yet? |
0000AE 6708 beq.s GetDoneMsg Yes. Go finish up. --------------------+ |
0000B0 200D move.l a5,d0 No, put the new source where we can | |
0000B2 C085 and.l d5,d0 look at the bottom bits: on boundary? | |
0000B4 674A beq.s Report Yes, set up for progress report. ---|+|
0000B6 4ED5 jmp (a5) No. Keep on Crawlin'... --> |||
* Finish up. Get the pointer to start addr, |||
0000B8 41Fa FFBC GetDoneMsg lea DoneBegAddrMsg(pc),a0 <----------------------------------+||
0000BC 2009 move.l a1,d0 and the value to plug in, ||
0000BE 6100 FF50 bsr hexadecimalize which gets converted, likewise, get ||
0000C2 41FA FFC3 lea DoneEndAddrMsg(pc),a0 ||
0000C6 203C 0000 8000 move.l #MEM_SIZ,d0 the end address and its value, ||
0000CC 6100 FF42 bsr hexadecimalize also converted to hexAscii. ||
0000D0 41FA FF8B lea DoneMsg(pc),a0 Get pointer to complete done message, ||
0000D4 7641 move.l #D_SIZ,d3 length of the done message, ||
0000D6 487A 0050 pea Exit(pc) push a return pointer, ||
0000DA 6034 bra.s Display and go display the message. --------------+||
* Make an error report. Get message ptr, |||
0000DC 41FA FF75 GetErrMsg lea ErrCountMsg(pc),a0 <-------------------------------------||+
0000E0 0400 0007 sub.b #W_LONGS-1,d0 convert worm count to a pass count, ||
0000E4 6100 FF2A bsr hexadecimalize make it hex for Display. <--> ||
* Get addr of ASCII error addr, ||
0000E8 41FA FF58 lea ErrAddrMsg(pc),a0 ||
0000EC 70FC move.l #-4,d0 get bad long addr to display, ||
0000EE D089 add.l a1,d0 less four to account for postincrement, ||
0000F0 6100 FF1E bsr hexadecimalize make it hex for Display. <--> ||
0000F4 41FA FF2E lea ErrMsg(pc),a0 Get pointer to whole err msg, ||
0000F8 7639 move.l #E_SIZ,d3 the size for the write, ||
0000FA 487A 002C pea Exit(pc) push a return pointer, ||
0000FE 6010 bra.s Display and Display the message. -----------------+|
* Progress report. Get message ptr, ||
000100 41FA FF9C Report lea ProgMsg(pc),a0 <-----------------------------------------|+
000104 200D move.l a5,d0 load the checked address, |
000106 6100 FF08 bsr hexadecimalize make it hex for Display. <--> |
00010A 5188 sub.l #8,a0 Regain pointer to the message, |
00010C 7609 move.l #P_SIZ,d3 get the size for the write, |
00010E 4855 pea (a5) push a return ptr to the new Worm, |
* and drop through into Display. v
**** Display **************************************************************
* Display is an implementation-dependent scheme for reporting the Worm's
* progress. Upon entry, A0 contains a pointer to a string to Display, and D3
* contains the length of the string to Display.
*
* Entry: d3 -- number of bytes to display.
* a0 -- address of a string to display.
*
* Uses: d0 -- file descriptor of stdout.
* a1 -- scratch register for pointing to SysCall param block.
*
* Stack: as needed by system call.
*
******** B E G I N S Y S T E M - D E P E N D E N T C O D E ********
000110 2F03 Display move.l d3,-(a7) Load the byte count, <---------------------+
000112 2F08 move.l a0,-(a7) the actual string pointer,
000114 3F3C 000D move.w #write,-(a7) and the system call index,
000118 204F move.l a7,a0 point to the syscall parameter block,
00011A 7001 move.l #1,d0 load file descriptor for stdout,
X00011C 0000 0001 SYS indx and write the message. <-->
000120 DFFC 0000 000A add.l #10,a7 Remove the params from the stack, and
000126 4E75 rts return somewhere. -->
*
* For lack of a better place to put it, the system- dependent exit code is here.
*
X000128 0000 0005 Exit SYS term Terminate this program. (System dependent.)
******** E N D S Y S T E M - D E P E N D E N T C O D E ********
The Worm Memory Test Mon Mar 24 02:15:36 1986 page 6
**** Disable, Enable *******************************************************
* These routines provide the exclusion mechanism for the non-interruptible code
* in Worm at Crawl. These routines must execute in supervisor state, therefore
* they are executed via the TRAP exception instruction. Enable requires that
* D1 be preserved from the preceding Disable.
*
* Uses: SR -- interrupt mask is raised and lowered.
* d2 -- scratch register for restoring original interrupt mask.
* d1 -- scratch register storage place for old interrupt mask.
*
******** B E G I N S Y S T E M - D E P E N D E N T C O D E ********
00012C 40F9 0000 000A Disable move sr,10 Grab the status register,
000132 0241 0300 and.w #$0300,d1 keep only the interrupt bits,
000136 027C 0300 and #$0300,sr and disable all interrupts
+00013A 0000 0008 0000 SYS cpint,SIGTRAP2,Disable <-->
000146 4E77 rtr before entering critical code region. -->
000148 40C2 Enable move sr,d2 Regain the status register,
00014A 8441 or.w d1,d2 reset the previous interrupt level,
00014C 46C2 move d2,sr and enable the proper interrupts
+00014E 0000 0008 0000 SYS cpint,SIGTRAP3,Enable <-->
00015A 4E77 rtr before exiting critical code region. -->
******** E N D S Y S T E M - D E P E N D E N T C O D E ********
The Worm Memory Test Mon Mar 24 02:15:36 1986 page 7
**** Worm **************************************************************
* Worm is a self-modifying, self-relocating procedure which starts at some
* location in high memory and works its way down to its end address,
* periodically reporting its progress.
*
* The loop at Crawl depends strongly on the 68000 prefetch mechanism. This
* loop will not work on a 68020 machine (which has a 64 entry cache), nor on
* most simulators (which often do not bother to simulate prefetch accurately).
* This loop will also not work with the TRACE bit set, and must be protected
* from all interrupts, including page faults in virtual memory systems.
*
* When this loop moves the DBNE long word at Crawl+4, it overlays the MOVE.L
* and the CMPM.L at Crawl. The CMPM.L is in the prefetch queue, so it gets
* executed even though its memory image has just been clobbered. The DBNE is
* fetched, and its execution flushes the prefetch queue as is the case with all
* branches. Execution continues with the copy of the DBNE just moved, which
* executes again, branching to Crawl-4, the new loop location. Note that the
* loop count gets decremented twice in this scenario, removing the need for the
* usual predecrement before entering the loop.
*
*
* Entry: d7 -- length of Worm in long words.
* d6 -- base of memory area to test.
* d5 -- address mask for display boundary.
* a5 -- first long word address of Worm at present.
* a4 -- first long word address of Worm's original image.
* a3 -- display manager's address.
*
* Exit: d0 -- W_LONGS complement of pass count if error.
* a5 -- entry value less relocation, i.e.: next pass entry value.
* a1 -- address pass/fail report value.
*
* Uses: d0 -- decrementing Worm length.
* a2 -- incrementing COMPARE address.
* a1 -- incrementing TO address.
* a0 -- incrementing FROM address.
*
* Unused: d4, d3, a7, a6.
*
00015C 3007 Worm move.w d7,d0 Restore the Worm's length,
00015E 204D move.l a5,a0 its starting point,
000160 244C move.l a4,a2 and its original address.
000162 43ED FFFC lea -4(a5),a1 Get the destination for this pass.
******** B E G I N S Y S T E M - D E P E N D E N T C O D E ********
000166 4E42 trap #DISABLE Don't interrupt this critical passage! <-->
******** E N D S Y S T E M - D E P E N D E N T C O D E ********
000168 2298 Crawl move.l (a0)+,(a1) Move a long word piece of Worm, <-------+
00016A B589 cmp.l (a1)+,(a2)+ and check it against the original, |
00016C 56C8 FFFA dbne d0,Crawl one long word at a time. -------------+
******** B E G I N S Y S T E M - D E P E N D E N T C O D E ********
000170 4E43 trap #ENABLE Allow interrupts -- critical section over. <-->
******** E N D S Y S T E M - D E P E N D E N T C O D E ********
000172 598D sub.l #REL_SIZ,a5 Update the new Worm address,
000174 4E71 nop keep the whole thing on long boundary,
000176 4ED3 jmp (a3) report to the Manager. -->
*
* The following pattern (which is notoriously hard on 16 bit dynamic RAM
* memories) gets left in memory and can be checked later if desired.
*
000178 Droppings
000178 5555 AAAA DC.L $5555AAAA Pattern to be left in RAM.
0000 0020 W_SIZ EQU *-Worm Length of self-relocating code, in bytes
0000 0008 W_LONGS EQU W_SIZ/4 and longs.
**** Init **************************************************************
* Init performs system-dependent initialization and sets up registers for use
* of Worm and Manager. Init then copies the Worm into the top of test memory
* and starts the Worm crawling.
*
* Entry: not applicable.
*
* Exit: a5 -- Worm's test image address at top of memory to be tested.
* a4 -- Worm's permanent image address.
* a3 -- Manager routine pointer.
* d7 -- length of Worm in long words.
* d6 -- base of memory area to test.
* d5 -- address mask for testing display boundary.
*
0000 017C Ovrly EQU * This area will be overlaid with the worm.
00017C 576F 726D 206D LogMsg DC.B 'Worm memory tester, '
000190 2448 6561 6465 DC.B '$Header: worm.a-v 1.2 86/03/24 01:44:36 jans Exp $'
0001C4 0D4D 656D 6F72 DC.B CR,'Memory checked down to location:',CR
0000 006A L_SIZ EQU *-LogMsg
0001E6 00 EVEN
GLOBAL Init
0001E6 Init
*
* First, perform some system-dependent initialization: set up the TRAPs needed
* to protect the Worm from interrupts, protect the area to be tested from page
* faults, and write a welcome message.
*
******** B E G I N S Y S T E M - D E P E N D E N T C O D E ********
+0001E6 0000 0008 0000 SYS cpint,SIGTRAP2,Disable Set up the exception handlers for the
+0001F2 0000 0008 0000 SYS cpint,SIGTRAP3,Enable interrupt exclusion routines.
+0001FE 0000 0039 0000 SYS memman,1,MemBeg,MemEnd Protect memory image from page faults.
00020E 7001 move.l #1,d0 Prepare and write a stdout
+000210 0000 000D 0000 SYS write,LogMsg,L_SIZ welcome message.
******** E N D S Y S T E M - D E P E N D E N T C O D E ********
*
* Next, set up registers that will be used by the Worm and Manager.
*
00021C 2A3C 0000 03FC move.l #D_MASK,d5 Get the Display address boundary mask.
000222 41FA FF58 lea Ovrly(pc),a0 Load the lowest address to test
000226 2C08 move.l a0,d6 into a data register for comparison,
000228 47FA FE7E lea Manager(pc),a3 get the Display Manager's address,
00022C 49FA FF2E lea Worm(pc),a4 the Worm's non-crawling image address,
+000230 2A7C 0000 7FE0 move.l #MemEnd-W_SIZ,a5 and the high-mem Worm start address.
000236 3E3C 0008 move.w #W_LONGS,d7 Get the Worm's length in longs.
*
* Finally, move the Worm to the top of memory to be tested.
*
00023A 204C move.l a4,a0 Get a copy of Worm's permanent image pointer,
00023C 224D move.l a5,a1 its test image pointer,
00023E 3007 move.w d7,d0 and its length in longs.
000240 5340 sub.w #1,d0
000242 2290 MoveWorm move.l (a0),(a1) Move, and compare <-------------+
000244 B388 cmp.l (a0)+,(a1)+ a long word of the Worm |
000246 56C8 FFFA dbne d0,MoveWorm at a time. -------------------+
00024A 4A40 tst.w d0 Exit loop by error, or countdown?
00024C 6A00 FE5A bpl Manager Error, go Report it. -->
000250 4ED5 jmp (a5) Countdown. Start Crawling! -->
0000 0252 C_SIZ EQU *-MemBeg (Size of non-relocating code.)
000252 0000 0000 0000 DS.B MEM_SIZ-C_SIZ
0000 8000 MemEnd EQU *
ENDDEF
0000 01E6 END Init (Set transfer address to the Init.)
0 Errors detected.
SEGMENT SIZES
TEXT SEGMENT = 000000
DATA SEGMENT = 008000
BSS SEGMENT = 000000
[EOF]