(*$S+*) PROGRAM CODESTAT; {========================================================} { } { UCSD P-CODE DISASSEMBLER } { } { Release level: I.5 Sept, 1978 } { } { Written by William P. Franks } { } { Institute for Information Systems } { UC San Diego, La Jolla, Ca } { } { Kenneth L. Bowles, Director } { } { COPYRIGHT (C) 1978, Regents of the } { University of California, San Diego } { } {========================================================} CONST MAXPROCNUM=150; TYPE NMENONIC=PACKED ARRAY[0..7] OF CHAR; BYTETYPE=ARRAY[0..7] OF INTEGER; WORDTYPE=ARRAY[0..15] OF INTEGER; BYTE=0..255; OPTYPE=(SHORT,ONE,OPT,TWO,LOPT,WORDS,CHRS,BLK,CMPRSS,CMPRSS2,WORD); OPREC=RECORD CASE OPTYPE OF SHORT:(TOTAL0:INTEGER); ONE,CHRS,BLK:(TOTAL1:INTEGER; BYTEONE1:BYTETYPE); TWO:(TOTAL2:INTEGER; BYTEONE2:BYTETYPE; BYTETWO2:BYTETYPE; FLAVOR2:ARRAY[2..29] OF INTEGER); WORD,OPT:(TOTAL3:INTEGER; PARMONE3:WORDTYPE); LOPT:(TOTAL4:INTEGER; BYTEONE4:BYTETYPE; PARMTWO4:WORDTYPE); WORDS:(TOTAL5:INTEGER; PARMONE5:WORDTYPE; PARMTWO5:WORDTYPE; PARMTHREE5:WORDTYPE); CMPRSS:(TOTAL6:INTEGER; FLAVOR6:ARRAY[0..40] OF INTEGER); CMPRSS2:(TOTAL7:INTEGER; FLAVOR7:ARRAY[1..6] OF INTEGER) END; OPPTR=^OPREC; OPFACTS=RECORD NAMES:ARRAY[52..255] OF NMENONIC; RECTYPES:ARRAY[0..255] OF OPTYPE END; JUMPREC=RECORD POS,NEG:WORDTYPE END; PRCLARRY=ARRAY[0..MAXPROCNUM] OF INTEGER; DSPTR=^DSARRY; DSARRY=ARRAY[0..1] OF INTEGER; HEXTYPE=PACKED RECORD CASE INTEGER OF 0:(DUM2,DUM1,HI,LO:0..15); 1:(HIBYTE,LOWBYTE:0..255); 2:(WORD:INTEGER) END; VAR DISPLAY:BOOLEAN; CH,CR:CHAR; PCTMAX,MAXOP,INUM,BYTESIZE,BYTEPOS,OP,BUFSTART,PROCNUM,SEGNUM:INTEGER; BITE:BYTE; DSSTART:DSPTR; SWAP,CONTROL,CONSOLE,DONEPROC,LEXCHECK,DATAWATCH, LEXLOOK :BOOLEAN; HEXCOUNT,MAXPROC,SEGSTBLK,BUFSTBLK,OPTOTAL, SEGSIZE,OFFSET,BACKJUMP,SLDC, SLDL,SLDO,SIND,PROCSTART,DATASEG,DATAPROC, DATASEGSIZE,LEXLEVEL,DATAREF,DTSGSZ,JUMPTOTAL :INTEGER; HEX:HEXTYPE; RNUM:REAL; OPCODE:ARRAY[0..255] OF OPPTR; LISTFILE:INTERACTIVE; HEXCHAR,CODE :PACKED ARRAY[0..15] OF CHAR; INPUTFILE:FILE; JUMPSTATS:JUMPREC; SEGLEX:ARRAY[0..15] OF INTEGER; SEGDIREC:PACKED ARRAY[0..511] OF BYTE; NAMES:ARRAY[52..255] OF NMENONIC; RECTYPES:PACKED ARRAY[0..255] OF OPTYPE; PROCS:ARRAY [0..MAXPROCNUM] OF INTEGER; PROCCALL:ARRAY[0..15] OF ^PRCLARRY; JUMPS,PROCLEX:ARRAY[0..99] OF INTEGER; LASTFILENAME:STRING; BUFFER:PACKED ARRAY[0..2559] OF BYTE; SEGMENT PROCEDURE INIT; VAR I:INTEGER; FILENAME:STRING; OPFILE:FILE OF OPFACTS; PROCEDURE NEWOP(FLAVOR:OPTYPE); BEGIN CASE FLAVOR OF SHORT:NEW(OPCODE[I],SHORT); ONE:NEW(OPCODE[I],ONE); BLK:NEW(OPCODE[I],BLK); CHRS:NEW(OPCODE[I],CHRS); OPT:NEW(OPCODE[I],OPT); TWO:NEW(OPCODE[I],TWO); LOPT:NEW(OPCODE[I],LOPT); WORDS:NEW(OPCODE[I],WORDS); CMPRSS:NEW(OPCODE[I],CMPRSS); CMPRSS2:NEW(OPCODE[I],CMPRSS2); WORD:NEW(OPCODE[I],WORD) END; WITH OPCODE[I]^ DO CASE FLAVOR OF SHORT:TOTAL0:=0; CHRS,BLK,ONE:BEGIN TOTAL1:=0; FILLCHAR(BYTEONE1,16,0); END; TWO:BEGIN TOTAL2:=0; FILLCHAR(BYTEONE2,16,0); FILLCHAR(BYTETWO2,16,0); FILLCHAR(FLAVOR2,56,0); END; WORD,OPT:BEGIN TOTAL3:=0; FILLCHAR(PARMONE3,32,0); END; LOPT:BEGIN TOTAL4:=0; FILLCHAR(BYTEONE4,16,0); FILLCHAR(PARMTWO4,32,0); END; WORDS:BEGIN TOTAL5:=0; FILLCHAR(PARMONE5,32,0); FILLCHAR(PARMTWO5,32,0); FILLCHAR(PARMTHREE5,32,0); END; CMPRSS:BEGIN TOTAL6:=0; FILLCHAR(FLAVOR6,82,0); END; CMPRSS2:BEGIN TOTAL7:=0; FILLCHAR(FLAVOR7,12,0); END END; END; BEGIN(* INIT *) CR:=CHR(13); RESET(OPFILE,'*OPCODES.I5'); NAMES:=OPFILE^.NAMES; FOR I:=0 TO 255 DO BEGIN NEWOP(OPFILE^.RECTYPES[I]); RECTYPES[I]:=OPFILE^.RECTYPES[I]; END; CLOSE(OPFILE); PAGE(OUTPUT); GOTOXY(22,10); WRITELN('UCSD P-CODE DISASSEMBLER'); GOTOXY(0,0); WRITE('Input code file: '); READLN(FILENAME); (*$I-*) OPENOLD(INPUTFILE,CONCAT(FILENAME,'.CODE')); (*$I+*) IF IORESULT <> 0 THEN OPENOLD(INPUTFILE,FILENAME); IF BLOCKREAD(INPUTFILE,SEGDIREC,1)=1 THEN ; FOR SEGNUM:=0 TO 15 DO IF SEGDIREC[SEGNUM*4] + SEGDIREC[SEGNUM*4 + 1]<>0 THEN BEGIN NEW(PROCCALL[SEGNUM]); FILLCHAR(PROCCALL[SEGNUM]^,SIZEOF(PRCLARRY),0); END ELSE PROCCALL[SEGNUM]:=NIL; PAGE(OUTPUT); GOTOXY(0,10); WRITELN(' ':10,'Is this code file designed for a machine'); WRITE(' ':7,'where byte zero is the most significant byte ?'); READ(KEYBOARD,CH); SWAP:=(CH='Y'); PAGE(OUTPUT); GOTOXY(0,10); WRITE('Dis-assembly output file ( for none): '); READLN(FILENAME); LASTFILENAME:=FILENAME; DISPLAY:=(FILENAME<>''); CONSOLE:=(FILENAME='CONSOLE:') OR (FILENAME='#1:'); IF DISPLAY THEN REWRITE(LISTFILE,FILENAME); SEGNUM:=0; OPTOTAL:=0; SLDC:=0; SLDL:=0; SLDO:=0; SIND:=0; JUMPTOTAL:=0; HEXCOUNT:=0; CODE:=' '; HEXCHAR:='0123456789ABCDEF'; FILLCHAR(JUMPSTATS.POS,32,0); FILLCHAR(JUMPSTATS.NEG,32,0); LEXLOOK:=FALSE; END; PROCEDURE PROMPT; FORWARD; SEGMENT PROCEDURE DISASSEMBLE; FUNCTION BUFRESET(BYTEPOS,OFFSET,DIRECTION:INTEGER):INTEGER; VAR NEWBYTE:INTEGER; BEGIN NEWBYTE:=BYTEPOS + OFFSET; REPEAT BUFSTBLK:=BUFSTBLK + DIRECTION; BUFSTART:=(BUFSTBLK - SEGSTBLK)*512; UNTIL (NEWBYTE - BUFSTART>=0) AND (NEWBYTE - BUFSTART<2557); IF BLOCKREAD(INPUTFILE,BUFFER,5,BUFSTBLK)=1 THEN; BUFRESET:=NEWBYTE - BUFSTART; END; FUNCTION LASTBYTE:BYTE; VAR CHANGE:INTEGER; BEGIN IF BYTEPOS<1 THEN BEGIN BYTEPOS:=BUFRESET(BUFSTART + BYTEPOS,-1,-1); OFFSET:=OFFSET - 1; END ELSE BEGIN BYTEPOS:=BYTEPOS - 1; OFFSET:=OFFSET - 1; END; LASTBYTE:=BUFFER[BYTEPOS]; END; FUNCTION GETBYTE:BYTE; VAR HEX:HEXTYPE; BEGIN IF BYTEPOS>2559 THEN BYTEPOS:=BUFRESET(BUFSTART + BYTEPOS,0,5); GETBYTE:=BUFFER[BYTEPOS]; IF HEXCOUNT<15 THEN BEGIN HEX.LOWBYTE:=BUFFER[BYTEPOS]; CODE[HEXCOUNT]:=HEXCHAR[HEX.HI]; CODE[HEXCOUNT + 1]:=HEXCHAR[HEX.LO]; HEXCOUNT:=HEXCOUNT + 2; END; BYTEPOS:=BYTEPOS + 1; END; FUNCTION GETBIG:INTEGER; VAR BIG:HEXTYPE; FIRSTBYTE:BYTE; BEGIN FIRSTBYTE:=GETBYTE; IF FIRSTBYTE>127 THEN BEGIN BIG.LOWBYTE:=GETBYTE; BIG.HIBYTE:=FIRSTBYTE - 128; GETBIG:=BIG.WORD; END ELSE GETBIG:=FIRSTBYTE; END; FUNCTION GETWORD:INTEGER; VAR WERD:HEXTYPE; BEGIN IF SWAP THEN BEGIN WERD.HIBYTE:=GETBYTE; WERD.LOWBYTE:=GETBYTE; END ELSE BEGIN WERD.LOWBYTE:=GETBYTE; WERD.HIBYTE:=GETBYTE; END; GETWORD:=WERD.WORD; END; FUNCTION MOSTSIGBIT(OPERAND:INTEGER):INTEGER; VAR BYTESIZE:INTEGER; BEGIN IF OPERAND<0 THEN MOSTSIGBIT:=15 ELSE BEGIN BYTESIZE:=-1; REPEAT BYTESIZE:=BYTESIZE + 1; OPERAND:=OPERAND DIV 2; UNTIL OPERAND=0; MOSTSIGBIT:=BYTESIZE; END; END; PROCEDURE ACTACCESS(FINALEX,OFFSET:INTEGER); FORWARD; PROCEDURE SHORTOP; {SLDC ABI ABR ADI ADR LAND DIF DVI DVR CHK FLO FLT INN INT LOR MODI MPI MPR NGI NGR LNOT SRS SBI SBR SGS SQI SQR STO IXS UNI S2P LDCN LDP STP LDB STB EQUI GEQI GTRI LEQI LESI NEQI S1P IXB BYT XIT SLDL SLDO SIND} BEGIN OPCODE[BITE]^.TOTAL0:=OPCODE[BITE]^.TOTAL0 + 1; IF BITE=214 THEN DONEPROC:=TRUE; IF BITE<128 THEN BEGIN SLDC:=SLDC + 1; IF DISPLAY THEN WRITELN(LISTFILE,NAMES[127],BITE:6,' ':18,CODE); END ELSE BEGIN IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); IF BITE>215 THEN IF BITE<232 THEN BEGIN SLDL:=SLDL + 1; IF DATAWATCH THEN ACTACCESS(LEXLEVEL,BITE - 215); IF DISPLAY THEN WRITELN(LISTFILE,BITE-215:6,' ':18,CODE); END ELSE IF BITE<248 THEN BEGIN SLDO:=SLDO + 1; IF DATAWATCH THEN ACTACCESS(0,BITE - 231); IF DISPLAY THEN WRITELN(LISTFILE,BITE-231:6,' ':18,CODE); END ELSE BEGIN SIND:=SIND + 1; IF DISPLAY THEN WRITELN(LISTFILE,BITE-248:6,' ':18,CODE); END ELSE IF DISPLAY THEN WRITELN(LISTFILE,' ':24,CODE); END; IF DONEPROC THEN IF DISPLAY THEN WRITELN(LISTFILE); END; PROCEDURE ONEOP; {ADJ FJP SAS RNP CIP UJP LDM STM RBP CBP CLP CGP EFJ NFJ} VAR JUMPSIZE:INTEGER; PCALL:BOOLEAN; PROCEDURE JUMPOPST; VAR NEG:BOOLEAN; BEGIN NEG:=(JUMPSIZE<0); IF NEG THEN JUMPSIZE:=-JUMPSIZE; BYTESIZE:=-1; REPEAT BYTESIZE:=BYTESIZE + 1; JUMPSIZE:=JUMPSIZE DIV 2; UNTIL JUMPSIZE=0; IF NEG THEN JUMPSTATS.NEG[BYTESIZE]:=JUMPSTATS.NEG[BYTESIZE] + 1 ELSE JUMPSTATS.POS[BYTESIZE]:=JUMPSTATS.POS[BYTESIZE] + 1; END; BEGIN(* ONEOP *) WITH OPCODE[BITE]^ DO BEGIN TOTAL1:=TOTAL1 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); IF (BITE=173) OR (BITE=193) THEN DONEPROC:=TRUE; IF (BITE IN [161,185,211,212]) THEN BEGIN BITE:=GETBYTE; IF BITE<128 THEN BEGIN JUMPTOTAL:=JUMPTOTAL + 1; JUMPSIZE:=BITE; JUMPOPST; IF DISPLAY THEN WRITELN(LISTFILE, BUFSTART + BYTEPOS + BITE - PROCSTART:6,' ':18,CODE); END ELSE BEGIN JUMPTOTAL:=JUMPTOTAL + 1; JUMPSIZE:=JUMPS[(256-BITE-8)DIV 2] - (BUFSTART+BYTEPOS-PROCSTART); JUMPOPST; IF DISPLAY THEN WRITELN(LISTFILE, JUMPS[(256 - BITE - 8) DIV 2]:6,' ':18,CODE); END; END ELSE BEGIN PCALL:=(BITE IN [174,206,207]); BITE:=GETBYTE; IF PCALL THEN PROCCALL[SEGNUM]^[BITE]:=PROCCALL[SEGNUM]^[BITE] + 1; IF DISPLAY THEN WRITELN(LISTFILE,BITE:6,' ':18,CODE); IF DONEPROC THEN IF DISPLAY THEN WRITELN(LISTFILE); END; BYTESIZE:=MOSTSIGBIT(BITE); BYTEONE1[BYTESIZE]:=BYTEONE1[BYTESIZE] + 1; END; END; PROCEDURE OPTOP; {INC IND IXA LAO LDO MOV MVB SRO LLA LDL STL BTP} VAR BIG:INTEGER; LOCAL,GLOBAL:BOOLEAN; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL3:=TOTAL3 + 1; IF DATAWATCH THEN BEGIN LOCAL:=(BITE IN [198,202,204]); GLOBAL:=(BITE IN [165,167,171]); END; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BIG:=GETBIG; BYTESIZE:=MOSTSIGBIT(BIG); PARMONE3[BYTESIZE]:=PARMONE3[BYTESIZE] + 1; IF DATAWATCH THEN IF LOCAL THEN ACTACCESS(LEXLEVEL,BIG) ELSE IF GLOBAL THEN ACTACCESS(0,BIG); IF DISPLAY THEN WRITELN(LISTFILE,BIG:6,' ':18,CODE); END; END; PROCEDURE LOPTOP; {LDA LOD STR} VAR BIG,LINKS:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL4:=TOTAL4 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BITE:=GETBYTE; IF DISPLAY THEN WRITE(LISTFILE,BITE:6); LINKS:=BITE; BYTESIZE:=MOSTSIGBIT(BITE); BYTEONE4[BYTESIZE]:=BYTEONE4[BYTESIZE] + 1; BIG:=GETBIG; BYTESIZE:=MOSTSIGBIT(BIG); PARMTWO4[BYTESIZE]:=PARMTWO4[BYTESIZE] + 1; IF DATAWATCH THEN ACTACCESS(LEXLEVEL - LINKS,BIG); IF DISPLAY THEN WRITELN(LISTFILE,BIG:6,' ':12,CODE); END; END; PROCEDURE TWOOP; {IXP CXP} VAR BYTEONE,BYTETWO:BYTE; EXTPR:BOOLEAN; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL2:=TOTAL2+ 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); IF BITE=205 THEN EXTPR:=TRUE ELSE EXTPR:=FALSE; BYTEONE:=GETBYTE; BYTESIZE:=MOSTSIGBIT(BYTEONE); BYTEONE2[BYTESIZE]:=BYTEONE2[BYTESIZE] + 1; BYTETWO:=GETBYTE; DONEPROC:=(EXTPR) AND (BYTEONE=0) AND (BYTETWO=2); IF (EXTPR) AND (BYTEONE=0) AND (BYTETWO>1) AND (BYTETWO<30) THEN BEGIN FLAVOR2[BYTETWO]:=FLAVOR2[BYTETWO] + 1; IF DISPLAY THEN WRITELN(LISTFILE,NAMES[56 + BYTETWO],' ':16,CODE); END ELSE BEGIN IF EXTPR THEN PROCCALL[BYTEONE]^[BYTETWO]:=PROCCALL[BYTEONE]^[BYTETWO] + 1; IF DISPLAY THEN WRITELN(LISTFILE,BYTEONE:6,BYTETWO:6,' ':12,CODE); END; BYTESIZE:=MOSTSIGBIT(BYTETWO); BYTETWO2[BYTESIZE]:=BYTETWO2[BYTESIZE] + 1; END; END; PROCEDURE WORDOP; { LCI } VAR WERD:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL3:=TOTAL3+ 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); WERD:=GETWORD; IF DISPLAY THEN WRITELN(LISTFILE,WERD:6,' ':18,CODE); BYTESIZE:=MOSTSIGBIT(WERD); PARMONE3[BYTESIZE]:=PARMONE3[BYTESIZE] + 1; END; END; PROCEDURE WORDSOP; { XJP } VAR WORD1,WORD2,WORD3:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL5:=TOTAL5 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); IF ODD(BYTEPOS) THEN BITE:=GETBYTE; WORD1:=GETWORD; BYTESIZE:=MOSTSIGBIT(WORD1); PARMONE5[BYTESIZE]:=PARMONE5[BYTESIZE] + 1; WORD2:=GETWORD; BYTESIZE:=MOSTSIGBIT(WORD2); PARMTWO5[BYTESIZE]:=PARMTWO5[BYTESIZE] + 1; BYTESIZE:=MOSTSIGBIT(WORD2-WORD1+1); PARMTHREE5[BYTESIZE]:=PARMTHREE5[BYTESIZE] + 1; BITE:=GETBYTE; BITE:=GETBYTE; IF BITE<128 THEN WORD3:=BUFSTART + BYTEPOS + BITE - PROCSTART ELSE WORD3:=JUMPS[(256 - BITE - 8) DIV 2]; IF DISPLAY THEN WRITELN(LISTFILE,WORD1:6,WORD2:6,WORD3:6,' ':6,CODE); WORD2:=WORD2 - WORD1 + 1; FOR WORD1:=1 TO WORD2 DO BEGIN HEXCOUNT:=0; CODE:=' '; WORD3:=GETWORD; WORD3:=BUFSTART + BYTEPOS - WORD3 - 2 - PROCSTART; IF DISPLAY THEN WRITELN(LISTFILE,WORD3:41,' ':18,CODE); END; END; END; PROCEDURE CMPRSSOP; { CSP } BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL6:=TOTAL6 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BITE:=GETBYTE; IF DISPLAY THEN WRITELN(LISTFILE,NAMES[86 + BITE],' ':16,CODE); FLAVOR6[BITE]:=FLAVOR6[BITE] + 1; END; END; PROCEDURE CMPRSS2OP; {EQU GEQ GTR LEQ LES NEQ} VAR BIG:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL7:=TOTAL7 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BITE:=GETBYTE; FLAVOR7[BITE DIV 2]:=FLAVOR7[BITE DIV 2] +1; IF (BITE=10) OR (BITE=12) THEN BIG:=GETBIG; IF DISPLAY THEN CASE BITE OF 2:WRITELN(LISTFILE,'REAL',' ':20,CODE); 4:WRITELN(LISTFILE,'STR ',' ':20,CODE); 6:WRITELN(LISTFILE,'BOOL',' ':20,CODE); 8:WRITELN(LISTFILE,'POWR',' ':20,CODE); 10:WRITELN(LISTFILE,'BYTE',BIG:6,' ':14,CODE); 12:WRITELN(LISTFILE,'WORD',BIG:6,' ':14,CODE) END; END; END; PROCEDURE CHRSOP; { LCA } VAR SKIPOVER,I:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL1:=TOTAL1 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BITE:=GETBYTE; IF DISPLAY THEN WRITE(LISTFILE,BITE:6,' '''); BYTESIZE:=MOSTSIGBIT(BITE); BYTEONE1[BYTESIZE]:=BYTEONE1[BYTESIZE] + 1; IF DISPLAY THEN FOR I:=1 TO BITE DO WRITE(LISTFILE,CHR(GETBYTE)) ELSE FOR I:=1 TO BITE DO SKIPOVER:=GETBYTE; IF DISPLAY THEN WRITELN(LISTFILE,''''); END; END; PROCEDURE BLKOP; { LDC } VAR WERD,I,SKIPOVER:INTEGER; BEGIN WITH OPCODE[BITE]^ DO BEGIN TOTAL1:=TOTAL1 + 1; IF DISPLAY THEN WRITE(LISTFILE,NAMES[BITE]); BITE:=GETBYTE; IF DISPLAY THEN WRITELN(LISTFILE,BITE:6,' ':18,CODE); BYTESIZE:=MOSTSIGBIT(BITE); BYTEONE1[BYTESIZE]:=BYTEONE1[BYTESIZE] + 1; IF ODD(BYTEPOS) THEN SKIPOVER:=GETBYTE; FOR I:=1 TO BITE DO BEGIN HEXCOUNT:=0; CODE:=' '; WERD:=GETWORD; IF DISPLAY THEN WRITELN(LISTFILE,WERD:41,' ':18,CODE); END; END; END; (*$I DISASM1.TEXT *) (*$I DISASM2.TEXT*) BEGIN(*MAIN STUFF*) INIT; DISASSEMBLE; IF DATAWATCH THEN DATACOUNT; GATHER; IF DISPLAY AND NOT CONSOLE THEN CLOSE(LISTFILE,LOCK); END. { +------------------------------------------------------------------+ | | | F I N I S | | | +------------------------------------------------------------------+ }