{Copyright (c) Regents of University of California at San Diego} PROCEDURE PROCEJUR; VAR HEX:HEXTYPE; LINENUM,LPROCNUM:INTEGER; PROCEDURE JUMPINFO; VAR OTHERBYTE:INTEGER; BEGIN BACKJUMP:=0; BYTEPOS:=BYTEPOS - 6; OFFSET:=OFFSET - 6; REPEAT BACKJUMP:=BACKJUMP + 1; OTHERBYTE:=LASTBYTE; BITE:=LASTBYTE; IF (SWAP) AND (BITE<128) THEN {jumps relative to start of segment} JUMPS[BACKJUMP]:=BUFSTART + BYTEPOS - BITE*256 - OTHERBYTE ELSE IF (NOT SWAP) THEN IF OTHERBYTE<128 THEN JUMPS[BACKJUMP]:=BUFSTART + BYTEPOS - BITE - OTHERBYTE*256 ELSE BITE:=OTHERBYTE; UNTIL (BITE>127) OR (BACKJUMP=99); JUMPS[0]:=BACKJUMP - 1; IF BYTEPOS - OFFSET<0 THEN BYTEPOS:=BUFRESET(BUFSTART + BYTEPOS,-OFFSET,-1) ELSE BYTEPOS:=BYTEPOS - OFFSET; PROCSTART:=BUFSTART + BYTEPOS; {jumps now relative to start of procedure} FOR BACKJUMP:=1 TO JUMPS[0] DO JUMPS[BACKJUMP]:=JUMPS[BACKJUMP] - PROCSTART; END; BEGIN (*PROCEJUR*) IF PROCS[PROCNUM]=0 THEN WRITELN('Procedure not in file') ELSE BEGIN BYTEPOS:=SEGSIZE - BUFSTART - 2*(PROCNUM + 1) - PROCS[PROCNUM] - 2; IF BYTEPOS<0 THEN BYTEPOS:=BUFRESET(SEGSIZE - 2*(PROCNUM + 1),-PROCS[PROCNUM] - 2,-1) ELSE IF BYTEPOS>2556 THEN BYTEPOS:=BUFRESET(BUFSTART + BYTEPOS,0,1); OFFSET:=GETWORD; { pointer to ENTER IC } LPROCNUM:=GETBYTE; LEXLEVEL:=GETBYTE; BYTEPOS:=BYTEPOS - 4; IF LEXLEVEL=255 THEN LEXLEVEL:=-1; IF NOT (LEXCHECK OR LEXLOOK) THEN IF LPROCNUM=0 THEN WRITELN('Procedure ',PROCNUM:3,' is written in Assembly.') ELSE BEGIN JUMPINFO; DONEPROC:=FALSE; IF DISPLAY THEN WRITELN(LISTFILE, ' ':10,'BLOCK #',BYTEPOS DIV 512 + BUFSTBLK:3, ' OFFSET IN BLOCK=',BYTEPOS MOD 512:3,CR, 'SEGMENT PROC OFFSET#',' ':35,'HEX CODE') ELSE IF NOT CONTROL THEN BEGIN WRITE('.'); IF PROCNUM=50 THEN WRITE(CR,' '); END ELSE WRITE(CR,'[',PROCNUM:2,']'); LINENUM:=0; REPEAT HEX.WORD:=BUFSTART + BYTEPOS - PROCSTART; IF DISPLAY THEN WRITE(LISTFILE,SEGNUM:7,PROCNUM:5,HEX.WORD:6,'(', HEXCHAR[HEX.DUM1],HEXCHAR[HEX.HI],HEXCHAR[HEX.LO],'): '); IF CONTROL AND NOT CONSOLE THEN BEGIN WRITE('.'); LINENUM:=LINENUM + 1; IF (LINENUM MOD 50=0) THEN WRITE(CR,' '); END; HEXCOUNT:=0; CODE:=' '; BITE:=GETBYTE; OPTOTAL:=OPTOTAL + 1; CASE RECTYPES[BITE] OF SHORT:SHORTOP; CMPRSS:CMPRSSOP; CMPRSS2:CMPRSS2OP; ONE:ONEOP; CHRS:CHRSOP; BLK:BLKOP; OPT:OPTOP; LOPT:LOPTOP; TWO:TWOOP; WORDS:WORDSOP; WORD:WORDOP END; UNTIL DONEPROC; END; END; END; PROCEDURE ALLPROCS; VAR I,J,MAXDIST,INDEX:INTEGER; SORTNUMS:ARRAY[0..MAXPROCNUM] OF INTEGER; SORTPROCS:ARRAY[0..MAXPROCNUM] OF BYTE; BEGIN IF DISPLAY THEN BEGIN SORTNUMS:=PROCS; FOR I:=1 TO MAXPROCNUM DO SORTPROCS[I]:=I; FOR I:=1 TO PROCS[0] DO BEGIN MAXDIST:=0; INDEX:=0; FOR J:=I TO PROCS[0] DO IF SORTNUMS[J]>=MAXDIST THEN BEGIN MAXDIST:=SORTNUMS[J]; INDEX:=J; END; SORTNUMS[INDEX]:=SORTNUMS[I]; SORTNUMS[I]:=SORTPROCS[INDEX]; SORTPROCS[INDEX]:=SORTPROCS[I]; END; FOR I:=1 TO PROCS[0] DO BEGIN PROCNUM:=SORTNUMS[I]; PROCEJUR; END; END ELSE FOR PROCNUM:=1 TO PROCS[0] DO PROCEJUR; END; PROCEDURE SEGMINT; BEGIN IF SWAP THEN BEGIN SEGSTBLK:=SEGDIREC[SEGNUM*4 + 1]; SEGSIZE:=SEGDIREC[SEGNUM*4 + 3] + SEGDIREC[SEGNUM*4 + 2]*256; END ELSE BEGIN SEGSTBLK:=SEGDIREC[SEGNUM*4]; SEGSIZE:=SEGDIREC[SEGNUM*4 + 3]*256 + SEGDIREC[SEGNUM*4 + 2]; END; BUFSTBLK:=SEGSTBLK; IF SEGSIZE>2560 THEN BYTEPOS:=BUFRESET(SEGSIZE,-1,1) ELSE BYTEPOS:=BUFRESET(SEGSIZE,-1,0); PROCS[0]:=BUFFER[BYTEPOS]; (* number of procs in segment *) BYTEPOS:=BYTEPOS - 2*PROCS[0] - 1; FOR PROCNUM:=PROCS[0] DOWNTO 1 DO PROCS[PROCNUM]:=GETWORD; IF NOT (CONTROL OR LEXCHECK) THEN ALLPROCS; END; PROCEDURE ACTACCESS; {FINALEX,OFFSET:INTEGER;} VAR FINALPROC,FINALSEG:INTEGER; INSIDE:BOOLEAN; BEGIN IF (FINALEX=PROCLEX[DATAPROC]) AND (PROCNUM>=DATAPROC) THEN IF SEGNUM=DATASEG THEN BEGIN INSIDE:=(PROCNUM=DATAPROC); FINALPROC:=PROCNUM; WHILE PROCLEX[FINALPROC]>PROCLEX[DATAPROC] DO FINALPROC:=FINALPROC - 1; IF FINALPROC=DATAPROC THEN {$R-} DSSTART^[OFFSET]:=DSSTART^[OFFSET] + 1; {$R+} END ELSE IF (DATAPROC=1) AND (SEGNUM>DATASEG) THEN BEGIN FINALSEG:=SEGNUM; WHILE SEGLEX[FINALSEG]>SEGLEX[DATASEG] DO FINALSEG:=FINALSEG - 1; IF FINALSEG=DATASEG THEN {$R-} DSSTART^[OFFSET]:=DSSTART^[OFFSET] + 1; {$R+} END; END; PROCEDURE PROCGUIDE; TYPE SPACEPTR=^SPACE; SPACE=ARRAY[0..19] OF INTEGER; VAR I,J:INTEGER; DSSPACE:SPACEPTR; PROCEDURE DATASEGINFO; VAR TEMP:INTEGER; BEGIN PROCEJUR; BYTEPOS:=BYTEPOS - 2; IF SWAP THEN BEGIN DTSGSZ:=LASTBYTE; DTSGSZ:=DTSGSZ + LASTBYTE*256; TEMP:=LASTBYTE; DTSGSZ:=DTSGSZ + LASTBYTE*256 + TEMP; END ELSE BEGIN DTSGSZ:=LASTBYTE*256; DTSGSZ:=DTSGSZ + LASTBYTE; TEMP:=LASTBYTE*256; DTSGSZ:=DTSGSZ + LASTBYTE + TEMP; END; DTSGSZ:=DTSGSZ DIV 2; END; PROCEDURE PROCLOOK; BEGIN GOTOXY(0,3); WRITE(' ':50); GOTOXY(0,3); LEXLOOK:=TRUE; I:=(PROCS[0] DIV 5) + 1; FOR J:=0 TO ((PROCS[0]-1) DIV I) DO WRITE(' # LL SIZE'); WRITELN; FOR PROCNUM:=1 TO PROCS[0] DO BEGIN DATASEGINFO; GOTOXY(15*((PROCNUM-1) DIV I),5+((PROCNUM-1) MOD I)); WRITE(PROCNUM:5,':',LEXLEVEL:3,DTSGSZ:6); END; FOR J:=1 TO (5 - (PROCS[0] MOD 5)) DO WRITELN; PROMPT; LEXLOOK:=FALSE; END; BEGIN {PROCGUIDE} SEGMINT; REPEAT PAGE(OUTPUT); WRITE('Procedure guide: #(of procedure),'); IF LEXCHECK THEN WRITELN('L(isting),Q(uit)') ELSE WRITELN('A(ll),L(isting),Q(uit)'); WRITE(' to segment: '); FOR I:=1 TO 8 DO WRITE(CHR(SEGDIREC[63 + SEGNUM*8 + I])); PROCNUM:=0; WRITE(CR,CR,'which procedure '); IF LEXCHECK THEN WRITE('data segment to watch?') ELSE WRITE('to dis-assemble?'); READ(CH); IF (CH='L') THEN PROCLOOK ELSE IF (CH='A') AND (NOT LEXCHECK) THEN BEGIN PAGE(OUTPUT); WRITELN('dis-assembling all',PROCS[0]:3,' procedures',CR,CR); IF NOT DISPLAY THEN WRITE(CR,CR,'(',SEGNUM:2,')'); ALLPROCS; PROMPT; CH:='Q'; END ELSE IF (CH>='0') AND (CH<='9') THEN BEGIN PROCNUM:=ORD(CH)-ORD('0'); READ(CH); IF (CH>='0') AND (CH<='9') THEN PROCNUM:=PROCNUM*10 + ORD(CH) - ORD('0'); IF (PROCNUM<1) OR (PROCNUM>PROCS[0]) THEN BEGIN WRITELN(CR,'I didn''t say you had THAT procedure!'); PROMPT; END ELSE IF NOT LEXCHECK THEN BEGIN PAGE(OUTPUT); WRITELN('dis-assembling procedure',PROCNUM:3,CR); PROCEJUR; PROMPT; CH:=' '; END ELSE BEGIN DATAPROC:=PROCNUM; DATASEG:=SEGNUM; DATASEGINFO; DATASEGSIZE:=DTSGSZ; NEW(DSSTART); FOR I:=1 TO ((DATASEGSIZE+19) DIV 20) DO NEW(DSSPACE); FILLCHAR(DSSTART^,DATASEGSIZE*2,0); FOR PROCNUM:=1 TO PROCS[0] DO BEGIN PROCEJUR; PROCLEX[PROCNUM]:=LEXLEVEL; END; CH:=CHR(7); END; END; UNTIL (CH='Q') OR (CH=CHR(7)); END; PROCEDURE SEGMTGUIDE; VAR I,J:INTEGER; BEGIN REPEAT PAGE(OUTPUT); WRITELN('Segment guide: #(of segment),Q(uit)'); WRITELN(CR,CR,'you have these segments:'); FOR I:=0 TO 15 DO BEGIN WRITE(I:4,' '); FOR J:=1 TO 8 DO WRITE(CHR(SEGDIREC[63 + I*8 + J])); WRITELN; END; WRITE(CR,'which segment to look at '); IF LEXCHECK THEN WRITE('to decide on DATA SEGMENT?') ELSE WRITE('for possible DIS-ASSEMBLY?'); READ(CH); IF CH<>'Q' THEN BEGIN SEGNUM:=0; IF (CH>='0') AND (CH<='9') THEN SEGNUM:=ORD(CH)-ORD('0'); READ(CH); IF (CH>='0') AND (CH<='9') THEN SEGNUM:=SEGNUM*10 + ORD(CH) - ORD('0'); IF (SEGDIREC[4*SEGNUM] + SEGDIREC[4*SEGNUM + 1]=0) OR (SEGNUM>15) THEN BEGIN WRITELN(CR,'I didn''t say you had THAT segment!'); READ(KEYBOARD,CH); END ELSE BEGIN PROCGUIDE; IF CH<>CHR(7) THEN CH:='A'; END; END; UNTIL (CH='Q') OR (CH=CHR(7)); END; PROCEDURE LEXGUIDE; BEGIN LEXCHECK:=TRUE; DATASEG:=-1; REPEAT SEGMTGUIDE; IF CH='Q' THEN BEGIN PAGE(OUTPUT); GOTOXY(0,10); WRITELN('have you changed your mind about data segment watching?'); READ(KEYBOARD,CH); IF CH='Y' THEN DATAWATCH:=FALSE; END; UNTIL (CH=CHR(7)) OR (NOT DATAWATCH); IF DATAWATCH THEN FOR SEGNUM:=0 TO 15 DO IF SEGDIREC[4*SEGNUM] + SEGDIREC[4*SEGNUM + 1]<>0 THEN BEGIN SEGMINT; {Sets up appropiate segment} PROCNUM:=1; PROCEJUR; {Sets up procedure to determine segment's lexlevel} SEGLEX[SEGNUM]:=LEXLEVEL; END ELSE SEGLEX[SEGNUM]:=100; PAGE(OUTPUT); LEXCHECK:=FALSE; END; BEGIN (* SEGMENT DISASSEMBLE *) PAGE(OUTPUT); GOTOXY(0,10); WRITE(' Do you wish to keep track of references',CR, ' to a particular procedure''s data segment?'); READ(KEYBOARD,CH); DATAWATCH:=(CH='Y'); IF DATAWATCH THEN LEXGUIDE ELSE LEXCHECK:=FALSE; PAGE(OUTPUT); GOTOXY(0,10); WRITE('Do you wish control over dis-assembly?'); READ(KEYBOARD,CH); CONTROL:=(CH='Y'); IF CONTROL THEN BEGIN PAGE(OUTPUT); GOTOXY(0,7); WRITE(CHR(7)); WRITE('*** WARNING - - STATISTICS ARE GATHERED ON DIS-ASSEMBLED'); WRITELN(' PROCEDURES ONLY ***'); IF DATAWATCH THEN WRITELN(CR,CR,' ', '*** THIS INCLUDES DATA SEGMENT WATCHING ***'); READ(KEYBOARD,CH); SEGMTGUIDE; END ELSE BEGIN IF NOT CONSOLE THEN WRITE(CHR(12),CR); FOR SEGNUM:=0 TO 15 DO BEGIN IF NOT DISPLAY THEN WRITE(CR,'(',SEGNUM:2,')'); IF SEGDIREC[4*SEGNUM] + SEGDIREC[4*SEGNUM + 1]<>0 THEN SEGMINT; END; PROMPT; END; END;