home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / debug / fsdb / unassmbl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-12  |  31.5 KB  |  1,298 lines

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