home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 09 / steinman.sep < prev   
Text File  |  1986-09-30  |  20KB  |  352 lines

  1.           INFO    $Header: worm.a-v 1.2 86/03/24 01:44:36 jans Exp $ 
  2. ****   The Worm Memory Test   ******************************************
  3. * Author: Jan W. Steinman, 2002 Parkside Ct.,  West Linn, OR 97068.
  4. *
  5. * The Worm memory test has three parts.  Init sets up the registers for the
  6. * Worm.  The Display Manager interacts with the Worm each pass and periodically
  7. * Displays the Worm's progress.  The Worm itself Worms itself through memory,
  8. * from high to low, checking memory against a copy of itself.  The Droppings
  9. * form a pattern through memory when the test is complete.
  10. *
  11. * This version runs on the Tektronix 4404 under Uniflex.  System dependent code
  12. * is mostly segregated to the Init, Display, Disable and Enable routines.  Two
  13. * instructions in the Worm routine are system dependent, for enabling and
  14. * disabling interrupts.
  15. *
  16. * Register usage:
  17. *    D0    scratch register.
  18. *    D1    scratch register.
  19. *    D2    scratch register.
  20. *    D3    scratch register.
  21. *    D4    
  22. *    D5    address mask for determining if time to show progress.
  23. *    D6    base of memory area under test.
  24. *    D7    length of Worm in long words.
  25. *    A0    scratch register.
  26. *    A1    scratch register.
  27. *    A2    scratch register.
  28. *    A3    pointer to Display manager for position independent access.
  29. *    A4    pointer to permanent Worm image for comparison.
  30. *    A5    pointer to crawling Worm image.
  31. *    A6    
  32. *    A7    stack pointer.
  33. *
  34. * These included files contain system definitions and interrupt (signal)
  35. * numbers for the Uniflex operating system.  Don't bother to list these.
  36. *
  37.          OPT     lis           
  38.          DEFINE                (This makes all labels global for debug.)
  39. *
  40. * Set D_MASK with the bits that are zero at each progress report.
  41. *
  42.         0000 03FC      D_MASK   EQU     $00003FC    Report each boundary passed.
  43.         0000 0004      REL_SIZ  EQU     4           Relocation is four b per.
  44.         0000 8000      MEM_SIZ  EQU     $2000*REL_SIZ Test a 32K chunk.
  45.         0000 0002      DISABLE  EQU     2           Trap number for Disable routine.
  46.         0000 0003      ENABLE   EQU     3           Trap number for Enable routine.
  47.         0000 000D      CR       EQU     $0D         Carriage return.
  48.         0000 000A      LF       EQU     $0A          Line feed.
  49. *
  50. * Uniflex will not allow intersection math, so put all the code in the DATA
  51. * section, and don't use TEXT or BSS at all!
  52. *
  53.  000000  DATA                  Assemble into writable data section.
  54.         0000 0000      MemBeg   EQU     *             
  55.  
  56. ****    hexadecimalize    ******************************************************
  57. * hexadecimalize converts a long word to eight ASCII hexadecimal characters.
  58. * This routine is machine and OS independent.  It uses a simple table look-up
  59. * to generate the hexadecimal string.
  60. *
  61. *    Entry:    d0 -- Long word to be converted to hex.
  62. *        a0 -- Pointer to buffer where hex characters will go.
  63. *
  64. *    Exit:    d2 -- -1.  (Just in case someone cares!)
  65. *        d0 -- unchanged.
  66. *        -8(a0) -- points to eight ASCII characters.
  67. *
  68. *    Uses:    d3 -- nybble mask: constant $0F.
  69. *        d2 -- nybble counter.
  70. *        d1 -- current nybble to convert is LSN.
  71. *
  72.  000000 3031 3233 3435 CharTab  DC.B    '0123456789ABCDEF' Where hex characters are.
  73.  000010                hexadecimalize
  74.  000010 7407                    move.l  #7,d2         Bytes to make - 1.
  75.  000012 760F                    move.l  #$0F,d3       Nybble mask.
  76.  000014 E998           HexLoop  rol.l   #4,d0         Shift the next nybble into the LSN, <--------+
  77.  000016 2200                    move.l   d0,d1        make a copy for masking,                   |
  78.  000018 C283                    and.l    d3,d1        mask out all but least significant nybble, |
  79. *                index into char table and store result.    |
  80.  00001A 10FB 10E4               move.b   CharTab(pc,d1),(a0)+               |
  81.  00001E 51CA FFF4               dbra     d2,HexLoop   Repeat until done, and when done, -----------+
  82.  000022 4E75                    rts            hit the road, Jack. -->
  83.  
  84. ****    Manager    *************************************************************
  85. * Manager checks the Worm's progress, and periodically reports to the Display.
  86. * This routine is also entered if an error is encountered.
  87. *
  88. *    Entry:    d0 -- W_LONGS complement of pass count if error, else -1.
  89. *        a1 -- test address pass/fail value.
  90. *
  91. *    Exit:    via direct jump to Worm at (A5).
  92. *
  93. *    Uses:    d3, d2, d1, d0, a7, a1, a0
  94. *
  95. *    Stack:    one level, plus needs of Display.
  96. *
  97.  000024 0D57 6F72 6D20 ErrMsg   DC.B    CR,'Worm reports memory error at ' 
  98.  000042                ErrAddrMsg
  99.  000042 3030 3030 3030          DC.B    '00000000 on pass ' 
  100.  000053                ErrCountMsg
  101.  000053 3030 3030 3030          DC.B    '00000000.',CR 
  102.         0000 0039      E_SIZ    EQU     *-ErrMsg      
  103.  00005D 0D57 6F72 6D20 DoneMsg  DC.B    CR,'Worm tested memory from ' 
  104.  000076                DoneBegAddrMsg
  105.  000076 3030 3030 3030          DC.B    '00000000 through ' 
  106.  000087                DoneEndAddrMsg
  107.  000087 3030 3030 3030          DC.B    '00000000 successfully.',CR 
  108.         0000 0041      D_SIZ    EQU     *-DoneMsg     
  109.  00009E 3030 3030 3030 ProgMsg  DC.B    '00000000',CR 
  110.         0000 0009      P_SIZ    EQU     *-ProgMsg     
  111.  0000A8 00                      EVEN                  (Stay on legal instruction boundary.)
  112.  0000A8 4A40           Manager  tst.w    d0           Was loop exited by error, or countdown?
  113.  0000AA 6A30                    bpl.s   GetErrMsg    Error, go report it. -----------------------+
  114.  0000AC BC8D                    cmp.l    a5,d6        Countdown, so are we done yet?              |
  115.  0000AE 6708                    beq.s   GetDoneMsg      Yes.  Go finish up. --------------------+ |
  116.  0000B0 200D                    move.l   a5,d0          No, put the new source where we can     | |
  117.  0000B2 C085                    and.l    d5,d0            look at the bottom bits: on boundary? | |
  118.  0000B4 674A                    beq.s   Report              Yes, set up for progress report. ---|+|
  119.  0000B6 4ED5                    jmp      (a5)              No.  Keep on Crawlin'... -->        |||
  120. *                  Finish up.  Get the pointer to start addr,  |||
  121.  0000B8 41Fa FFBC      GetDoneMsg lea    DoneBegAddrMsg(pc),a0 <----------------------------------+||
  122.  0000BC 2009                    move.l   a1,d0        and the value to plug in,                  ||
  123.  0000BE 6100 FF50               bsr     hexadecimalize    which gets converted, likewise, get        ||
  124.  0000C2 41FA FFC3               lea      DoneEndAddrMsg(pc),a0              ||
  125.  0000C6 203C 0000 8000          move.l  #MEM_SIZ,d0    the end address and its value,             ||
  126.  0000CC 6100 FF42               bsr     hexadecimalize    also converted to hexAscii.                ||
  127.  0000D0 41FA FF8B               lea      DoneMsg(pc),a0 Get pointer to complete done message,      ||
  128.  0000D4 7641                    move.l  #D_SIZ,d3    length of the done message,                ||
  129.  0000D6 487A 0050               pea      Exit(pc)    push a return pointer,                     ||
  130.  0000DA 6034                    bra.s   Display        and go display the message. --------------+||
  131. *                  Make an error report.  Get message ptr,     |||
  132.  0000DC 41FA FF75      GetErrMsg lea     ErrCountMsg(pc),a0 <-------------------------------------||+
  133.  0000E0 0400 0007               sub.b   #W_LONGS-1,d0    convert worm count to a pass count,       ||
  134.  0000E4 6100 FF2A               bsr     hexadecimalize    make it hex for Display. <-->             ||
  135. *                  Get addr of ASCII error addr,               ||
  136.  0000E8 41FA FF58               lea      ErrAddrMsg(pc),a0                 ||
  137.  0000EC 70FC                    move.l  #-4,d0        get bad long addr to display,             ||
  138.  0000EE D089                    add.l    a1,d0        less four to account for postincrement,   ||
  139.  
  140.  0000F0 6100 FF1E               bsr     hexadecimalize    make it hex for Display. <-->             ||
  141.  0000F4 41FA FF2E               lea      ErrMsg(pc),a0 Get pointer to whole err msg,              ||
  142.  0000F8 7639                    move.l  #E_SIZ,d3    the size for the write,                   ||
  143.  0000FA 487A 002C               pea      Exit(pc)    push a return pointer,                    ||
  144.  0000FE 6010                    bra.s   Display        and Display the message. -----------------+|
  145. *       Progress report.  Get message ptr,          ||
  146.  000100 41FA FF9C      Report   lea      ProgMsg(pc),a0 <-----------------------------------------|+
  147.  000104 200D                    move.l   a5,d0        load the checked address,                 |
  148.  000106 6100 FF08               bsr     hexadecimalize    make it hex for Display. <-->             |
  149.  00010A 5188                    sub.l   #8,a0         Regain pointer to the message,              |
  150.  00010C 7609                    move.l  #P_SIZ,d3    get the size for the write,               |
  151.  00010E 4855                    pea      (a5)        push a return ptr to the new Worm,        |
  152. *                and drop through into Display.            v
  153.  
  154. ****    Display    **************************************************************
  155. * Display is an implementation-dependent scheme for reporting the Worm's
  156. * progress.  Upon entry, A0 contains a pointer to a string to Display, and D3
  157. * contains the length of the string to Display.
  158. *
  159. *    Entry:    d3 -- number of bytes to display.
  160. *        a0 -- address of a string to display.
  161. *
  162. *    Uses:    d0 -- file descriptor of stdout.
  163. *        a1 -- scratch register for pointing to SysCall param block.
  164. *
  165. *    Stack:    as needed by system call.
  166. *
  167. ********   B E G I N   S Y S T E M - D E P E N D E N T   C O D E   ********
  168.  000110 2F03           Display  move.l   d3,-(a7)     Load the byte count, <---------------------+
  169.  000112 2F08                    move.l   a0,-(a7)    the actual string pointer,
  170.  000114 3F3C 000D               move.w  #write,-(a7)    and the system call index,
  171.  000118 204F                    move.l   a7,a0        point to the syscall parameter block,
  172.  00011A 7001                    move.l  #1,d0        load file descriptor for stdout,
  173. X00011C 0000 0001               SYS     indx        and write the message. <-->
  174.  000120 DFFC 0000 000A          add.l   #10,a7        Remove the params from the stack, and
  175.  000126 4E75                    rts            return somewhere. -->
  176. *
  177. * For lack of a better place to put it, the system- dependent exit code is here.
  178. *
  179. X000128 0000 0005      Exit     SYS     term          Terminate this program.  (System dependent.)
  180. ********   E N D   S Y S T E M - D E P E N D E N T   C O D E   ********
  181. The Worm Memory Test Mon Mar 24 02:15:36 1986   page 6
  182.       
  183.  
  184.  
  185. ****    Disable, Enable    *******************************************************
  186. * These routines provide the exclusion mechanism for the non-interruptible code
  187. * in Worm at Crawl.  These routines must execute in supervisor state, therefore
  188. * they are executed via the TRAP exception instruction.  Enable requires that
  189. * D1 be preserved from the preceding Disable.
  190. *
  191. *    Uses:    SR -- interrupt mask is raised and lowered.
  192. *        d2 -- scratch register for restoring original interrupt mask.
  193. *        d1 -- scratch register storage place for old interrupt mask.
  194. *
  195. ********   B E G I N   S Y S T E M - D E P E N D E N T   C O D E   ********
  196.  00012C 40F9 0000 000A Disable  move     sr,10        Grab the status register,
  197.  000132 0241 0300               and.w   #$0300,d1    keep only the interrupt bits,
  198.  000136 027C 0300               and     #$0300,sr    and disable all interrupts
  199. +00013A 0000 0008 0000          SYS     cpint,SIGTRAP2,Disable <-->
  200.  000146 4E77                    rtr            before entering critical code region. -->
  201.  
  202.  000148 40C2           Enable   move    sr,d2         Regain the status register,
  203.  00014A 8441                    or.w    d1,d2        reset the previous interrupt level,
  204.  00014C 46C2                    move    d2,sr        and enable the proper interrupts
  205. +00014E 0000 0008 0000          SYS     cpint,SIGTRAP3,Enable <-->
  206.  00015A 4E77                    rtr            before exiting critical code region. -->
  207. ********   E N D   S Y S T E M - D E P E N D E N T   C O D E   ********
  208. The Worm Memory Test Mon Mar 24 02:15:36 1986   page 7
  209.       
  210.  
  211.  
  212. ****    Worm    **************************************************************
  213. * Worm is a self-modifying, self-relocating procedure which starts at some
  214. * location in high memory and works its way down to its end address,
  215. * periodically reporting its progress.
  216. *
  217. * The loop at Crawl depends strongly on the 68000 prefetch mechanism.  This
  218. * loop will not work on a 68020 machine (which has a 64 entry cache), nor on
  219. * most simulators (which often do not bother to simulate prefetch accurately).
  220. * This loop will also not work with the TRACE bit set, and must be protected
  221. * from all interrupts, including page faults in virtual memory systems.
  222. *
  223. * When this loop moves the DBNE long word at Crawl+4, it overlays the MOVE.L
  224. * and the CMPM.L at Crawl.  The CMPM.L is in the prefetch queue, so it gets
  225. * executed even though its memory image has just been clobbered.  The DBNE is
  226. * fetched, and its execution flushes the prefetch queue as is the case with all
  227. * branches.  Execution continues with the copy of the DBNE just moved, which
  228. * executes again, branching to Crawl-4, the new loop location.  Note that the
  229. * loop count gets decremented twice in this scenario, removing the need for the
  230. * usual predecrement before entering the loop.
  231. *
  232. *
  233. *    Entry:    d7 -- length of Worm in long words.
  234. *        d6 -- base of memory area to test.
  235. *        d5 -- address mask for display boundary.
  236. *        a5 -- first long word address of Worm at present.
  237. *        a4 -- first long word address of Worm's original image.
  238. *        a3 -- display manager's address.
  239. *
  240. *    Exit:    d0 -- W_LONGS complement of pass count if error.
  241. *        a5 -- entry value less relocation, i.e.: next pass entry value.
  242. *        a1 -- address pass/fail report value.
  243. *
  244. *    Uses:    d0 -- decrementing Worm length.
  245. *        a2 -- incrementing COMPARE address.
  246. *        a1 -- incrementing TO address.
  247. *        a0 -- incrementing FROM address.
  248. *
  249. *    Unused:    d4, d3, a7, a6.
  250. *
  251.  00015C 3007           Worm     move.w   d7,d0        Restore the Worm's length,
  252.  00015E 204D                    move.l   a5,a0        its starting point,
  253.  000160 244C                    move.l   a4,a2        and its original address.
  254.  000162 43ED FFFC               lea      -4(a5),a1    Get the destination for this pass.
  255. ********   B E G I N   S Y S T E M - D E P E N D E N T   C O D E   ********
  256.  000166 4E42                    trap    #DISABLE      Don't interrupt this critical passage! <-->
  257. ********   E N D   S Y S T E M - D E P E N D E N T   C O D E   ********
  258.  000168 2298           Crawl    move.l   (a0)+,(a1)   Move a long word piece of Worm, <-------+
  259.  00016A B589                    cmp.l    (a1)+,(a2)+    and check it against the original,    |
  260.  00016C 56C8 FFFA               dbne     d0,Crawl    one long word at a time. -------------+
  261. ********   B E G I N   S Y S T E M - D E P E N D E N T   C O D E   ********
  262.  000170 4E43                    trap    #ENABLE       Allow interrupts -- critical section over. <-->
  263. ********   E N D   S Y S T E M - D E P E N D E N T   C O D E   ********
  264.  000172 598D                    sub.l   #REL_SIZ,a5   Update the new Worm address,
  265.  000174 4E71                    nop            keep the whole thing on long boundary,
  266.  000176 4ED3                    jmp      (a3)        report to the Manager. -->
  267.  
  268. *
  269. * The following pattern (which is notoriously hard on 16 bit dynamic RAM
  270. * memories) gets left in memory and can be checked later if desired.
  271. *
  272.  000178                Droppings
  273.  000178 5555 AAAA               DC.L    $5555AAAA     Pattern to be left in RAM.
  274.         0000 0020      W_SIZ    EQU     *-Worm        Length of self-relocating code, in bytes
  275.         0000 0008      W_LONGS  EQU     W_SIZ/4        and longs.
  276.  
  277. ****    Init    **************************************************************
  278. * Init performs system-dependent initialization and sets up registers for use
  279. * of Worm and Manager.  Init then copies the Worm into the top of test memory
  280. * and starts the Worm crawling.
  281. *
  282. *    Entry:    not applicable.
  283. *
  284. *    Exit:    a5 -- Worm's test image address at top of memory to be tested.
  285. *        a4 -- Worm's permanent image address.
  286. *        a3 -- Manager routine pointer.
  287. *        d7 -- length of Worm in long words.
  288. *        d6 -- base of memory area to test.
  289. *        d5 -- address mask for testing display boundary.
  290. *
  291.         0000 017C      Ovrly    EQU     *             This area will be overlaid with the worm.
  292.  00017C 576F 726D 206D LogMsg   DC.B    'Worm memory tester, ' 
  293.  000190 2448 6561 6465          DC.B    '$Header: worm.a-v 1.2 86/03/24 01:44:36 jans Exp $' 
  294.  0001C4 0D4D 656D 6F72          DC.B    CR,'Memory checked down to location:',CR 
  295.         0000 006A      L_SIZ    EQU     *-LogMsg      
  296.  
  297.  0001E6 00                      EVEN                  
  298.          GLOBAL  Init          
  299.  0001E6                Init    
  300. *
  301. * First, perform some system-dependent initialization: set up the TRAPs needed
  302. * to protect the Worm from interrupts, protect the area to be tested from page
  303. * faults, and write a welcome message.
  304. *
  305. ********   B E G I N   S Y S T E M - D E P E N D E N T   C O D E   ********
  306. +0001E6 0000 0008 0000          SYS     cpint,SIGTRAP2,Disable    Set up the exception handlers for the
  307. +0001F2 0000 0008 0000          SYS     cpint,SIGTRAP3,Enable      interrupt exclusion routines.
  308. +0001FE 0000 0039 0000          SYS     memman,1,MemBeg,MemEnd    Protect memory image from page faults.
  309.  00020E 7001                    move.l  #1,d0            Prepare and write a stdout
  310. +000210 0000 000D 0000          SYS     write,LogMsg,L_SIZ      welcome message.
  311. ********   E N D   S Y S T E M - D E P E N D E N T   C O D E   ********
  312. *
  313. * Next, set up registers that will be used by the Worm and Manager.
  314. *
  315.  00021C 2A3C 0000 03FC          move.l  #D_MASK,d5    Get the Display address boundary mask.
  316.  000222 41FA FF58               lea      Ovrly(pc),a0 Load the lowest address to test
  317.  000226 2C08                    move.l   a0,d6        into a data register for comparison,
  318.  000228 47FA FE7E               lea      Manager(pc),a3    get the Display Manager's address,
  319.  00022C 49FA FF2E               lea      Worm(pc),a4    the Worm's non-crawling image address,
  320. +000230 2A7C 0000 7FE0          move.l  #MemEnd-W_SIZ,a5  and the high-mem Worm start address.
  321.  000236 3E3C 0008               move.w  #W_LONGS,d7   Get the Worm's length in longs.
  322. *
  323. * Finally, move the Worm to the top of memory to be tested.
  324. *
  325.  00023A 204C                    move.l   a4,a0        Get a copy of Worm's permanent image pointer,
  326.  00023C 224D                    move.l   a5,a1        its test image pointer,
  327.  00023E 3007                    move.w   d7,d0        and its length in longs.
  328.  000240 5340                    sub.w   #1,d0         
  329.  000242 2290           MoveWorm move.l   (a0),(a1)    Move, and compare <-------------+
  330.  000244 B388                    cmp.l    (a0)+,(a1)+    a long word of the Worm       |
  331.  000246 56C8 FFFA               dbne     d0,MoveWorm    at a time. -------------------+
  332.  
  333.  00024A 4A40                    tst.w    d0           Exit loop by error, or countdown?
  334.  00024C 6A00 FE5A               bpl     Manager        Error, go Report it. -->
  335.  000250 4ED5                    jmp      (a5)        Countdown.  Start Crawling! -->
  336.         0000 0252      C_SIZ    EQU     *-MemBeg      (Size of non-relocating code.)
  337.  
  338.  000252 0000 0000 0000          DS.B    MEM_SIZ-C_SIZ 
  339.         0000 8000      MemEnd   EQU     *             
  340.          ENDDEF                
  341.         0000 01E6               END     Init          (Set transfer address to the Init.)
  342.  
  343. 0 Errors detected.
  344.  
  345. SEGMENT SIZES
  346. TEXT SEGMENT = 000000
  347. DATA SEGMENT = 008000
  348. BSS SEGMENT  = 000000
  349.  
  350.  
  351.                                         [EOF]
  352.