home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / FSDB091A.ZIP / UNASSMBL.C < prev    next >
C/C++ Source or Header  |  1994-03-01  |  32KB  |  1,228 lines

  1. /* This is file UNASSMBL.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified by Morten Welinder, terra@diku.dk, for use with full screen
  16.    debugger.  These changes are copyright 1994 by Morten Welinder.
  17.  
  18.    Known bugs (fixed = +, not fixed = -):
  19.    - string instructions don't display overriden segment.
  20.    + "aad"/"aam" did't display immediate byte (and therefore got the length
  21.      of the instruction wrong).
  22.    + the tables had an entry at 0x82; that's a bug from Intel's manuals.
  23.    - there are no entries for 486 instructions ("invd", "wbinvd", "xadd",
  24.      "xcmpxchg", "bswap", and "invlpg")
  25.    + "jnc" and "jc" were swapped.  Twice.
  26.    + "setnc" and "setc" were swapped.
  27.    + "setp"/"setnp" should have been "setpe"/"setpo" for consistency.
  28.    */
  29.  
  30. #include <stdio.h>
  31. #include <string.h>
  32.  
  33. #include "ed.h"
  34. #include "unassmbl.h"
  35. #include "syms.h"
  36.  
  37. #define SOURCE_LIST
  38.  
  39. int seg_size=32;
  40.  
  41. static word8 buf[20];
  42. static word32 vaddr;
  43. static int bufp, bufe;
  44. static char ubuf[100], *ubufp;
  45. static col;
  46.  
  47. static ua_str(char *s);
  48.  
  49. /* Percent tokens in strings:
  50.    First char after '%':
  51.         A - direct address
  52.         C - reg of r/m picks control register
  53.         D - reg of r/m picks debug register
  54.         E - r/m picks operand
  55.         F - flags register
  56.         G - reg of r/m picks general register
  57.         I - immediate data (takes extended size, data size)
  58.         J - relative IP offset
  59.         M - r/m picks memory
  60.         O - no r/m, offset only
  61.         R - mod of r/m picks register only
  62.         S - reg of r/m picks segment register
  63.         T - reg of r/m picks test register
  64.         X - DS:ESI
  65.         Y - ES:EDI
  66.         2 - prefix of two-byte opcode
  67.         e - put in 'e' if use32 (second char is part of reg name)
  68.             put in 'w' for use16 or 'd' for use32 (second char is 'w')
  69.         f - floating point (second char is esc value)
  70.         g - do r/m group 'n'
  71.         p - prefix
  72.         s - size override (second char is a,o)
  73.         + - make default signed
  74.    Second char after '%':
  75.         a - two words in memory (BOUND)
  76.         b - byte
  77.         c - byte or word
  78.         d - dword
  79.         p - 32 or 48 bit pointer
  80.         s - six byte pseudo-descriptor
  81.         v - word or dword
  82.         w - word
  83.         F - use floating regs in mod/rm
  84.         + - always sign
  85.         - - sign if negative
  86.         1-8 - group number, esc value, etc
  87. */
  88.  
  89. char *opmap1[] = {
  90. /* 0 */
  91.   "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  92.   "add al,%I-bb", "add %eax,%I-vv", "push es", "pop es",
  93.   "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  94.   "or al,%Ibb", "or %eax,%Ivv", "push cs", "%2 ",
  95. /* 1 */
  96.   "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  97.   "adc al,%I-bb", "adc %eax,%I-vv", "push ss", "pop ss",
  98.   "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  99.   "sbb al,%I-bb", "sbb %eax,%I-vv", "push ds", "pop ds",
  100. /* 2 */
  101.   "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  102.   "and al,%Ibb", "and %eax,%Ivv", "%pe", "daa",
  103.   "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  104.   "sub al,%I-bb", "sub %eax,%I-vv", "%pc", "das",
  105. /* 3 */
  106.   "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  107.   "xor al,%Ibb", "xor %eax,%Ivv", "%ps", "aaa",
  108.   "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  109.   "cmp al,%I-bb", "cmp %eax,%I-vv", "%pd", "aas",
  110. /* 4 */
  111.   "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  112.   "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  113.   "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  114.   "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  115. /* 5 */
  116.   "push %eax", "push %ecx", "push %edx", "push %ebx",
  117.   "push %esp", "push %ebp", "push %esi", "push %edi",
  118.   "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  119.   "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  120. /* 6 */
  121.   "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  122.   "%pf", "%pg", "%so", "%sa",
  123.   "push %I-vv", "imul %Gv=%Ev*%I-vv", "push %I-vb", "imul %Gv=%Ev*%I-vb",
  124.   "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  125. /* 7 */
  126.   "jo %Jb", "jno %Jb", "jc %Jb",  "jnc %Jb",
  127.   "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  128.   "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  129.   "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  130. /* 8 */
  131.   "%g1 %Eb,%Ibb", "%g1 %Ev,%Ivv", 0, "%g1 %Ev,%Ivb",
  132.   "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  133.   "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  134.   "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  135. /* 9 */
  136.   "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  137.   "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  138.   "cbw", "cwd", "call %Ap", "fwait",
  139.   "push %eflags", "pop %eflags", "sahf", "lahf",
  140. /* a */
  141.   "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  142.   "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  143.   "test al,%Ibb", "test %eax,%Ivv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  144.   "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  145. /* b */
  146.   "mov al,%Ibb", "mov cl,%Ibb", "mov dl,%Ibb", "mov bl,%Ibb",
  147.   "mov ah,%Ibb", "mov ch,%Ibb", "mov dh,%Ibb", "mov bh,%Ibb",
  148.   "mov %eax,%I-vv", "mov %ecx,%I-vv", "mov %edx,%I-vv", "mov %ebx,%I-vv",
  149.   "mov %esp,%Ivv", "mov %ebp,%Ivv", "mov %esi,%I-vv", "mov %edi,%I-vv",
  150. /* c */
  151.   "%g2 %Eb,%Ibb", "%g2 %Ev,%Ibb", "ret %Iw", "ret",
  152.   "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ibb", "mov %Ev,%I-vv",
  153.   "enter %Iww,%Ibb", "leave", "retf %Iww", "retf",
  154.   "int 3", "int %Ibb", "into", "iret",
  155. /* d */
  156.   "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  157.   "aam %Ibb", "aad %Ibb", 0, "xlat",
  158.   "%f0", "%f1", "%f2", "%f3",
  159.   "%f4", "%f5", "%f6", "%f7",
  160. /* e */
  161.   "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  162.   "in al,%Ibb", "in %eax,%Ibb", "out %Ibb,al", "out %Ibb,%eax",
  163.   "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  164.   "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  165. /* f */
  166.   "lock %p ", 0, "repne %p ", "rep(e) %p ",
  167.   "hlt", "cmc", "%g3", "%g0",
  168.   "clc", "stc", "cli", "sti",
  169.   "cld", "std", "%g4", "%g5"
  170.   };
  171.  
  172. char *second[] = {
  173. /* 0 */
  174.   "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  175.   0, 0, 0, 0, 0, 0, 0, 0,
  176. /* 1 */
  177.   0, 0, 0, 0, 0, 0, 0, 0,
  178.   0, 0, 0, 0, 0, 0, 0, 0,
  179. /* 2 */
  180.   "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  181.   "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  182.   0, 0, 0, 0, 0, 0, 0, 0,
  183. /* 3 */
  184.   0, 0, 0, 0, 0, 0, 0, 0,
  185.   0, 0, 0, 0, 0, 0, 0, 0,
  186.   0, 0, 0, 0, 0, 0, 0, 0,
  187.   0, 0, 0, 0, 0, 0, 0, 0,
  188.   0, 0, 0, 0, 0, 0, 0, 0,
  189.   0, 0, 0, 0, 0, 0, 0, 0,
  190.   0, 0, 0, 0, 0, 0, 0, 0,
  191.   0, 0, 0, 0, 0, 0, 0, 0,
  192.   0, 0, 0, 0, 0, 0, 0, 0,
  193.   0, 0, 0, 0, 0, 0, 0, 0,
  194. /* 8 */
  195.   "jo %Jv", "jno %Jv", "jc %Jv",  "jnc %Jv",
  196.   "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  197.   "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  198.   "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  199. /* 9 */
  200.   "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb",
  201.   "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  202.   "sets %Eb", "setns %Eb", "setpe %Eb", "setpo %Eb",
  203.   "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  204. /* a */
  205.   "push fs", "pop fs", 0, "bt %Ev,%Gv",
  206.   "shld %Ev,%Gv,%Ibb", "shld %Ev,%Gv,cl", 0, 0,
  207.   "push gs", "pop gs", 0, "bts %Ev,%Gv",
  208.   "shrd %Ev,%Gv,%Ibb", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  209. /* b */
  210.   0, 0, "lss %Mp", "btr %Ev,%Gv",
  211.   "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  212.   0, 0, "%g8 %Ev,%Ibb", "btc %Ev,%Gv",
  213.   "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  214. /* c */
  215.   0, 0, 0, 0, 0, 0, 0, 0,
  216.   0, 0, 0, 0, 0, 0, 0, 0,
  217.   0, 0, 0, 0, 0, 0, 0, 0,
  218.   0, 0, 0, 0, 0, 0, 0, 0,
  219.   0, 0, 0, 0, 0, 0, 0, 0,
  220.   0, 0, 0, 0, 0, 0, 0, 0,
  221.   0, 0, 0, 0, 0, 0, 0, 0,
  222.   0, 0, 0, 0, 0, 0, 0, 0,
  223.   };
  224.  
  225. char *groups[][8] = {     /* group 0 is group 3 for %Ev set */
  226.   { "test %Ev,%Ivv", "test %Ev,%Ivv,", "not %Ev", "neg %Ev",
  227.     "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev" },
  228.   { "add%+-", "or", "adc%+-", "sbb%+-", "and", "sub%+-", "xor", "cmp%+-" },
  229.   { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" },
  230.   { "test %Eb,%Ibb", "test %Eb,%Ibb,", "not %Eb", "neg %Eb",
  231.     "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb" },
  232.   { "inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0 },
  233.   { "inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  234.     "jmp %Ev", "jmp %Ep", "push %Ev", 0 },
  235.   { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  236.     "verr %Ew", "verw %Ew", 0, 0 },
  237.   { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  238.     "smsw %Ew", 0, "lmsw %Ew", 0 },
  239.   { 0, 0, 0, 0, "bt", "bts", "btr", "btc" }
  240.   };
  241.  
  242. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  243. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  244. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  245. char *fop_9[]  = { "*fxch st,%GF" };
  246. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  247. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  248. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  249.                    "fldlg2", "fldln2", "fldz", 0 };
  250. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  251.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  252. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  253.                    "frndint", "fscale", "fsin", "fcos" };
  254. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  255. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  256. char *fop_32[] = { "*fadd %GF,st" };
  257. char *fop_33[] = { "*fmul %GF,st" };
  258. char *fop_36[] = { "*fsubr %GF,st" };
  259. char *fop_37[] = { "*fsub %GF,st" };
  260. char *fop_38[] = { "*fdivr %GF,st" };
  261. char *fop_39[] = { "*fdiv %GF,st" };
  262. char *fop_40[] = { "*ffree %GF" };
  263. char *fop_42[] = { "*fst %GF" };
  264. char *fop_43[] = { "*fstp %GF" };
  265. char *fop_44[] = { "*fucom %GF" };
  266. char *fop_45[] = { "*fucomp %GF" };
  267. char *fop_48[] = { "*faddp %GF,st" };
  268. char *fop_49[] = { "*fmulp %GF,st" };
  269. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  270. char *fop_52[] = { "*fsubrp %GF,st" };
  271. char *fop_53[] = { "*fsubp %GF,st" };
  272. char *fop_54[] = { "*fdivrp %GF,st" };
  273. char *fop_55[] = { "*fdivp %GF,st" };
  274. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  275.  
  276. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  277.   0, 0, 0, 0, 0, 0, 0, 0,
  278.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  279.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  280.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  281.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  282.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  283.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  284.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  285.   };
  286.  
  287. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  288. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  289.        "fsub", "fsubr", "fdiv", "fdivr",
  290. /*08*/ "fld", 0, "fst", "fstp",
  291.        "fldenv", "fldcw", "fstenv", "fstcw",
  292. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  293.        "fisub", "fisubr", "fidiv", "fidivr",
  294. /*24*/ "fild", 0, "fist", "fistp",
  295.        "frstor", "fldt", 0, "fstpt",
  296. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  297.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  298. /*40*/ "fldq", 0, "fstq", "fstpq",
  299.        0, 0, "fsave", "fstsww",
  300. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  301.        "fisubw", "fisubrw", "fidivw", "fidivr",
  302. /*56*/ "fildw", 0, "fistw", "fistpw",
  303.        "fbldt", "fildq", "fbstpt", "fistpq"
  304.   };
  305.  
  306. static word8 getbyte(void)
  307. {
  308.   int s;
  309.   if (bufp >= bufe)
  310.   {
  311.     s = 20;
  312.     if ((vaddr & 0xfff) + s > 0x1000)
  313.       s = 0x1000 - (vaddr & 0xfff);
  314.     read_child(vaddr, buf, s);
  315.     bufe = s;
  316.     bufp = 0;
  317.   }
  318.   vaddr++;
  319. #ifndef FULLSCR
  320.   printf("%02x", buf[bufp]);
  321.   col+=2;
  322. #endif
  323.   return buf[bufp++];
  324. }
  325.  
  326. static int default_pick_sign;
  327.  
  328. static prefix;
  329. static modrmv;
  330. static sibv;
  331. static opsize;
  332. static addrsize;
  333.  
  334. static modrm(void)
  335. {
  336.   if (modrmv == -1)
  337.     modrmv = getbyte();
  338.   return modrmv;
  339. }
  340.  
  341. static sib(void)
  342. {
  343.   if (sibv == -1)
  344.     sibv = getbyte();
  345.   return sibv;
  346. }
  347.  
  348. #define mod(a)  (((a)>>6)&7)
  349. #define reg(a)  (((a)>>3)&7)
  350. #define rm(a)   ((a)&7)
  351. #define ss(a)   (((a)>>6)&7)
  352. #define indx(a) (((a)>>3)&7)
  353. #define base(a) ((a)&7)
  354.  
  355. /*------------------------------------------------------------------------*/
  356. uprintf(char *s, ...)
  357. {
  358.   char **a = &s;
  359.   vsprintf(ubufp, s, a+1);
  360.   while (*ubufp) ubufp++;
  361. }
  362.  
  363. uputchar(char c)
  364. {
  365.   if (c == '\t')
  366.   {
  367.     do {
  368.       *ubufp++ = ' ';
  369.     } while ((ubufp-ubuf) % 8);
  370.   }
  371.   else
  372.     *ubufp++ = c;
  373.   *ubufp = 0;
  374. }
  375.  
  376. /*------------------------------------------------------------------------*/
  377. int bytes(char c)
  378. {
  379.   switch (c)
  380.   {
  381.     case 'b':
  382.       return 1;
  383.     case 'w':
  384.       return 2;
  385.     case 'd':
  386.       return 4;
  387.     case 'v':
  388.       if (opsize == 32)
  389.         return 4;
  390.       else
  391.         return 2;
  392.   }
  393.   return 0;
  394. }
  395.  
  396. /*------------------------------------------------------------------------*/
  397. static ohex(char c, int extend, int optional, int defsize, int sign)
  398. {
  399.   static char *formats[4] = { "%#x", "%d", "%+d", "%+d" };
  400.   char *fmt;
  401.   int n=0, s=0, i, j;
  402.   int32 delta;
  403.   unsigned char buf[6];
  404.   char *name;
  405.   fmt = formats[sign];
  406.  
  407.   switch (c)
  408.   {
  409.     case 'a':
  410.       break;
  411.     case 'b':
  412.       n = 1;
  413.       break;
  414.     case 'w':
  415.       n = 2;
  416.       break;
  417.     case 'd':
  418.       n = 4;
  419.       break;
  420.     case 's':
  421.       n = 6;
  422.       break;
  423.     case 'c':
  424.     case 'v':
  425.       if (defsize == 32)
  426.         n = 4;
  427.       else
  428.         n = 2;
  429.       break;
  430.     case 'p':
  431.       if (defsize == 32)
  432.         n = 6;
  433.       else
  434.         n = 4;
  435.       s = 1;
  436.       break;
  437.     case 'x':
  438.       return;
  439.   }
  440.   for (i=0; i<n; i++)
  441.     buf[i] = getbyte();
  442.   for (; i<extend; i++)
  443.     buf[i] = (buf[i-1] & 0x80) ? 0xff : 0;
  444.   if (s)
  445.   {
  446.     uprintf("0x%02x%02x:", buf[n-1], buf[n-2]);
  447.     n -= 2;
  448.   }
  449.   switch (n)
  450.   {
  451.     case 1:
  452.       delta = *(signed char *)buf;
  453.       break;
  454.    case 2:
  455.       delta = *(signed short *)buf;
  456.       break;
  457.     case 4:
  458.       delta = *(signed long *)buf;
  459.       break;
  460.   }
  461.   if (extend > n)
  462.   {
  463.     if (delta || !optional)
  464.     {
  465.       uprintf(fmt, delta);
  466.     }
  467.     return;
  468.   }
  469.   if ((n == 4) && sign < 2)
  470.   {
  471. #ifdef FULLSCR
  472.     if (delta >= 0 && delta < 0x1000) /* No labels there, only constants.  */
  473.       name = 0;
  474.     else
  475. #endif
  476.     name = syms_val2name(delta, &delta);
  477.     if (name)
  478.     {
  479.       uprintf("%s", name);
  480.       if (delta)
  481.         uprintf("+%lu", delta);
  482.       return;
  483.     }
  484.   }
  485.   switch (n)
  486.   {
  487.     case 1:
  488.       uprintf(fmt, (unsigned char)delta);
  489.       break;
  490.     case 2:
  491.       uprintf(fmt, (unsigned short)delta);
  492.       break;
  493.     case 4:
  494.       uprintf(fmt, (unsigned long)delta);
  495.       break;
  496.   }
  497. }
  498.  
  499. /*------------------------------------------------------------------------*/
  500.  
  501. static char *reg_names[3][8]={
  502.   "al","cl","dl","bl","ah","ch","dh","bh",
  503.   "ax","cx","dx","bx","sp","bp","si","di",
  504.   "eax","ecx","edx","ebx","esp","ebp","esi","edi" };
  505.  
  506. reg_name(int which, char size)
  507. {
  508.   if (size == 'F')
  509.   {
  510.     uprintf("st(%d)", which);
  511.     return;
  512.   }
  513.   if (((size == 'v') && (opsize == 32)) || (size == 'd'))
  514.   {
  515.     uputchar('e');
  516.   }
  517.   if (size == 'b')
  518.   {
  519.     uputchar("acdbacdb"[which]);
  520.     uputchar("llllhhhh"[which]);
  521.   }
  522.   else
  523.   {
  524.     uputchar("acdbsbsd"[which]);
  525.     uputchar("xxxxppii"[which]);
  526.   }
  527. }
  528.  
  529. /*------------------------------------------------------------------------*/
  530. do_sib(m)
  531. {
  532.   static char *i_str[] = {
  533.     "+eax", "+ecx", "+edx", "+ebx", "", "+ebp", "+esi", "+edi" };
  534.   int pick_signed = default_pick_sign;
  535.   int s, i, b, extra=0;
  536.   s = ss(sib());
  537.   i = indx(sib());
  538.   b = base(sib());
  539.   if (b == 5)
  540.   {
  541.       if (m == 0)
  542.       {
  543.         ua_str("%p:[");
  544.         ohex('d', 4, 0, addrsize, 1);
  545.       }
  546.       else
  547.       {
  548.         ua_str("%p:[ebp");
  549.         pick_signed |= 2;
  550.       }
  551.   }
  552.   else
  553.   {
  554.     static char *sib_str[] = {
  555.       "%p:[eax", "%p:[ecx", "%p:[edx", "%p:[ebx", "%p:[esp", 0, "%p:[esi", "%p:[edi" };
  556.     pick_signed |= 2;
  557.     ua_str(sib_str[b]);
  558.     if ((b == i) && (b != 4) && (i != 5))
  559.       extra = 1;
  560.   }
  561.   if (extra == 0)
  562.   {
  563.     pick_signed |= 2;
  564.     uprintf(i_str[i]);
  565.   }
  566.   if (i != 4 && s)
  567.     uprintf("*%d", (1<<s)+extra);
  568.   return pick_signed;
  569. }
  570.  
  571. /*------------------------------------------------------------------------*/
  572.  
  573. static int modrm_extend;
  574.  
  575. do_modrm(char t)
  576. {
  577.   int m = mod(modrm());
  578.   int r = rm(modrm());
  579.   int extend = (addrsize == 32) ? 4 : 2;
  580.   int pick_signed = default_pick_sign;
  581.   if (m == 3)
  582.   {
  583.     reg_name(r, t);
  584.     return;
  585.   }
  586.   if ((m == 0) && (r == 5) && (addrsize == 32))
  587.   {
  588.     ua_str("%p:[");
  589.     ohex('d', extend, 0, addrsize, 0);
  590.     uputchar(']');
  591.     return;
  592.   }
  593.   if ((m == 0) && (r == 6) && (addrsize == 16))
  594.   {
  595.     ua_str("%p:[");
  596.     ohex('w', extend, 0, addrsize, 0);
  597.     uputchar(']');
  598.     return;
  599.   }
  600.   if ((addrsize != 32) || (r != 4))
  601.     ua_str("%p:[");
  602.   if (addrsize == 16)
  603.   {
  604.     static char *r_str[] = {
  605.       "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
  606.     uprintf(r_str[r]);
  607.     pick_signed |= 2;
  608.   }
  609.   else
  610.   {
  611.     if (r == 4)
  612.       pick_signed |= do_sib(m);
  613.     else
  614.     {
  615.       uprintf(reg_names[2][r]);
  616.       pick_signed |= 2;
  617.     }
  618.   }
  619.   modrm_extend = extend;
  620.   ohex("xbv"[m], extend, 1, addrsize, pick_signed);
  621.   uputchar(']');
  622. }
  623.  
  624. /*------------------------------------------------------------------------*/
  625. static floating_point(int e1)
  626. {
  627.   int esc = e1*8 + reg(modrm());
  628.   if (mod(modrm()) == 3)
  629.   {
  630.     if (fspecial[esc])
  631.     {
  632.       if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  633.       {
  634.         ua_str(fspecial[esc][0]+1);
  635.       }
  636.       else
  637.       {
  638.         ua_str(fspecial[esc][rm(modrm())]);
  639.       }
  640.     }
  641.     else
  642.     {
  643.       ua_str(floatops[esc]);
  644.       ua_str(" %EF");
  645.     }
  646.   }
  647.   else
  648.   {
  649.     ua_str(floatops[esc]);
  650.     ua_str(" %EF");
  651.   }
  652. }
  653.  
  654. /*------------------------------------------------------------------------*/
  655. static percent(char c, char **tptr)
  656. {
  657.   word32 vofs, v, delta;
  658.   char *name;
  659.   int default_signed = default_pick_sign;
  660.   char t = *(*tptr)++, it;
  661.   int extend = (addrsize == 32) ? 4 : 2;
  662.   int iextend;
  663.  
  664.   if (c != '+')
  665.   {
  666.     if (t == '-')
  667.     {
  668.       default_signed = 1;
  669.       t = *(*tptr)++;
  670.     }
  671.     else if (t == '+')
  672.     {
  673.       default_signed = 2;
  674.       t = *(*tptr)++;
  675.     }
  676.   }
  677.   switch (c)
  678.   {
  679.     case 'A':
  680.       ohex(t, extend, 0, addrsize, 0);
  681.       break;
  682.     case 'C':
  683.       uprintf("cr%d", reg(modrm()));
  684.       break;
  685.     case 'D':
  686.       uprintf("dr%d", reg(modrm()));
  687.       break;
  688.     case 'E':
  689.       do_modrm(t);
  690.       break;
  691.     case 'G':
  692.       if (t == 'F')
  693.         reg_name(rm(modrm()), t);
  694.       else
  695.         reg_name(reg(modrm()), t);
  696.       break;
  697.     case 'I':
  698.       it = *(*tptr)++;
  699.       switch (t)
  700.       {
  701.         case 'b':
  702.           iextend = 1;
  703.           break;
  704.         case 'v':
  705.           iextend = extend;
  706.           break;
  707.         default:
  708.           iextend = 0;
  709.           break;
  710.       }
  711.       ohex(it, iextend, 0, opsize, default_signed);
  712.       break;
  713.     case 'J':
  714.       switch (bytes(t))
  715.       {
  716.         case 1:
  717.           vofs = (int8)getbyte();
  718.           break;
  719.         case 2:
  720.           vofs = getbyte();
  721.           vofs += getbyte()<<8;
  722.           vofs = (int16)vofs;
  723.           break;
  724.         case 4:
  725.           vofs = (word32)getbyte();
  726.           vofs |= (word32)getbyte() << 8;
  727.           vofs |= (word32)getbyte() << 16;
  728.           vofs |= (word32)getbyte() << 24;
  729.           break;
  730.       }
  731.       name = syms_val2name(vofs+vaddr, &delta);
  732.       uprintf("%s", name);
  733.       if (delta)
  734.         uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
  735.                 (vofs & 0x80000000L) ? 0x1e : 0x1f);
  736.       break;
  737.     case 'M':
  738.       do_modrm(t);
  739.       break;
  740.     case 'O':
  741.       ua_str("%p:[");
  742.       ohex(t, extend, 0, addrsize, 0);
  743.       uputchar(']');
  744.       break;
  745.     case 'R':
  746.       do_modrm(t);
  747.       break;
  748.     case 'S':
  749.       uputchar("ecsdfg"[reg(modrm())]);
  750.       uputchar('s');
  751.       break;
  752.     case 'T':
  753.       uprintf("tr%d", reg(modrm()));
  754.       break;
  755.     case 'X':
  756.       uprintf("ds:[");
  757.       if (addrsize == 32)
  758.         uputchar('e');
  759.       uprintf("si]");
  760.       break;
  761.     case 'Y':
  762.       uprintf("es:[");
  763.       if (addrsize == 32)
  764.         uputchar('e');
  765.       uprintf("di]");
  766.       break;
  767.     case '2':
  768.       ua_str(second[getbyte()]);
  769.       break;
  770.     case 'e':
  771.       if (opsize == 32)
  772.       {
  773.         if (t == 'w')
  774.           uputchar('d');
  775.         else
  776.         {
  777.           uputchar('e');
  778.           uputchar(t);
  779.         }
  780.       }
  781.       else
  782.         uputchar(t);
  783.       break;
  784.     case 'f':
  785.       floating_point(t-'0');
  786.       break;
  787.     case 'g':
  788.       ua_str(groups[t-'0'][reg(modrm())]);
  789.       break;
  790.     case 'p':
  791.       switch (t)
  792.       {
  793.         case 'c':
  794.         case 'd':
  795.         case 'e':
  796.         case 'f':
  797.         case 'g':
  798.         case 's':
  799.           prefix = t;
  800.           ua_str(opmap1[getbyte()]);
  801.           break;
  802.         case ':':
  803.           if (prefix)
  804.             uprintf("%cs:", prefix);
  805.           break;
  806.         case ' ':
  807.           ua_str(opmap1[getbyte()]);
  808.           break;
  809.       }
  810.       break;
  811.     case 's':
  812.       switch (t)
  813.       {
  814.         case 'a':
  815.           addrsize = 48 - addrsize;
  816.           ua_str(opmap1[getbyte()]);
  817.           break;
  818.         case 'o':
  819.           opsize = 48 - opsize;
  820.           ua_str(opmap1[getbyte()]);
  821.           break;
  822.       }
  823.       break;
  824.     case '+':
  825.       switch (t)
  826.       {
  827.         case '-':
  828.           default_pick_sign = 1;
  829.           break;
  830.         case '+':
  831.           default_pick_sign = 2;
  832.           break;
  833.         default:
  834.           default_pick_sign = 0;
  835.           break;
  836.       }
  837.   }
  838. }
  839.  
  840. static ua_str(char *s)
  841. {
  842.   int c;
  843.   if (s == 0)
  844.   {
  845.     uprintf("<invalid>");
  846.     return;
  847.   }
  848.   while ((c = *s++) != 0)
  849.   {
  850.     if (c == '%')
  851.     {
  852.       c = *s++;
  853.       percent(c, &s);
  854.     }
  855.     else
  856.       if (c == ' ')
  857.         uputchar('\t');
  858.       else
  859.         uputchar(c);
  860.   }
  861. }
  862.  
  863. #ifdef SOURCE_LIST
  864. /*
  865. ** A little brute force hacking and hey presto! A source debugger!
  866. ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  867. **
  868. ** KNOWN BUGS:
  869. ** The program will summarily terminate if you run out
  870. ** of memory while you're looking for all the line offsets.  Since
  871. ** a two thousand line source file only creats an 8K array, and the
  872. ** symbol table goes into virtual memory, this shouldn't happen too
  873. ** often.
  874. **
  875. ** One file is left open for reading indefinitely.
  876. */
  877. #include <stdlib.h>
  878. #include <string.h>
  879. /*
  880. ** keep the source line offsets in virtual memory, so you can
  881. ** debug big programs
  882. */
  883. extern word32 salloc(word32 size);
  884. #define symsput(where,ptr,size)     memput(where,ptr,size)
  885. #define symsget(where,ptr,size)     memget(where,ptr,size)
  886.  
  887. /*
  888. ** for each file encountered, keep an array of line start offsets
  889. ** so you can seek into the file to display the current line.
  890. */
  891. typedef struct {
  892.         char *filename;
  893.         long *offsets;
  894. } line_info;
  895.  
  896. static line_info *files;
  897. static last_file = 0;
  898.  
  899. /*
  900. ** add_file -- add a file to the source line database
  901. */
  902. static int
  903. add_file(char *name) {
  904.         FILE *f = fopen(name,"rb");
  905.         char c;
  906.         long *lines,curpos;
  907.         unsigned curline = 0;
  908.  
  909.         if(!f)
  910.                 return -1;
  911.  
  912.         if (files == 0)
  913.           files = (line_info *)malloc(sizeof(line_info));
  914.         else
  915.           files = realloc(files, (last_file+1) * sizeof(line_info));
  916.  
  917.         files[last_file].filename = strdup(name);
  918.  
  919.         /*
  920.         ** build an array of line offsets in real memory.
  921.         */
  922.         lines = malloc(sizeof(long));
  923.         lines[curline++] = curpos = 0L;
  924.  
  925.         while((c = getc(f)) != EOF) {
  926.                 curpos++;
  927.                 if(c == '\n') {
  928.                         lines = realloc(lines,sizeof(long)*(curline+1));
  929.                         lines[curline++] = curpos;
  930.                 }
  931.         }
  932.         /*
  933.         ** now move the whole array into virtual memory
  934.         */
  935.         files[last_file].offsets = lines;
  936.         fclose(f);
  937.  
  938.         last_file++;
  939.         return 0;
  940. }
  941.  
  942. static line_info *
  943. find_file(char *name) {
  944.         int i;
  945.         for(i = 0; i < last_file; i++)
  946.                 if(strcmp(name,files[i].filename) == 0)
  947.                         return &files[i];
  948.         if(add_file(name) == -1)
  949.                         return NULL;
  950.         return find_file(name);
  951. }
  952.  
  953. /*
  954. ** myfopen -- cache the most recently accessed source file
  955. ** so you aren't constantly reopening a new file
  956. */
  957. static FILE *
  958. myfopen(char *name) {
  959.         static char fname[80] = "";
  960.         static FILE *current = NULL;
  961.         if(current != NULL && strcmp(fname,name) == 0)
  962.                         return current;
  963.         if(current != NULL) fclose(current);
  964.         strcpy(fname,name);
  965.         return (current = fopen(name,"rb"));
  966. }
  967.  
  968. /*
  969. ** put_source_line -- print the current source line, along with
  970. ** the line # and file name, if necessary.
  971. */
  972. #ifdef FULLSCR
  973. void put_source_line(int fmt, char *name, int line, char *result)
  974. #else
  975. void put_source_line(int fmt,char *name,int line)
  976. #endif
  977. {
  978.         line_info *current = find_file(name);
  979.         FILE *cur;
  980. #ifdef FULLSCR
  981.     /* See below */
  982.     char *sbuf, *chp;
  983. #endif
  984.         if(current == NULL) {
  985.         regular:
  986. #ifdef FULLSCR
  987.       sbuf = alloca (100);
  988.           if (fmt == 0)
  989.         sprintf (sbuf, " (%s#%d):", name, line);
  990.           else
  991.         sprintf (sbuf, "#%d:", line);
  992.       strcat (result, sbuf);
  993. #else
  994.           if(fmt == 0)
  995.                   printf(" (%s#%d):\n", name, line);
  996.           else
  997.                   printf("#%d:\n", line);
  998. #endif
  999.         } else {
  1000. #ifdef FULLSCR
  1001.             /* I really hate set a maximum like this, but setting it
  1002.            this high will hopefully not feel like a maximum.  */
  1003.                 char buf[1000];
  1004. #else
  1005.                 char buf[70];
  1006. #endif
  1007.                 long offset;
  1008.                 if((cur = myfopen(name)) == NULL)
  1009.                         goto regular;
  1010.                 /*
  1011.                 ** get the symbol out of virtual memory
  1012.                 */
  1013.                 offset = current->offsets[line-1];
  1014.                 fseek(cur,offset,0);
  1015.                 /*
  1016.                 ** truncate line so it fits on screen.
  1017.                 */
  1018.                 fgets(buf,sizeof(buf)-2,cur);
  1019. #ifdef FULLSCR
  1020.                 if (chp = strchr (buf, '\n'))
  1021.           if (chp != buf && chp[-1] == '\r')
  1022.             chp [-1] = '\0';
  1023.           else
  1024.             *chp = '\0';
  1025.         sbuf = alloca (sizeof (buf) + 100);
  1026.         if (fmt == 0)
  1027.           sprintf (sbuf, " (%s#%d): %s", name, line, buf);
  1028.         else
  1029.           sprintf (sbuf, "#%d: %s", line, buf);
  1030.         strcat (result, sbuf);
  1031. #else
  1032.                 if(strchr(buf,'\n') == NULL)
  1033.                         strcat(buf,"\n");
  1034.                 if(fmt == 0)
  1035.                         printf(" (%s#%d): %s", name, line,buf);
  1036.                 else
  1037.                         printf("#%d: %s",line,buf);
  1038. #endif
  1039.         }
  1040. }
  1041.  
  1042. #endif
  1043.  
  1044. int last_unassemble_unconditional;
  1045. int last_unassemble_jump;
  1046. int last_unassemble_extra_lines;
  1047. /* Please read the above regarding this max.  */
  1048. char last_unassemble_text[1100];
  1049.  
  1050. char *
  1051. unassemble_proper (word32 v, int *len)
  1052. {
  1053.   prefix = 0;
  1054.   modrmv = sibv = -1;
  1055.   opsize = addrsize = seg_size;
  1056.   vaddr = v;
  1057.   bufp = bufe = 0;
  1058.   col = 0;
  1059.   ubufp = ubuf;
  1060.   ua_str(opmap1[getbyte()]);
  1061.   
  1062.   *len = vaddr - v;
  1063.   return ubuf;
  1064. }
  1065.  
  1066. char *
  1067. unassemble_source (word32 v)
  1068. {
  1069.   word32 delta;
  1070.   char *name, *lname, *result = last_unassemble_text;
  1071.   int linenum;
  1072.  
  1073.   result[0] = '\0';
  1074.  
  1075.   name = syms_val2name (v, &delta);
  1076.   if (!delta && (name[0] != '0'))
  1077.     {
  1078.       strcat (strcat (result, name), "()");
  1079.       lname = syms_val2line (v, &linenum, 1);
  1080.       if (lname)
  1081.     put_source_line (0, lname, linenum, result);
  1082.       else
  1083.     strcat (result, ":");
  1084.     }
  1085.   else
  1086.     {
  1087.       lname = syms_val2line (v, &linenum, 1);
  1088.       if (lname)
  1089.     put_source_line (1, lname, linenum, result);
  1090.       else
  1091.     return NULL;
  1092.     }
  1093.   return result;
  1094. }
  1095.  
  1096. #ifndef FULLSCR
  1097. word32 unassemble(word32 v, int showregs)
  1098. {
  1099.   int a,b,n,wi, linenum;
  1100.   char *cmp, *brp;
  1101.   word8 *wp;
  1102.   word32 delta;
  1103.   char *name, *lname;
  1104.   char *regpos;
  1105.  
  1106.   default_pick_sign = 0;
  1107.   ansi(A_yellow);
  1108.   last_unassemble_unconditional = 0;
  1109.   last_unassemble_jump = 0;
  1110.   last_unassemble_extra_lines = 0;
  1111.   name = syms_val2name(v, &delta);
  1112.   if (!delta && (name[0] != '0'))
  1113.   {
  1114.     printf("%s()", name);
  1115.     lname = syms_val2line(v, &linenum, 1);
  1116.     if (lname)
  1117. #ifndef SOURCE_LIST
  1118.       printf(" (%s#%d):\n", lname, linenum);
  1119. #else
  1120.       put_source_line(0,lname,linenum);
  1121. #endif
  1122.     else
  1123.       printf(":\n");
  1124.     last_unassemble_extra_lines++;
  1125.   }
  1126.   else
  1127.   {
  1128.     lname = syms_val2line(v, &linenum, 1);
  1129.     if (lname)
  1130.     {
  1131. #ifndef SOURCE_LIST
  1132.       printf("#%d:\n", linenum);
  1133. #else
  1134.       put_source_line(1,lname,linenum);
  1135. #endif
  1136.       last_unassemble_extra_lines++;
  1137.     }
  1138.   }
  1139.  
  1140.   ansi(A_grey);
  1141.   printf("%08lx: ", v);
  1142. #if 0
  1143.   if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
  1144.   {
  1145.     printf("<bad address>\n");
  1146.     return v;
  1147.   }
  1148. #endif
  1149.  
  1150.   prefix = 0;
  1151.   modrmv = sibv = -1;
  1152.   opsize = addrsize = seg_size;
  1153.   vaddr = v;
  1154.   bufp = bufe = 0;
  1155.   col = 0;
  1156.   ubufp = ubuf;
  1157.   ua_str(opmap1[getbyte()]);
  1158.   do {
  1159.     putchar(' ');
  1160.     col++;
  1161.   } while (col < 15);
  1162.   col += strlen(ubuf);
  1163.   do {
  1164.     uputchar(' ');
  1165.     col++;
  1166.   } while (col < 43);
  1167.  
  1168.   ansi(A_cyan);
  1169.   printf("%s", ubuf);
  1170.   ansi(A_grey);
  1171.  
  1172.   if ((strncmp(ubuf, "jmp ", 4) == 0)
  1173.      || (strncmp(ubuf, "ret", 3) == 0))
  1174.     last_unassemble_unconditional = 1;
  1175.   if (ubuf[0] == 'j')
  1176.     last_unassemble_jump = 1;
  1177.  
  1178.   if (!showregs)
  1179.   {
  1180.     putchar('\n');
  1181.     return vaddr;
  1182.   }
  1183.  
  1184.   col -= 43; /* total 25 columns left */
  1185.   wp = (word8 *)&(a_tss.tss_eax);
  1186.   cmp = strchr(ubuf+8, ',');
  1187.   brp = strchr(ubuf+8, '[');
  1188.   if (!cmp) cmp = ubuf+8;
  1189.   if (!brp) brp = ubufp;
  1190.   if (brp < cmp) cmp = brp;
  1191.   if (strncmp(ubuf, "mov ", 4))
  1192.     cmp = ubuf+8;
  1193.   for (b=0; b<8; b++)
  1194.   {
  1195.     for (a=2; a>=0; a--)
  1196.     {
  1197.       n = (a==0) ? 1 : ((a==1) ? 2 : 4);
  1198.       if (regpos = strstr(cmp, reg_names[a][b]))
  1199.       {
  1200.     if (!isalnum (regpos[-1]) && (regpos[-1] != '_'))
  1201.     {
  1202.       col += strlen(reg_names[a][b])+n*2+2;
  1203.       if (col > 29)
  1204.       {
  1205.         printf("\n%53s", "");
  1206.         col = 0;
  1207.       }
  1208.       printf("%s=", reg_names[a][b]);
  1209.       if (a == 0)
  1210.         wi = (b&3)*4 + (b>>2);
  1211.       else
  1212.         wi = b*4;
  1213.       while (n)
  1214.       {
  1215.         n--;
  1216.         printf("%02x", wp[wi+n]);
  1217.       }
  1218.       putchar(' ');
  1219.       break;
  1220.     }
  1221.       }
  1222.     }
  1223.   }
  1224.   putchar('\n');
  1225.   return vaddr;
  1226. }
  1227. #endif /* FULLSCR */
  1228.