1 /* Dumprun.c Dumps the contents of a MMURTL Run file (DLL or Device Driver*/
\r
4 #define U32 unsigned long
\r
6 #define U16 unsigned int
\r
8 #define U8 unsigned char
\r
18 #include "runfile.h"
\r
20 /* disassembler data */
\r
24 int seg_size = 32; /* set to 32 for /3 option */
\r
25 int fRaw = 0; /* dump raw byte too? */
\r
32 /* The Intel 386 Software Writers Guide provides a table that uses the
\r
33 following codes to assist in manual disassembly of 386 code. The
\r
34 letters below are the same as the codes in the manual. The % (vertical
\r
35 bar is an escape character - like in c - to signify expansion of the codes is
\r
36 required when the string is being outut.
\r
41 "ADD %Eb,%Gb", "ADD %Ev,%Gv", "ADD %Gb,%Eb", "ADD %Gv,%Ev",
\r
42 "ADD AL,%Ib", "ADD %eAX,%Iv", "PUSH ES", "POP ES",
\r
43 "OR %Eb,%Gb", "OR %Ev,%Gv", "OR %Gb,%Eb", "OR %Gv,%Ev",
\r
44 "OR AL,%Ib", "OR %eAX,%Iv", "PUSH CS", "%2 ",
\r
46 "ADC %Eb,%Gb", "ADC %Ev,%Gv", "ADC %Gb,%Eb", "ADC %Gv,%Ev",
\r
47 "ADC AL,%Ib", "ADC %eAX,%Iv", "PUSH SS", "POP SS",
\r
48 "SBB %Eb,%Gb", "SBB %Ev,%Gv", "SBB %Gb,%Eb", "SBB %Gv,%Ev",
\r
49 "SBB AL,%Ib", "SBB %eAX,%Iv", "PUSH DS", "POP DS",
\r
51 "AND %Eb,%Gb", "AND %Ev,%Gv", "AND %Gb,%Eb", "AND %Gv,%Ev",
\r
52 "AND AL,%Ib", "AND %eAX,%Iv", "%pE", "DAA",
\r
53 "SUB %Eb,%Gb", "SUB %Ev,%Gv", "SUB %Gb,%Eb", "SUB %Gv,%Ev",
\r
54 "SUB AL,%Ib", "SUB %eAX,%Iv", "%pC", "DAS",
\r
56 "XOR %Eb,%Gb", "XOR %Ev,%Gv", "XOR %Gb,%Eb", "XOR %Gv,%Ev",
\r
57 "XOR AL,%Ib", "XOR %eAX,%Iv", "%pS", "AAA",
\r
58 "CMP %Eb,%Gb", "CMP %Ev,%Gv", "CMP %Gb,%Eb", "CMP %Gv,%Ev",
\r
59 "CMP AL,%Ib", "CMP %eAX,%Iv", "%pD", "AAS",
\r
61 "INC %eAX", "INC %eCX", "INC %eDX", "INC %eBX",
\r
62 "INC %eSP", "INC %eBP", "INC %eSI", "INC %eDI",
\r
63 "DEC %eAX", "DEC %eCX", "DEC %eDX", "DEC %eBX",
\r
64 "DEC %eSP", "DEC %eBP", "DEC %eSI", "DEC %eDI",
\r
66 "PUSH %eAX", "PUSH %eCX", "PUSH %eDX", "PUSH %eBX",
\r
67 "PUSH %eSP", "PUSH %eBP", "PUSH %eSI", "PUSH %eDI",
\r
68 "POP %eAX", "POP %eCX", "POP %eDX", "POP %eBX",
\r
69 "POP %eSP", "POP %eBP", "POP %eSI", "POP %eDI",
\r
71 "PUSHA", "POPA", "BOUND %Gv,%Ma", "ARPL %Ew,%Rw",
\r
72 "%pF", "%pG", "%so", "%sa",
\r
73 "PUSH %Iv", "IMUL %Gv=%Ev*%Iv", "PUSH %Ib", "IMUL %Gv=%Ev*%Ib",
\r
74 "INSB %Yb,DX", "INS%ew %Yv,DX", "OUTSB DX,%Xb", "OUTS%ew DX,%Xv",
\r
76 "JO %Jb", "JNO %Jb", "JC %Jb", "JNC %Jb",
\r
77 "JZ %Jb", "JNZ %Jb", "JBE %Jb", "JNBE %Jb",
\r
78 "JS %Jb", "JNS %Jb", "JPE %Jb", "JPO %Jb",
\r
79 "JL %Jb", "JGE %Jb", "JLE %Jb", "JG %Jb",
\r
81 "%g1 %Eb,%Ib", "%g1 %Ev,%Iv", "MOV AL,%Ib", "%g1 %Ev,%Ib",
\r
82 "TEST %Eb,%Gb", "TEST %Ev,%Gv", "XCHG %Eb,%Gb", "XCHG %Ev,%Gv",
\r
83 "MOV %Eb,%Gb", "MOV %Ev,%Gv", "MOV %Gb,%Eb", "MOV %Gv,%Ev",
\r
84 "MOV %Ew,%Sw", "LEA %Gv,%M ", "MOV %Sw,%Ew", "POP %Ev",
\r
86 "NOP", "XCHG %eAX,%eCX", "XCHG %eAX,%eDX", "XCHG %eAX,%eBX",
\r
87 "XCHG %eAX,%eSP", "XCHG %eAX,%eBP", "XCHG %eAX,%eSI", "XCHG %eAX,%eDI",
\r
88 "CBW", "CDW", "CALL %Ap", "FWAIT",
\r
89 "PUSH %eflags", "POP %eflags", "SAHF", "LAHF",
\r
91 "MOV AL,%Ov", "MOV %eAX,%Ov", "MOV %Ov,al", "MOV %Ov,%eAX",
\r
92 "MOVSB %Xb,%Yb", "MOVS%ew %Xv,%Yv", "CMPSB %Xb,%Yb", "CMPS%ew %Xv,%Yv",
\r
93 "TEST AL,%Ib", "TEST %eAX,%Iv", "STOSB %Yb,AL", "STOS%ew %Yv,%eAX",
\r
94 "LODSB AL,%Xb", "LODS%ew %eAX,%Xv", "SCASB AL,%Xb", "SCAS%ew %eAX,%Xv",
\r
96 "MOV AL,%Ib", "MOV CL,%Ib", "MOV DL,%Ib", "MOV BL,%Ib",
\r
97 "MOV AH,%Ib", "MOV CH,%Ib", "MOV DH,%Ib", "MOV BH,%Ib",
\r
98 "MOV %eAX,%Iv", "MOV %eCX,%Iv", "MOV %eDX,%Iv", "MOV %eBX,%Iv",
\r
99 "MOV %eSP,%Iv", "MOV %eBP,%Iv", "MOV %eSI,%Iv", "MOV %eDI,%Iv",
\r
101 "%g2 %Eb,%Ib", "%g2 %Ev,%Ib", "RET %Iw", "RET",
\r
102 "LES %Gv,%Mp", "LDS %Gv,%Mp", "MOV %Eb,%Ib", "MOV %Ev,%Iv",
\r
103 "ENTER %Iw,%Ib", "LEAVE", "RETF %Iw", "RETF",
\r
104 "INT 3", "INT %Ib", "INTO", "IRET",
\r
106 "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
\r
107 "AAM", "AAD", 0, "XLAT",
\r
110 "ESC 0,%Ib", "ESC 1,%Ib", "ESC 2,%Ib", "ESC 3,%Ib",
\r
111 "ESC 4,%Ib", "ESC 5,%Ib", "ESC 6,%Ib", "ESC 7,%Ib",
\r
114 "%f0", "%f1", "%f2", "%f3",
\r
115 "%f4", "%f5", "%f6", "%f7",
\r
119 "LOOPNE %Jb", "LOOPE %Jb", "LOOP %Jb", "JCXZ %Jb",
\r
120 "IN AL,%Ib", "IN %eAX,%Ib", "OUT %Ib,AL", "OUT %Ib,%eAX",
\r
121 "CALL %Jv", "JMP %Jv", "JMP %Ap", "JMP %Jb",
\r
122 "IN AL,DX", "IN %eAX,DX", "OUT DX,AL", "OUT DX,%eAX",
\r
124 "LOCK%p ", 0, "REPNE%p ", "REP(e)%p ",
\r
125 "HLT", "CMC", "%g3", "%g0",
\r
126 "CLC", "STC", "CLI", "STI",
\r
127 "CLD", "STD", "%g4", "%g5"
\r
130 char *SecOp00[] = {
\r
132 "%g6", "%g7", "LAR %Gv,%Ew", "LSL %Gv,%Ew", 0, 0, "CLTS", 0,
\r
133 0, 0, 0, 0, 0, 0, 0, 0 };
\r
135 char *SecOp20[] = {
\r
137 "MOV %Rd,%Cd", "MOV %Rd,%Dd", "MOV %Cd,%Rd", "MOV %Dd,%Rd",
\r
138 "MOV %Rd,%Td", 0, "MOV %Td,%Rd", 0,
\r
139 0, 0, 0, 0, 0, 0, 0, 0};
\r
141 char *SecOp80[] = {
\r
142 "JO %Jv", "JNO %Jv", "JC %Jv", "JNC %Jv", /*RAB Rev JNC /JC */
\r
143 "JZ %Jv", "JNZ %Jv", "JBE %Jv", "JNBE %Jv",
\r
144 "JS %Jv", "JNS %Jv", "JPE %Jv", "JPO %Jv",
\r
145 "JL %Jv", "JGE %Jv", "JLE %Jv", "JG %Jv",
\r
147 "SETO %Eb", "SETNO %Eb", "SETNC %Eb", "SETC %Eb",
\r
148 "SETZ %Eb", "SETNZ %Eb", "SETBE %Eb", "SETNBE %Eb",
\r
149 "SETS %Eb", "SETNS %Eb", "SETP %Eb", "SETNP %Eb",
\r
150 "SETL %Eb", "SETGE %Eb", "SETLE %Eb", "SETG %Eb",
\r
152 "PUSH FS", "POP FS", 0, "BT %Ev,%Gv",
\r
153 "SHLD %Ev,%Gv,%Ib", "SHLD %Ev,%Gv,cl", 0, 0,
\r
154 "PUSH GS", "POP GS", 0, "BTS %Ev,%Gv",
\r
155 "SHRD %Ev,%Gv,%Ib", "SHRD %Ev,%Gv,cl", 0, "IMUL %Gv,%Ev",
\r
158 0, 0, "LSS %Mp", "BTR %Ev,%Gv",
\r
159 "LFS %Mp", "LGS %Mp", "MOVZX %Gv,%Eb", "MOVZX %Gv,%Ew",
\r
160 0, 0, "%g8 %Ev,%Ib", "BTC %Ev,%Gv",
\r
161 "BSF %Gv,%Ev", "BSR%Gv,%Ev", "MOVSX %Gv,%Eb", "MOVSX %Gv,%Ew",
\r
164 /* NOTE: Second byte of 2 byte OpCodes are Invalid if Over 0xBF */
\r
167 char *groups[9][8] = { /* group 0 is group 3 for %Ev set */
\r
168 { "TEST %Ev,%Iv", "TEST %Ev,%Iv,", "NOT %Ev", "NEG %Ev",
\r
169 "MUL %eAX,%Ev", "IMUL %eAX,%Ev", "DIV %eAX,%Ev", "IDIV %eAX,%Ev" },
\r
170 { "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP" },
\r
171 { "ROL", "ROR", "RCL", "RCR", "SHL", "SHR", "SHL", "SAR" },
\r
172 { "TEST %Eb,%Ib", "TEST %Eb,%Ib,", "NOT %Eb", "NEG %Eb",
\r
173 "MUL AL,%Eb", "IMUL AL,%Eb", "DIV AL,%Eb", "IDIV AL,%Eb" },
\r
174 { "INC %Eb", "DEC %Eb", 0, 0, 0, 0, 0, 0 },
\r
175 { "INC %Ev", "DEC %Ev", "CALL %Ev", "CALL %Ep",
\r
176 "JMP %Ev", "JMP %Ep", "PUSH %Ev", 0 },
\r
177 { "SLDT %Ew", "STR %Ew", "LLDT %Ew", "LTR %Ew",
\r
178 "VERR %Ew", "VERW %Ew", 0, 0 },
\r
179 { "SGDT %Ms", "SIDT %Ms", "LGDT %Ms", "LIDT %Ms",
\r
180 "SMSW %Ew", 0, "LMSW %Ew", 0 },
\r
181 { 0, 0, 0, 0, "BT", "BTS", "BTR", "BTC" }
\r
185 char *seg_names[]= {"ES","CS","SS","DS","FS","GS"};
\r
186 char *breg_names[]={"AL","CL","DL","BL","AH","CH","DH","BH" };
\r
187 char *wreg_names[]={"AX","CX","DX","BX","SP","BP","SI","DI" };
\r
188 char *dreg_names[]={"EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI" };
\r
199 /* Run file data */
\r
201 char *pCode, *pData, *pStack; /* Ptrs in User mem to load to */
\r
202 long sCode, sData, sStack; /* Size of segments */
\r
203 unsigned long oCode, oData; /* Offset in file to Code & Data */
\r
204 unsigned long offCode, offData; /* Virtual Offset for Code & Data Segs */
\r
205 unsigned long nCDFIX, oCDFIX,
\r
212 struct tagtype tag;
\r
214 FILE *run_fh = 0; /* Current .RUN, .DLL, or .DDR (output) */
\r
215 FILE *out_fh = 0; /* Output file */
\r
221 char fDumpData = 0;
\r
224 /*********************************************
\r
225 Dumps all bytes pointed to to stream with
\r
226 offset printed in front of each line.
\r
233 unsigned char buff[17];
\r
234 unsigned char line[78]; /* Addr xx xx xx xx... ASCII */
\r
244 sprintf(line, "%08lX ", addr); /* print current offset */
\r
246 fread (buff, 1, j, run_fh); /* Read j bytes from stream */
\r
248 for (i=0; i<j; i++) {
\r
250 sprintf(&line[11 + (i*3)], "%02lX ", val);
\r
251 if (buff[i] < 0x20)
\r
253 if (buff[i] > 0x7F)
\r
255 line[i+61] = buff[i]; /* printed char */
\r
261 fprintf(out_fh, "%s\r\n", line); /* put in chars */
\r
271 /*****************************************************
\r
272 Gets a byte to disassemble saving the raw bytes that
\r
273 make it up in RawBuf[nRaw].
\r
274 ******************************************************/
\r
282 if (i==EOF) fEOF = 1;
\r
285 RawBuf[nRaw++] = b;
\r
291 /*************************************************/
\r
292 /* Get Mod/RM field byte for current instruction */
\r
297 modrmv = getbyte();
\r
304 /*************************************************/
\r
305 /* Get 'scale-index-base' byte for current instruction */
\r
316 /**********************************************************/
\r
317 /* Macros to shift or mask a byte so bit type data such as
\r
318 reg or mod can be pulled out of certain instruction
\r
322 #define mod(a) (((a)>>6)&7)
\r
323 #define reg(a) (((a)>>3)&7)
\r
324 #define rm(a) ((a)&7)
\r
325 #define ss(a) (((a)>>6)&7)
\r
326 #define indx(a) (((a)>>3)&7)
\r
327 #define base(a) ((a)&7)
\r
329 /*------------------------------------------------------------------------*/
\r
331 /**************************************
\r
332 * Write a decimal number to a file fout
\r
333 ***************************************/
\r
335 void put_num(U32 value, FILE *fout)
\r
340 if(value & 0x80000000) {
\r
345 stack[i++] = (value % 10) + '0';
\r
346 while(value /= 10);
\r
348 fputc(stack[--i], fout);
\r
352 /**************************************
\r
353 Write a Hex byte to a file fout.
\r
354 ***************************************/
\r
356 void put_hexb(U8 value, FILE *fout)
\r
363 stack[i] = (value % 16) + '0';
\r
364 if (stack[i] > 0x39)
\r
368 while(value /= 16);
\r
369 while (i < j--) { /* zero pad front end to width */
\r
373 fputc(stack[--i], fout);
\r
377 /**************************************
\r
378 Write a Hex number to a file fout.
\r
379 ***************************************/
\r
381 void put_hexw(U16 value, FILE *fout)
\r
389 stack[i] = (value % 16) + '0';
\r
390 if (stack[i] > 0x39)
\r
394 while(value /= 16);
\r
395 while (i < j--) { /* zero pad front end to width */
\r
399 fputc(stack[--i], fout);
\r
403 /**************************************
\r
404 Write a hex dword to a file fout.
\r
405 ***************************************/
\r
407 void put_hexd(U32 value, FILE *fout)
\r
415 stack[i] = (value % 16) + '0';
\r
416 if (stack[i] > 0x39)
\r
420 while(value /= 16);
\r
421 while (i < j--) { /* zero pad front end to width */
\r
425 fputc(stack[--i], fout);
\r
429 /*------------------------------------------------------------------------*/
\r
430 /* determines how many bytes left in the instruction from the
\r
431 letter in the table (which is passed in here). "v" is a variable
\r
432 number based on current segment size of code descriptor.
\r
454 /**************************************************************
\r
455 Get the correct number of bytes for immediate data from the
\r
456 code stream and output it as hex.
\r
457 ***************************************************************/
\r
459 void ohex(char c, int extend, int optional, int defsize)
\r
463 unsigned char buf[6];
\r
473 case 'b': /* byte */
\r
476 case 'w': /* word */
\r
479 case 'd': /* dword */
\r
482 case 's': /* fword */
\r
492 case 'p': /* 32 or 48 bit pointer */
\r
501 for (i=0; i<n; i++)
\r
502 buf[i] = getbyte();
\r
504 /* sign extend the value into a U32 */
\r
506 for (; i<extend; i++)
\r
507 buf[i] = (buf[i-1] & 0x80) ? 0xff : 0;
\r
509 if (s) /* outputs the segment value of FAR pointer */
\r
512 fprintf(out_fh,"%02X%02X",buf[n-1],buf[n-2]);
\r
514 put_hexb(buf[n-1], out_fh);
\r
515 put_hexb(buf[n-2], out_fh);
\r
523 fprintf(out_fh,"+");
\r
529 fprintf(out_fh,"%02X",buf[0]);
\r
530 /* put_hexb(buf[0], out_fh); */
\r
534 fprintf(out_fh,"%02X%02X",buf[1],buf[0]);
\r
535 /* put_hexb(buf[1], out_fh);
\r
536 put_hexb(buf[0], out_fh);
\r
541 fprintf(out_fh,"%02X%02X%02X%02X",buf[3],buf[2],buf[1],buf[0]);
\r
543 put_hexb(buf[3], out_fh);
\r
544 put_hexb(buf[2], out_fh);
\r
545 put_hexb(buf[1], out_fh);
\r
546 put_hexb(buf[0], out_fh);
\r
553 /*------------------------------------------------------------------------*/
\r
555 void reg_name(U8 which, char size)
\r
559 fprintf(out_fh, "st(%d)",which);
\r
563 if (((size == 'v') && (opsize == 32)) || (size == 'd'))
\r
565 fprintf(out_fh,"E");
\r
569 fprintf(out_fh, "%s", breg_names[which]);
\r
573 fprintf(out_fh, "%s", wreg_names[which]);
\r
577 /******************************************************************
\r
578 This takes in a two chars that represent part of the op code and
\r
579 puts out the proper text to match what the letter represents.
\r
580 c is the first char after the dollar sign and t is next one. See
\r
581 opcode1[] strings for what the chars mean.
\r
582 *******************************************************************/
\r
584 void escape(char c, char t)
\r
587 S32 delta, vofs, tmp;
\r
594 extend = (addrsize == 32) ? 4 : 2;
\r
598 case 'A': /* Direct Address */
\r
599 ohex(t, extend, 0, addrsize);
\r
601 case 'C': /* Reg of R/M picks control reg */
\r
602 fprintf(out_fh, "CR%d",reg(modrm()));
\r
604 case 'D': /* Reg of R/M pick debug reg */
\r
605 fprintf(out_fh, "DR%d",modrm());
\r
607 case 'E': /* R/M picks operand */
\r
610 case 'G': /* Reg of R/M picks general reg */
\r
612 reg_name(rm(modrm()), t);
\r
614 reg_name(reg(modrm()), t);
\r
616 case 'I': /* Immediate data */
\r
617 ohex(t, 0, 0, opsize);
\r
619 case 'J': /* Relative IP offset */
\r
623 vofsb = getbyte(); /* must remian signed! */
\r
627 vofsb = getbyte(); /*Must be Signed bytes/Words */
\r
628 vofsw = getbyte()<<8;
\r
629 vofs = vofsw + vofsb;
\r
641 delta = addrIn + vofs;
\r
642 fprintf(out_fh, "%08lX", delta);
\r
644 case 'M': /* R/M picks memory */
\r
647 case 'O': /* NO R/M, Offset only */
\r
648 expand_out("%p:[");
\r
649 ohex(t, extend, 0, addrsize);
\r
650 fprintf(out_fh,"]");
\r
652 case 'R': /* Mod of R/M pick REG only */
\r
655 case 'S': /* Reg of R/M picks seg reg */
\r
656 fprintf(out_fh, "%s", seg_names[reg(modrm())]);
\r
658 case 'T': /* Reg of R/M picks test reg */
\r
659 fprintf(out_fh, "TR%d",modrm());
\r
661 case 'X': /* DS:ESI */
\r
662 fprintf(out_fh,"DS:[");
\r
663 if (addrsize == 32)
\r
664 fprintf(out_fh,"E");
\r
665 fprintf(out_fh,"SI]");
\r
667 case 'Y': /* ES:EDI */
\r
668 fprintf(out_fh,"ES:[");
\r
669 if (addrsize == 32)
\r
670 fprintf(out_fh,"E");
\r
671 fprintf(out_fh,"DI]");
\r
673 case '2': /* Prefix of 2 byte opcode */
\r
676 expand_out(SecOp00[b2]);
\r
677 else if ((b2 > 0x1F) && (b2 < 0x30))
\r
678 expand_out(SecOp20[b2-0x20]);
\r
679 else if ((b2 > 0x7F) && (b2 < 0xC0))
\r
680 expand_out(SecOp80[b2-0x80]);
\r
682 fprintf(out_fh, "<invalid>");
\r
684 case 'e': /* If "USE32" t is part of reg name */
\r
687 if (t == 'w') /* put out "d" if t is "w" on USE32 segs*/
\r
688 fprintf(out_fh,"D");
\r
691 fprintf(out_fh,"E"); /* put out "E" if not t <> "w" then put t */
\r
696 fputc(t, out_fh); /* when USE16 just put out esc char */
\r
699 case 'f': /* floating point */
\r
700 fprintf(out_fh,"<Float Op>");
\r
702 /* floating_point(t-'0'); */
\r
705 case 'g': /* do R/M group 'n' */
\r
706 expand_out(groups[t-'0'][reg(modrm())]);
\r
708 case 'p': /* Segment prefix */
\r
718 expand_out(opmap1[getbyte()]);
\r
722 fputc(prefix, out_fh);
\r
723 fprintf(out_fh,"S:");
\r
727 expand_out(opmap1[getbyte()]);
\r
731 case 's': /* Size override */
\r
735 addrsize = 48 - addrsize; /* a is address */
\r
736 expand_out(opmap1[getbyte()]);
\r
738 case 'o': /* o is operand */
\r
739 opsize = 48 - opsize;
\r
740 expand_out(opmap1[getbyte()]);
\r
748 /******************************************
\r
749 This expands and outputs the instruction
\r
750 string passed in if it find the escape
\r
751 character (vertical bar).
\r
752 ******************************************/
\r
754 void expand_out(char *s)
\r
759 if (s == 0) /* if NULL pointer, then it's BAD */
\r
761 fprintf(out_fh,"<invalid>");
\r
763 while ((c = *s++) != 0) /* put next char in c */
\r
765 if (c == '%') /* if c is % then ESCAPE */
\r
767 c = *s++; /* get letter representing value */
\r
771 if (c == ' ') /* if space, put TAB in string */
\r
772 fprintf(out_fh," ");
\r
774 fputc(c, out_fh); /* else put out the char found! */
\r
780 /* outputs 'scale-index-base' instructions */
\r
790 case 0: expand_out("%p:[EAX"); break;
\r
791 case 1: expand_out("%p:[ECX"); break;
\r
792 case 2: expand_out("%p:[EDX"); break;
\r
793 case 3: expand_out("%p:[EBX"); break;
\r
794 case 4: expand_out("%p:[ESP"); break;
\r
798 expand_out("%p:[");
\r
799 ohex('d', 4, 0, addrsize);
\r
802 expand_out("%p:[EBP");
\r
804 case 6: expand_out("%p:[ESI"); break;
\r
805 case 7: expand_out("%p:[EDI"); break;
\r
809 case 0: fprintf(out_fh,"+EAX"); break;
\r
810 case 1: fprintf(out_fh,"+ECX"); break;
\r
811 case 2: fprintf(out_fh,"+EDX"); break;
\r
812 case 3: fprintf(out_fh,"+EBX"); break;
\r
814 case 5: fprintf(out_fh,"+EBP"); break;
\r
815 case 6: fprintf(out_fh,"+ESI"); break;
\r
816 case 7: fprintf(out_fh,"+EDI"); break;
\r
822 case 1: fprintf(out_fh,"*2"); break;
\r
823 case 2: fprintf(out_fh,"*4"); break;
\r
824 case 3: fprintf(out_fh,"*8"); break;
\r
828 /*------------------------------------------------------------------------*/
\r
829 void do_modrm(char t)
\r
837 extend = (addrsize == 32) ? 4 : 2;
\r
844 if ((m == 0) && (r == 5) && (addrsize == 32))
\r
846 expand_out("%p:[");
\r
847 ohex('d', extend, 0, addrsize);
\r
848 fprintf(out_fh,"]");
\r
851 if ((m == 0) && (r == 6) && (addrsize == 16))
\r
853 expand_out("%p:[");
\r
854 ohex('w', extend, 0, addrsize);
\r
855 fprintf(out_fh,"]");
\r
858 if ((addrsize != 32) || (r != 4))
\r
859 expand_out("%p:[");
\r
860 if (addrsize == 16)
\r
864 case 0: fprintf(out_fh,"BX+SI"); break;
\r
865 case 1: fprintf(out_fh,"BX+DI"); break;
\r
866 case 2: fprintf(out_fh,"BP+SI"); break;
\r
867 case 3: fprintf(out_fh,"BP+DI"); break;
\r
868 case 4: fprintf(out_fh,"SI"); break;
\r
869 case 5: fprintf(out_fh,"DI"); break;
\r
870 case 6: fprintf(out_fh,"BP"); break;
\r
871 case 7: fprintf(out_fh,"BX"); break;
\r
878 case 0: fprintf(out_fh,"EAX"); break;
\r
879 case 1: fprintf(out_fh,"ECX"); break;
\r
880 case 2: fprintf(out_fh,"EDX"); break;
\r
881 case 3: fprintf(out_fh,"EBX"); break;
\r
882 case 4: do_sib(m); break;
\r
883 case 5: fprintf(out_fh,"EBP"); break;
\r
884 case 6: fprintf(out_fh,"ESI"); break;
\r
885 case 7: fprintf(out_fh,"EDI"); break;
\r
891 ohex('b', extend, 0, addrsize); /* was 1 */
\r
894 fprintf(out_fh,"+");
\r
895 ohex('v', extend, 0, addrsize); /* was 1 */
\r
898 fprintf(out_fh,"]");
\r
901 /***********************************************
\r
902 This disassembles one instruction each time it
\r
904 ************************************************/
\r
906 U32 disassemble(void)
\r
912 char *name, *lname;
\r
918 opsize = addrsize = seg_size;
\r
920 fprintf(out_fh, "%08lX ", addrIn);
\r
922 expand_out(opmap1[getbyte()]); /* decode instruction and output */
\r
926 fprintf(out_fh, " ");
\r
928 put_hexb(RawBuf[i++], out_fh);
\r
929 fprintf(out_fh, " ");
\r
933 fprintf(out_fh, "\r\n");
\r
938 /************************************************
\r
939 * Write part of an instruction to the file "fi"
\r
940 *************************************************/
\r
942 void put_str(char *ptr, FILE *fi)
\r
948 /*******************************************
\r
949 * Report a non-recoverable error
\r
950 ********************************************/
\r
952 void fatal_error(char *string)
\r
954 put_str(string, stderr);
\r
955 put_str("Disassembly aborted\r\n", stderr);
\r
960 /*********************************************************
\r
961 This reads and dumps a RUN file with complete tag field
\r
962 descriptions and data.
\r
963 *********************************************************/
\r
965 void DumpRunFile(FILE *fh)
\r
968 long i, dret, nPages, nobj;
\r
969 char fDone, filetype, junk;
\r
971 addrIn = 0; /* Default Address */
\r
972 offCode = 0; /* Default virtual code */
\r
976 fprintf(out_fh, "\r\nFile LFA: %ld\r\n", ftell(fh));
\r
977 nobj = fread (&tag, 1, 5, fh);
\r
980 fprintf(out_fh, "Tage Value (hex): %02X\r\n", ii);
\r
981 fprintf(out_fh, "Tage Length (dec): %ld\r\n", tag.len);
\r
987 nobj = fread (&filetype, 1, 1, fh);
\r
989 fprintf(out_fh, "File type: STANDARD RUN FILE\r\n");
\r
990 else if (filetype == 2)
\r
991 fprintf(out_fh, "File type: DYNAMIC LINK LIBRAY\r\n");
\r
992 else if (filetype == 3)
\r
993 fprintf(out_fh, "File type: DEVICE DRIVER\r\n");
\r
995 fprintf(out_fh, "File type: UNKNOWN (ID=%d)\r\n",filetype);
\r
1000 fprintf(out_fh, "Segment Sizes:\r\n");
\r
1001 nobj = fread (&sStack, 1, 4, fh);
\r
1002 if (nobj) nobj = fread (&sCode, 1, 4, fh);
\r
1003 if (nobj) nobj = fread (&sData, 1, 4, fh);
\r
1004 fprintf(out_fh, " Stack %ld\r\n", sStack);
\r
1005 fprintf(out_fh, " Code %ld\r\n", sCode);
\r
1006 fprintf(out_fh, " Data %ld\r\n", sData);
\r
1009 nobj = fread (&offData, 1, 4, fh);
\r
1010 fprintf(out_fh, "Virtual Data Offset: %08lXh\r\n", offData);
\r
1013 nobj = fread (&offCode, 1, 4, fh);
\r
1014 fprintf(out_fh, "Virtual Code Offset: %08lXh\r\n", offCode);
\r
1015 addrIn = offCode; /* Virtual Address */
\r
1018 nobj = fread (&pStart, 1, 4, fh);
\r
1019 fprintf(out_fh, "Start Address: %08lXh\r\n", pStart);
\r
1022 fprintf(out_fh, "Code Segment Contents...\r\n");
\r
1024 while ((disassemble() - offCode) < tag.len);
\r
1028 nobj = fread (&junk, 1, 1, fh);
\r
1031 fprintf(out_fh, "Data Segment Contents...\r\n");
\r
1037 nobj = fread (&junk, 1, 1, fh);
\r
1041 fprintf(out_fh, "CD Fixups - Refs to Data at CSeg offsets:\r\n");
\r
1042 while ((tag.len) && (nobj)) {
\r
1043 nobj = fread (&i, 1, 4, fh);
\r
1045 fprintf(out_fh, " Offset- %08lXh\r\n", i);
\r
1049 fprintf(out_fh, "CC Fixups - Refs to Code at CSeg offsets:\r\n");
\r
1050 while ((tag.len) && (nobj)) {
\r
1051 nobj = fread (&i, 1, 4, fh);
\r
1053 fprintf(out_fh, " Offset- %08lXh\r\n", i);
\r
1057 fprintf(out_fh, "DD Fixups - Refs to Data at DSeg offsets:\r\n");
\r
1058 while ((tag.len) && (nobj)) {
\r
1059 nobj = fread (&i, 1, 4, fh);
\r
1061 fprintf(out_fh, " Offset- %08lXh\r\n", i);
\r
1065 fprintf(out_fh, "DD Fixups - Refs to Code at DSeg offsets:\r\n");
\r
1066 while ((tag.len) && (nobj)) {
\r
1067 nobj = fread (&i, 1, 4, fh);
\r
1069 fprintf(out_fh, " Offset- %08lXh\r\n", i);
\r
1073 nobj = fread (&i, 1, 4, fh);
\r
1074 fprintf(out_fh, "END Tag Value: %ld\r\n", i);
\r
1078 while ((tag.len--) && (nobj))
\r
1079 nobj = fread (&junk, 1, 1, fh);
\r
1085 /***************************
\r
1086 * Main program DUMPRUNFILE
\r
1087 ****************************/
\r
1089 void main(S16 argc, S8 *argv[])
\r
1094 out_fh = 0; /* default the list file */
\r
1096 for(i=1; i < argc; ++i) {
\r
1098 if (*ptr == '/') {
\r
1101 case 'U' : /* UnAssemble Code */
\r
1105 case 'D' : /* Dump Symbols */
\r
1109 case 'O' : /* Output Hex code with Unassembly */
\r
1114 printf("Invalid option/swtich \n");
\r
1123 strncpy(runname, argv[i], 39);
\r
1124 run_fh = fopen(argv[i], "rb");
\r
1126 else if (!out_fh) {
\r
1127 strncpy(outname, argv[i], 39);
\r
1128 if(!(out_fh = fopen(argv[i], "w"))) {
\r
1129 printf("Can't open OUTPUT file\n");
\r
1135 printf("Too many options\n"); /* Too many parameters */
\r
1141 /* Input file not explicitly named errors out */
\r
1144 printf("Usage: DumpRun runfile outputfile /U /D \r\n");
\r
1145 printf("/U = Unassemble Code segment\r\n");
\r
1146 printf("/O = Output code in hex with Unassembly (must use /U)\r\n");
\r
1147 printf("/D = Dump data segment contents in hex format\r\n");
\r
1148 printf("If outputfile isn't specifiled output is sent to screenr\r\n");
\r
1149 printf("Can't open RUNFILE.\n"); /* Can't open file */
\r
1153 /* Output file not explicitly named is set to stdout */
\r
1160 printf("DumpRunFile Ver x1.0 (c) R.A. Burgess 1993, 1994\r\n");
\r
1161 printf("Dump being sent to file: %s \r\n\r\n", outname);
\r
1164 fprintf(out_fh, "DumpRunFile Ver x1.0 (c) R.A. Burgess 1993, 1994\r\n\r\n");
\r
1166 DumpRunFile(run_fh);
\r
1175 /*********************** End of Module *****************/
\r