home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2431 / disasm.c < prev    next >
C/C++ Source or Header  |  1991-01-01  |  31KB  |  1,527 lines

  1. /*
  2.  * Xenix disassembly program by P.Garbha (pgd@compuram.bbt.se)
  3.  *
  4.  * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
  5.  * July 1988
  6.  * Copyright (C) 1988 Free Software Foundation, Inc.
  7.  */
  8.  
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <a.out.h>
  13. #include <sys/relsym.h>
  14. #include <string.h>
  15.  
  16. #include "386opcodes.h"
  17.  
  18. #define    MAXSEG    20
  19. #define    THRESHOLD    0x100
  20.  
  21. static int prefixes;
  22.  
  23. static char obuf[100];
  24. static char *obufp;
  25. static char scratchbuf[1000];
  26. static unsigned char *start_codep;
  27. static unsigned char *codep;
  28. static int mod;
  29. static int rm;
  30. static int reg;
  31.  
  32. struct xexec xoutx;
  33. struct xext xoutxe;
  34. struct xseg xoutxs[MAXSEG];
  35. struct {
  36.     short signature;
  37.     short lengthb;        /* length of file, lsb */
  38.     short lengthp;        /* length of file in 512-byte pages */
  39.     short relitems;        /* number of relocation table items */
  40.     short hdrsize;        /* size of header in 16-byte paragraphs */
  41.     short maxparas1;        
  42.     short maxparas2;
  43.     short stackoff;        /* Offset of stack segment in load module */
  44.     short initsp;        /* Initial sp */
  45.     short checksum;        /* Word checksum */
  46.     short initip;        /* Initial ip */
  47.     short csoff;        /* Offset of code segment */
  48.     short reloff;        /* Offset of the first relocation item */
  49.     short ovlno;        /* Overlay number */
  50. } exehdr;
  51.  
  52. int segcount = 0;
  53. struct xseg *textsegp = 0, *datasegp = 0, *symsegp = 0;
  54. int textseg = -1, dataseg = -1;
  55. unsigned char *textp, *datap, *xtextp;
  56.  
  57. int textsize, datasize, database;
  58.  
  59. struct symtab {
  60.     char    *symstring;
  61.     unsigned int symval;
  62.     short    symrefcount;
  63.     short    symflags;
  64. };
  65.  
  66. #define    TEXTSEG        0000001
  67. #define    DATASEG        0000002
  68. #define    GENERATED    0000004
  69. #define    BYTEREF        0000010
  70. #define    WORDREF        0000020
  71. #define    DWORDREF    0000040
  72. #define    JUMPREF        0000100
  73. #define    CALLREF        0000200
  74. #define    DEFINED        0000400
  75. #define    PUSHLIMMED    0001000
  76. #define    ASCIZ        0002000
  77. #define    ADDRREF        0004000
  78.  
  79. #define    NOENTER        0100000
  80.  
  81. struct symtab *lookup(), *enter();
  82. char *symname(), *getimmed(), *datasymbol(), *ascizdata();
  83.  
  84. #define    SYMHS    20033
  85. struct symtab *symhash[SYMHS];
  86. int symcount = 0;
  87.  
  88. int pass2 = 0;
  89.  
  90. init()
  91. {
  92.     register int i;
  93.  
  94.     for (i = 0; i < SYMHS; i++) {
  95.         symhash[i] = NULL;
  96.     }
  97. }
  98.  
  99. main(argc, argv)
  100.     char **argv;
  101. {
  102.     init();
  103.     if (argc < 2) fatal("No input file");
  104.     loadaout(argv[1]);
  105.     dopass1();
  106.     symtabpass();
  107.     dopass2();
  108.     dodata();
  109.     exit(0);
  110. }
  111.  
  112. dopass1()
  113. {
  114.     int ipc;
  115.     char buf[200];
  116.     int len;
  117.  
  118.     ipc = 0;
  119.     while (ipc < textsize) {
  120.         len = i386dis(ipc, textp+ipc, buf);
  121.         ipc += len;
  122.     }
  123. }
  124.  
  125. dopass2()
  126. {
  127.     int ipc;
  128.     int oipc = 0;
  129.     char buf[200];
  130.     int len;
  131.     register struct symtab *lbp;
  132.     int i, mode;
  133.     int unreachable = 0, firsttime = 0;
  134.  
  135.     pass2 = 1;
  136.     ipc = 0;
  137.     while (ipc < textsize) {
  138.         if (textp != xtextp) abort();
  139.         lbp = lookup(ipc, TEXTSEG);
  140.         if (lbp && lbp->symrefcount == 1 && lbp->symflags & (WORDREF|DWORDREF) && !(lbp->symflags & (CALLREF|JUMPREF))) {
  141.             mode = lbp->symflags;
  142.             printf("%s:\t\t; %0x (%d)\n", symname(lbp), ipc, lbp->symrefcount);
  143.             for (;;) {
  144.                 register unsigned int addr;
  145.                 register struct symtab *symp;
  146.                 codep = textp+ipc;
  147.                 addr = *(unsigned int *)codep;
  148.                 symp = lookup(addr, TEXTSEG|JUMPREF);
  149.                 if (symp)
  150.                     printf("\t.dword\t%s\n", symname(symp));
  151.                 else
  152.                     printf("\t.dword\t%#x\n", addr);
  153.                 len = 4;
  154.                 ++ipc;
  155.                 for (i = 1; i < len; i++) {
  156.                     if (lbp = lookup(ipc, TEXTSEG)) {
  157.                         /*
  158.                          * This is a hack, just to
  159.                          * void breaking a jump table
  160.                          * by a garbage label.
  161.                          * We assume no code segment
  162.                          * starts with the 0 opcode
  163.                          */
  164.                         if (textp[ipc] < 0xf) {
  165.                             ipc++;
  166.                             continue;
  167.                         }
  168.                         printf("Code overlapping, backing up\n");
  169.                         oipc = ipc + len;
  170.                         break;
  171.                     }
  172.                     ipc++;
  173.                 }
  174.                 if (i < len || i == len && lookup(ipc, TEXTSEG))
  175.                     break;
  176.             }
  177.         } else {
  178.             register int opcode;
  179.  
  180.             opcode = *(textp+ipc);
  181.             if (lbp) {
  182.                 printf("%s:\t\t; %0x (%d)\n", symname(lbp), ipc, lbp->symrefcount);
  183.                 unreachable = 0;
  184.             }
  185.             if (unreachable && opcode == 0) {
  186.                 printf("\t.byte\t0\t\t; unreachable");
  187.                 len = 1;
  188.             } else if (unreachable && opcode == 0x90) {
  189.                 printf("\tnop\t\t\t; unreachable");
  190.                 len = 1;
  191.             } else {
  192.                 if (unreachable && firsttime) {
  193.                     printf("Warning: Unreachable code\n");
  194.                     firsttime = 0;
  195.                 }
  196.                 len = i386dis(ipc, textp+ipc, buf);
  197.                 putchar('\t');
  198.                 fputs(buf, stdout);
  199.             }
  200.             /*
  201.              * Check for moving into unreachable code
  202.              */
  203.             if (opcode==0xeb||opcode==0xe9||opcode==0xc3||opcode==0xc2||opcode==0xa||opcode==0xcb) {
  204.                 unreachable = firsttime = 1;
  205.             }
  206.             /*        printf("\t\t; %#x", *start_codep); */
  207.             putchar('\n');
  208.             ++ipc;
  209.             for (i = 1; i < len; i++) {
  210.                 register struct symtab *symp;
  211.                 if (symp = lookup(ipc, TEXTSEG)) {
  212.                     if (unreachable) {
  213.                         printf("Code overlapping, backing up\n");
  214.                         break;
  215.                     }
  216.                     printf("Warning: Hidden label: %s\n", symname(symp));
  217.                 }
  218.                 ipc++;
  219.             }
  220.         }
  221.     }
  222. }
  223.  
  224. /*
  225.  * Print out data area
  226.  */
  227. dodata()
  228. {
  229.     int dpc;
  230.     register struct symtab *lbp;
  231.     register int c;
  232.  
  233.     dpc = 0;
  234.     while (dpc < datasize) {
  235.         lbp = lookup(dpc+database, DATASEG);
  236.         while (lbp && (lbp->symflags & ASCIZ)) {
  237.             for (;;) {
  238.                 dpc++;
  239.                 if (dpc >= datasize)
  240.                     return;
  241.                 if (lbp = lookup(dpc+database, DATASEG))
  242.                     break;
  243.             }
  244.         }
  245.         if (lbp) {
  246.             printf("%s:\t\t; %0x (%d)", symname(lbp), dpc+database, lbp->symrefcount);
  247.             if (lbp->symflags & BYTEREF) printf(" BYTE ");
  248.             if (lbp->symflags & WORDREF) printf(" WORD ");
  249.             if (lbp->symflags & DWORDREF) printf(" DWORD ");
  250.             if (lbp->symflags & ASCIZ) printf(" ASCIZ ");
  251.             if (lbp->symflags & ADDRREF) printf(" ADDR ");
  252.             putchar('\n');
  253.         }
  254.         if (!pass2) {
  255.             dpc++;
  256.             continue;
  257.         }
  258.             
  259.         switch (lbp ? lbp->symflags & (BYTEREF|WORDREF|DWORDREF|ADDRREF) : BYTEREF) {
  260.         case BYTEREF:
  261.         default:
  262.         deflt:
  263.             c = datap[dpc];
  264.             printf("\t.byte\t%#x\t;", c);
  265.             if (c>=' ' && c < 127)
  266.                 printf("'%c'", c);
  267.             else
  268.                 printf("   ");
  269.             printf(" %#x\n", dpc /*+database */);
  270.             dpc++;
  271.             break;
  272.  
  273.         case WORDREF:
  274.             if (dpc+1 < datasize
  275.                 && !lookup(dpc+database+1, DATASEG)) {
  276.                 printf("\t.word\t%#x\t; %d\t%#x\n",
  277.                        *((unsigned short *)(datap+dpc)), dpc);
  278.                 dpc += 2;
  279.                 break;
  280.             }
  281.             goto deflt;
  282.  
  283.         case DWORDREF:
  284.             if (dpc+3 < datasize
  285.                 && !lookup(dpc+database+1, DATASEG)
  286.                 && !lookup(dpc+database+2, DATASEG)
  287.                 && !lookup(dpc+database+3, DATASEG)) {
  288.                 printf("\t.dword\t%#x\t; %d\t%#x\n",
  289.                        *((unsigned long *)(datap+dpc)), dpc);
  290.                 dpc += 4;
  291.                 break;
  292.             }
  293.             goto deflt;
  294.         }
  295.     }
  296.                        
  297. }
  298.  
  299. ckprefix ()
  300. {
  301.     prefixes = 0;
  302.     while (1) {
  303.         switch (*codep) {
  304.         case 0xf3:
  305.             prefixes |= PREFIX_REPZ;
  306.             break;
  307.         case 0xf2:
  308.             prefixes |= PREFIX_REPNZ;
  309.             break;
  310.         case 0xf0:
  311.             prefixes |= PREFIX_LOCK;
  312.             break;
  313.         case 0x2e:
  314.             prefixes |= PREFIX_CS;
  315.             break;
  316.         case 0x36:
  317.             prefixes |= PREFIX_SS;
  318.             break;
  319.         case 0x3e:
  320.             prefixes |= PREFIX_DS;
  321.             break;
  322.         case 0x26:
  323.             prefixes |= PREFIX_ES;
  324.             break;
  325.         case 0x64:
  326.             prefixes |= PREFIX_FS;
  327.             break;
  328.         case 0x65:
  329.             prefixes |= PREFIX_GS;
  330.             break;
  331.         case 0x66:
  332.             prefixes |= PREFIX_DATA;
  333.             break;
  334.         case 0x67:
  335.             prefixes |= PREFIX_ADR;
  336.             break;
  337.         case 0x9b:
  338.             prefixes |= PREFIX_FWAIT;
  339.             break;
  340.         default:
  341.             return;
  342.         }
  343.         codep++;
  344.     }
  345. }
  346.  
  347. static int dflag;
  348. static int aflag;
  349. static int Sflag;
  350.  
  351. static char op1out[100], op2out[100], op3out[100];
  352. static int start_pc;
  353.  
  354. /*
  355.  * disassemble the first instruction in 'inbuf'.  You have to make
  356.  *   sure all of the bytes of the instruction are filled in.
  357.  *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
  358.  *   (see topic "Redundant prefixes" in the "Differences from 8086"
  359.  *   section of the "Virtual 8086 Mode" chapter.)
  360.  * 'pc' should be the address of this instruction, it will
  361.  *   be used to print the target address if this is a relative jump or call
  362.  * 'outbuf' gets filled in with the disassembled instruction.  it should
  363.  *   be long enough to hold the longest disassembled instruction.
  364.  *   100 bytes is certainly enough, unless symbol printing is added later
  365.  * The function returns the length of this instruction in bytes.
  366.  */
  367. i386dis (pc, inbuf, outbuf)
  368.     int pc;
  369.     unsigned char *inbuf;
  370.     char *outbuf;
  371. {
  372.     struct dis386 *dp;
  373.     char *p;
  374.     int i;
  375.     int enter_instruction;
  376.     char *first, *second, *third;
  377.     int needcomma;
  378.     
  379.     obuf[0] = 0;
  380.     op1out[0] = 0;
  381.     op2out[0] = 0;
  382.     op3out[0] = 0;
  383.     
  384.     start_pc = pc;
  385.     start_codep = inbuf;
  386.     codep = inbuf;
  387.     
  388.     ckprefix ();
  389.     
  390.     if (*codep == 0xc8)
  391.         enter_instruction = 1;
  392.     else
  393.         enter_instruction = 0;
  394.     
  395.     obufp = obuf;
  396.     
  397.     if (prefixes & PREFIX_REPZ)
  398.         oappend ("repz ");
  399.     if (prefixes & PREFIX_REPNZ)
  400.         oappend ("repnz ");
  401.     if (prefixes & PREFIX_LOCK)
  402.         oappend ("lock ");
  403.     
  404.     if ((prefixes & PREFIX_FWAIT) && ((*codep < 0xd8) || (*codep > 0xdf))) {
  405.         /* fwait not followed by floating point instruction */
  406.         oappend ("fwait");
  407.         strcpy (outbuf, obuf);
  408.         return (1);
  409.     }
  410.  
  411.     /* these would be initialized to 0 if disassembling for 8086 or 286 */
  412.     dflag = aflag = Sflag = 0;
  413.     if ((xoutx.x_cpu & XC_CPU) == XC_386) {
  414.         dflag = aflag = 1;
  415.     }
  416.  
  417.     if (prefixes & PREFIX_DATA)
  418.         dflag ^= 1;
  419.  
  420.     if (prefixes & PREFIX_ADR) {
  421.         aflag ^= 1;
  422.         oappend ("addr16 ");
  423.     }
  424.  
  425.     if (*codep == 0x0f)
  426.         dp = &dis386_twobyte[*++codep];
  427.     else
  428.         dp = &dis386[*codep];
  429.     codep++;
  430.     mod = (*codep >> 6) & 3;
  431.     reg = (*codep >> 3) & 7;
  432.     rm = *codep & 7;
  433.  
  434.     if (dp->name == NULL && dp->bytemode1 == FLOATCODE) {
  435.         dofloat ();
  436.     } else {
  437.         if (dp->name == NULL)
  438.             dp = &grps[dp->bytemode1][reg];
  439.  
  440.         putop (dp->name);
  441.  
  442.         obufp = op1out;
  443.         if (dp->op1)
  444.             (*dp->op1)(dp->bytemode1);
  445.         
  446.         obufp = op2out;
  447.         if (dp->op2)
  448.             (*dp->op2)(dp->bytemode2);
  449.         
  450.         obufp = op3out;
  451.         if (dp->op3)
  452.             (*dp->op3)(dp->bytemode3);
  453.     }
  454.  
  455.     obufp = obuf + strlen (obuf);
  456. /*    for (i = strlen (obuf); i < 6; i++)
  457.         oappend (" ");
  458.     oappend (" "); */
  459.     oappend ("\t");
  460.  
  461.     /* enter instruction is printed with operands in the
  462.      * same order as the intel book; everything else
  463.      * is printed in reverse order 
  464.      */
  465.     if (enter_instruction) {
  466.         first = op1out;
  467.         second = op2out;
  468.         third = op3out;
  469.     } else {
  470.         first = op3out;
  471.         second = op2out;
  472.         third = op1out;
  473.     }
  474.     needcomma = 0;
  475.     if (*first) {
  476.         oappend (first);
  477.         needcomma = 1;
  478.     }
  479.     if (*second) {
  480.         if (needcomma)
  481.             oappend (",");
  482.         oappend (second);
  483.         needcomma = 1;
  484.     }
  485.     if (*third) {
  486.         if (needcomma)
  487.             oappend (",");
  488.         oappend (third);
  489.     }
  490.     strcpy (outbuf, obuf);
  491.     return (codep - inbuf);
  492. }
  493.  
  494. #include "387opcodes.h"
  495.  
  496. dofloat ()
  497. {
  498.     struct dis386 *dp;
  499.     unsigned char floatop;
  500.     
  501.     floatop = codep[-1];
  502.     
  503.     if (mod != 3) {
  504.         putop (float_mem[(floatop - 0xd8) * 8 + reg]);
  505.         obufp = op1out;
  506.         OP_E (v_mode);
  507.         return;
  508.     }
  509.     codep++;
  510.     
  511.     dp = &float_reg[floatop - 0xd8][reg];
  512.     if (dp->name == NULL) {
  513.         putop (fgrps[dp->bytemode1][rm]);
  514.         /* instruction fnstsw is only one with strange arg */
  515.         if (floatop == 0xdf && *codep == 0xe0)
  516.             strcpy (op1out, "%eax");
  517.     } else {
  518.         putop (dp->name);
  519.         obufp = op1out;
  520.         if (dp->op1)
  521.             (*dp->op1)(dp->bytemode1);
  522.         obufp = op2out;
  523.         if (dp->op2)
  524.             (*dp->op2)(dp->bytemode2);
  525.     }
  526. }
  527.  
  528. /* ARGSUSED */
  529. OP_ST (ignore)
  530. {
  531.     oappend ("%st");
  532. }
  533.  
  534. /* ARGSUSED */
  535. OP_STi (ignore)
  536. {
  537.     sprintf (scratchbuf, "%%st(%d)", rm);
  538.     oappend (scratchbuf);
  539. }
  540.  
  541.  
  542. /* capital letters in template are macros */
  543. putop (template)
  544.     char *template;
  545. {
  546.     char *p;
  547.     
  548.     for (p = template; *p; p++) {
  549.         switch (*p) {
  550.         default:
  551.             *obufp++ = *p;
  552.             break;
  553.         case 'C':        /* For jcxz/jecxz */
  554.             if (aflag == 0)
  555.                 *obufp++ = 'e';
  556.             break;
  557.         case 'N':
  558.             if ((prefixes & PREFIX_FWAIT) == 0)
  559.                 *obufp++ = 'n';
  560.             break;
  561.         case 'S':
  562.             /* operand size flag */
  563.             Sflag = 1;
  564.              if (dflag)
  565.                 *obufp++ = 'l';
  566.             else
  567.                 *obufp++ = 'w';
  568.             break;
  569.         }
  570.     }
  571.     *obufp = 0;
  572. }
  573.  
  574. oappend (s)
  575.     char *s;
  576. {
  577.     strcpy (obufp, s);
  578.     obufp += strlen (s);
  579.     *obufp = 0;
  580. }
  581.  
  582. append_prefix ()
  583. {
  584.     if (prefixes & PREFIX_CS)
  585.         oappend ("%cs:");
  586.     if (prefixes & PREFIX_DS)
  587.         oappend ("%ds:");
  588.     if (prefixes & PREFIX_SS)
  589.         oappend ("%ss:");
  590.     if (prefixes & PREFIX_ES)
  591.         oappend ("%es:");
  592.     if (prefixes & PREFIX_FS)
  593.         oappend ("%fs:");
  594.     if (prefixes & PREFIX_GS)
  595.         oappend ("%gs:");
  596. }
  597.  
  598. OP_indirE (bytemode)
  599. {
  600.     oappend ("*");
  601.     OP_E (bytemode);
  602. }
  603.  
  604. OP_E (bytemode)
  605. {
  606.     int disp;
  607.     int havesib;        /* have "scaled index base" byte */
  608.     int didoutput = 0;
  609.     int base;
  610.     int index;
  611.     int scale;
  612.     int havebase;
  613.     
  614.     /* skip mod/rm byte */
  615.     codep++;
  616.     
  617.     havesib = 0;
  618.     havebase = 0;
  619.     disp = 0;
  620.     
  621.     if (mod == 3) {        /* Register mod's */
  622.         switch (bytemode) {
  623.         case b_mode:
  624.             oappend (names8[rm]);
  625.             break;
  626.         case w_mode:
  627.             oappend (names16[rm]);
  628.             break;
  629.         case v_mode:
  630.             if (dflag)
  631.                 oappend (names32[rm]);
  632.             else
  633.                 oappend (names16[rm]);
  634.             break;
  635.         default:
  636.             oappend ("<bad dis table>");
  637.             break;
  638.         }
  639.         return;
  640.     }
  641.     
  642.     append_prefix();
  643.  
  644.     if (rm == 4 && aflag) {
  645.         havesib = 1;
  646.         havebase = 1;
  647.         scale = (*codep >> 6) & 3;
  648.         index = (*codep >> 3) & 7;
  649.         base = *codep & 7;
  650.         codep++;
  651.     }
  652.     
  653.     if (!aflag && mod < 3) {
  654.         switch (mod) {
  655.         case 0:
  656.             if (rm == 6) {
  657.                 disp = get16();
  658.                 oappend(datasymbol(disp, WORDREF, 1));
  659.                 return;
  660.             }
  661.             break;
  662.  
  663.         case 1:
  664.             sprintf(scratchbuf, "%#x", *codep++);
  665.             oappend(scratchbuf);
  666.             break;
  667.  
  668.         case 2:
  669.             disp = get16();
  670.             oappend(datasymbol(disp, WORDREF, 1));
  671.             break;
  672.         }
  673.             
  674.         switch (rm) {
  675.         case 0: oappend("(%bx,%si)"); return;
  676.         case 1: oappend("(%bx,%di)"); return;
  677.         case 2: oappend("(%bp,%si)"); return;
  678.         case 3: oappend("(%bp,%di)"); return;
  679.         case 4: oappend("(%si)"); return;
  680.         case 5: oappend("(%di)"); return;
  681.         case 6: oappend("(%bp)"); return;
  682.         case 7: oappend("(%bx)"); return;
  683.         }
  684.     }
  685.     switch (mod) {
  686.     case 0:
  687.         switch (rm) {
  688.         case 4:        /* DS:[d32+(scaled index)] */
  689.             if (!aflag)
  690.                 break;
  691.             /* implies havesib and havebase */
  692.             if (base == 5) {
  693.                 havebase = 0;
  694.                 disp = get32 ();
  695.             }
  696.             break;
  697.         case 5:        /* DS:d32 */
  698.             if (!aflag)
  699.                 break;
  700.             disp = get32 ();
  701.             break;
  702.         case 6:        /* DS:d16 */
  703.             if (aflag)
  704.                 break;
  705.             disp = get16 ();
  706.             break;
  707.         default:    /* DS:[Ereg] */
  708.             havebase = 1;
  709.             base = rm;
  710.             break;
  711.         }
  712.         break;
  713.  
  714.     case 1:            /* DS:[Ereg+d8] */
  715.         disp = *(char *)codep++;
  716.         if (rm != 4) {
  717.             havebase = 1;
  718.             base = rm;
  719.         }
  720.         break;
  721.  
  722.     case 2:            /* DS:[Ereg+d32] */
  723.         if (aflag) {
  724.             disp = get32 ();
  725.             if (rm != 4) {
  726.                 havebase = 1;
  727.                 base = rm;
  728.             }
  729.         } else {
  730.             disp = get16();
  731.         }
  732.         break;
  733.     }
  734.  
  735. /*    if (mod < 3) { */
  736.     if (havesib) {
  737.         if (mod == 0) {
  738.             if (base == 5) { /* DS:[d32+(scaled index)] */
  739.                 if (prefixes & PREFIX_CS) {
  740.                     register struct symtab *symp;
  741.                     int mode = scale==2 ? WORDREF
  742.                         : scale==3 ? DWORDREF
  743.                             : 0;
  744.                     symp = lookup(disp, TEXTSEG|mode);
  745.                     if (pass2)
  746.                         if (symp)
  747.                             sprintf (scratchbuf, "%s", symname(symp));
  748.                         else
  749.                             sprintf (scratchbuf, "%s", datasymbol(disp, mode, 1));
  750.                     oappend(scratchbuf);
  751.                 } else
  752.                     oappend(datasymbol(disp, 0, 1));
  753.             }
  754.         } else if (base == 5) { /* SS:[EBP+...] */
  755.             sprintf (scratchbuf, "%d", disp);
  756.             oappend(scratchbuf);
  757.         } else if (base == 4) {    /* SS:[ESP+...] */
  758.             sprintf(scratchbuf, "%d", disp);
  759.             oappend(scratchbuf);
  760.         } else {    /* DS:[...] */
  761.             if (mod == 1) {    /* Byte offset */
  762.                 sprintf (scratchbuf, "%d", disp);
  763.                 oappend(scratchbuf);
  764.             } else { /* Longword offset */
  765.                 oappend(datasymbol(disp, 0, 1));
  766.             }
  767.         }
  768.     } else if (aflag && rm == 5 || /* DS:d32 or SS:[EBP...] */
  769.            !aflag && rm == 6) {    /* DS:d16 */
  770.         if (mod == 0) { /* DS:d32 or DS:d16 */
  771.             /* Normal "direct" data address */
  772.             oappend(datasymbol(/* Sflag && !dflag ? disp + database : */ disp,
  773.                        bytemode==b_mode ? BYTEREF :
  774.                        bytemode==w_mode ? WORDREF :
  775.                        Sflag ? dflag ? DWORDREF
  776.                        : WORDREF : 0, 1));
  777.         } else {
  778.             sprintf(scratchbuf, "%d", disp);
  779.             oappend(scratchbuf);
  780.         }
  781. #if 0
  782.     } else if (mod == 2) { /* DS:[ereg+d8] */
  783.         sprintf(scratchbuf, "%d", disp);
  784.         oappend(scratchbuf);
  785. #endif
  786.     } else {    /* DS:[ereg+d32] */
  787.         oappend(datasymbol(disp, 0, 1));
  788.     }
  789. /*    } */
  790.     
  791.     if (havebase || havesib) {
  792.         oappend ("(");
  793.         if (!havebase && !havesib) oappend("????");
  794.         if (havebase)
  795.             oappend ((aflag ? names32 : names16_OP_E)[base]);
  796.         if (havesib) {
  797.             if (index != 4) {
  798.                 sprintf (scratchbuf, ",%s", names32[index]);
  799.                 oappend (scratchbuf);
  800.                 sprintf (scratchbuf, ",%d", 1 << scale);
  801.                 oappend (scratchbuf);
  802.             }
  803.         }
  804.         oappend (")");
  805.     }
  806. }
  807.  
  808. OP_G (bytemode)
  809. {
  810.     switch (bytemode) {
  811.     case b_mode:
  812.         oappend (names8[reg]);
  813.         break;
  814.     case w_mode:
  815.         oappend (names16[reg]);
  816.         break;
  817.     case d_mode:
  818.         oappend (names32[reg]);
  819.         break;
  820.     case v_mode:
  821.         if (dflag)
  822.             oappend (names32[reg]);
  823.         else
  824.             oappend (names16[reg]);
  825.         break;
  826.     default:
  827.         oappend ("<internal disassembler error>");
  828.         break;
  829.     }
  830. }
  831.  
  832. get32 ()
  833. {
  834.     int x = 0;
  835.     
  836.     x = *codep++ & 0xff;
  837.     x |= (*codep++ & 0xff) << 8;
  838.     x |= (*codep++ & 0xff) << 16;
  839.     x |= (*codep++ & 0xff) << 24;
  840.     return (x);
  841. }
  842.  
  843. get16 ()
  844. {
  845.     int x = 0;
  846.     
  847.     x = *codep++ & 0xff;
  848.     x |= (*codep++ & 0xff) << 8;
  849.     return (x);
  850. }
  851.  
  852. OP_REG (code)
  853. {
  854.     char *s;
  855.     
  856.     switch (code) {
  857.     case indir_dx_reg: 
  858.         s = "(%dx)"; 
  859.         break;
  860.     case ax_reg: 
  861.     case cx_reg: 
  862.     case dx_reg: 
  863.     case bx_reg:
  864.     case sp_reg: 
  865.     case bp_reg: 
  866.     case si_reg: 
  867.     case di_reg:
  868.         s = names16[code - ax_reg];
  869.         break;
  870.     case es_reg: 
  871.     case ss_reg: 
  872.     case cs_reg:
  873.     case ds_reg: 
  874.     case fs_reg: 
  875.     case gs_reg:
  876.         s = names_seg[code - es_reg];
  877.         break;
  878.     case al_reg: 
  879.     case ah_reg: 
  880.     case cl_reg: 
  881.     case ch_reg:
  882.     case dl_reg: 
  883.     case dh_reg: 
  884.     case bl_reg: 
  885.     case bh_reg:
  886.         s = names8[code - al_reg];
  887.         break;
  888.     case eAX_reg: 
  889.     case eCX_reg: 
  890.     case eDX_reg: 
  891.     case eBX_reg:
  892.     case eSP_reg: 
  893.     case eBP_reg: 
  894.     case eSI_reg: 
  895.     case eDI_reg:
  896.         if (dflag)
  897.             s = names32[code - eAX_reg];
  898.         else
  899.             s = names16[code - eAX_reg];
  900.         break;
  901.     default:
  902.         s = "<internal disassembler error>";
  903.         break;
  904.     }
  905.     oappend (s);
  906. }
  907.  
  908. OP_I (bytemode)
  909. {
  910.     int op;
  911.     
  912.     switch (bytemode) {
  913.     case b_mode:
  914.         op = *codep++ & 0xff;
  915.         break;
  916.     case v_mode:
  917.         if (dflag)
  918.             op = get32 ();
  919.         else
  920.             op = get16 ();
  921.         break;
  922.     case w_mode:
  923.         op = get16 ();
  924.         break;
  925.     default:
  926.         oappend ("<internal disassembler error>");
  927.         return;
  928.     }
  929.     oappend (getimmed(op));
  930. }
  931.  
  932. OP_sI (bytemode)
  933. {
  934.     int op;
  935.     
  936.     switch (bytemode) {
  937.     case b_mode:
  938.         op = *(char *)codep++;
  939.         break;
  940.     case v_mode:
  941.         if (dflag)
  942.             op = get32 ();
  943.         else
  944.             op = (short)get16();
  945.         break;
  946.     case w_mode:
  947.         op = (short)get16 ();
  948.         break;
  949.     default:
  950.         oappend ("<internal disassembler error>");
  951.         return;
  952.     }
  953.     oappend (getimmed(op));
  954. }
  955.  
  956. /*
  957.  * Jump opcodes
  958.  */
  959. OP_J (bytemode)
  960. {
  961.     int disp, addr;
  962.     int mask = -1;
  963.     register struct symtab *symp;
  964.     
  965.     switch (bytemode) {
  966.     case b_mode:
  967.         disp = *(char *)codep++;
  968.         break;
  969.     case v_mode:
  970.         if (dflag)
  971.             disp = get32 ();
  972.         else {
  973.             disp = (short)get16 ();
  974.             /* for some reason, a data16 prefix on a jump instruction
  975.                means that the pc is masked to 16 bits after the
  976.                displacement is added!  */
  977.             mask = 0xffff;
  978.         }
  979.         break;
  980.     default:
  981.         oappend ("<internal disassembler error>");
  982.         return;
  983.     }
  984.     
  985.     addr =  (start_pc + codep - start_codep + disp) & mask;
  986.     symp = lookup(addr, TEXTSEG|JUMPREF);
  987.     if (pass2) {
  988.         if (symp)
  989.             sprintf (scratchbuf, "%s", symname(symp));
  990.         else
  991.             sprintf (scratchbuf, "%s", datasymbol(addr, 0, 1));
  992.         oappend (scratchbuf);
  993.     }
  994. }
  995.  
  996. /* ARGSUSED */
  997. OP_SEG (dummy)
  998. {
  999.     static char *sreg[] = {
  1000.         "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
  1001.     };
  1002.     
  1003.     oappend (sreg[reg]);
  1004. }
  1005.  
  1006. /*
  1007.  * A subroutine address, or a jump/call far destination
  1008.  */
  1009. OP_DIR (size)
  1010. {
  1011.     int seg, offset, addr;
  1012.     register struct symtab *symp;
  1013.     
  1014.     switch (size) {
  1015.     case lptr:
  1016.         if (aflag) {
  1017.             offset = get32 ();
  1018.             seg = get16 ();
  1019.         } else  {
  1020.             offset = get16 ();
  1021.             seg = get16 ();
  1022.         }
  1023.         sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
  1024.         oappend (scratchbuf);
  1025.         break;
  1026.  
  1027.     case v_mode:        /* Call instruction destination */
  1028.         if (aflag)
  1029.             offset = get32 ();
  1030.         else
  1031.             offset = (short)get16 ();
  1032.         
  1033.         addr = start_pc + codep - start_codep + offset;
  1034.         symp = lookup(addr, TEXTSEG|CALLREF);
  1035.         if (pass2)
  1036.             if (symp)
  1037.                 oappend(symname(symp));
  1038.             else
  1039.                 oappend(datasymbol(addr, 0, 1));
  1040.         
  1041.         break;
  1042.     default:
  1043.         oappend ("<internal disassembler error>");
  1044.         break;
  1045.     }
  1046. }
  1047.  
  1048. /* ARGSUSED */
  1049. OP_OFF (bytemode)
  1050. {
  1051.     int off;
  1052.     
  1053.     if (aflag)
  1054.         off = get32 ();
  1055.     else
  1056.         off = get16 ();
  1057.     
  1058.     oappend(datasymbol(off, 0, 0));
  1059. }
  1060.  
  1061. /* ARGSUSED */
  1062. OP_ESDI (dummy)
  1063. {
  1064.     oappend ("%es:(");
  1065.     oappend (aflag ? "%edi" : "%di");
  1066.     oappend (")");
  1067. }
  1068.  
  1069. /* ARGSUSED */
  1070. OP_DSSI (dummy)
  1071. {
  1072.     oappend ("%ds:(");
  1073.     oappend (aflag ? "%esi" : "%si");
  1074.     oappend (")");
  1075. }
  1076.  
  1077. /* ARGSUSED */
  1078. OP_ONE (dummy)
  1079. {
  1080.     oappend ("1");
  1081. }
  1082.  
  1083. /* ARGSUSED */
  1084. OP_C (dummy)
  1085. {
  1086.     codep++; /* skip mod/rm */
  1087.     sprintf (scratchbuf, "%%cr%d", reg);
  1088.     oappend (scratchbuf);
  1089. }
  1090.  
  1091. /* ARGSUSED */
  1092. OP_D (dummy)
  1093. {
  1094.     codep++; /* skip mod/rm */
  1095.     sprintf (scratchbuf, "%%db%d", reg);
  1096.     oappend (scratchbuf);
  1097. }
  1098.  
  1099. /* ARGSUSED */
  1100. OP_T (dummy)
  1101. {
  1102.     codep++; /* skip mod/rm */
  1103.     sprintf (scratchbuf, "%%tr%d", reg);
  1104.     oappend (scratchbuf);
  1105. }
  1106.  
  1107. OP_rm (bytemode)
  1108. {
  1109.     switch (bytemode) {
  1110.     case d_mode:
  1111.         oappend (names32[rm]);
  1112.         break;
  1113.     case w_mode:
  1114.         oappend (names16[rm]);
  1115.         break;
  1116.     }
  1117. }
  1118.  
  1119. /*
  1120.  * Load the file to disassemble, into memory
  1121.  * Decoding the Xenix a.out header
  1122.  */
  1123. loadaout(fname)
  1124. {
  1125.     int fd;
  1126.     register int i;
  1127.     short magic;
  1128.  
  1129.     fd = open(fname, 0);
  1130.     if (fd == 0) {
  1131.         perror(fname); exit(1);
  1132.     }
  1133.     if (read(fd, &magic, 2) != 2) {
  1134.         perror(fname); exit(1);
  1135.     }
  1136.     lseek(fd, 0L, 0);
  1137.     if (magic == X_MAGIC) {
  1138.         if (read(fd, &xoutx, sizeof xoutx) != sizeof xoutx) {
  1139.             perror(fname); exit(1);
  1140.         }
  1141. /*        if ((xoutx.x_cpu & XC_CPU) != XC_386)
  1142.             fatal("Not a 80386 executable file - %s\n", fname); */
  1143.         if (read(fd, &xoutxe, sizeof xoutxe) != sizeof xoutxe) {
  1144.             perror(fname); exit(1);
  1145.         }
  1146.         if (!(xoutx.x_renv & XE_SEG))
  1147.             fatal("Not a Xenix segmented file - %s\n", fname);
  1148.         lseek(fd, xoutxe.xe_segpos, 0);
  1149.         segcount = xoutxe.xe_segsize / sizeof(struct xseg);
  1150.         if (segcount > MAXSEG)
  1151.             fatal("Too many segments (%d)", segcount);
  1152.         if (read(fd, xoutxs, segcount * sizeof(struct xseg)) != segcount * sizeof(struct xseg)) {
  1153.             perror(fname); exit(1);
  1154.         }
  1155.         for (i = 0; i < segcount; i++) {
  1156.             switch (xoutxs[i].xs_type) {
  1157.             case XS_TTEXT:
  1158.                 if (textsegp) fatal("Multiple text segments");
  1159.                 textsegp = &xoutxs[i];
  1160.                 textseg = textsegp->xs_seg;
  1161.                 break;
  1162.                 
  1163.             case XS_TDATA:
  1164.                 if (datasegp) fatal("Multiple data segments");
  1165.                 datasegp = &xoutxs[i];
  1166.                 dataseg = datasegp->xs_seg;
  1167.                 break;
  1168.                 
  1169.             case XS_TSYMS:
  1170.                 if (xoutxs[i].xs_attr != XS_SXSEG)
  1171.                     continue;
  1172.                 if (symsegp) fatal("Multiple symbol segments");
  1173.                 symsegp = &xoutxs[i];
  1174.                 break;
  1175.                 
  1176.             case XS_TREL:
  1177.                 break;
  1178.             default:
  1179.                 fatal("Unknown segment: %x", xoutxs[i].xs_type);
  1180.             }
  1181.         }
  1182.         if (textsegp == NULL) fatal("Undefined text segment");
  1183.         if (datasegp == NULL) fatal("Undefined data segment");
  1184.         if (symsegp != NULL)
  1185.             readsymbols(fd);
  1186.         textp = (unsigned char *)malloc(textsegp->xs_psize);
  1187.         if (textp == NULL) fatal("Out of memory");
  1188.         xtextp = textp;
  1189.         datap = (unsigned char *)malloc(datasegp->xs_psize);
  1190.         if (datap == NULL) fatal("Out of memory");
  1191.         lseek(fd, textsegp->xs_filpos, 0);
  1192.         if (read(fd, textp, textsegp->xs_psize) != textsegp->xs_psize) {
  1193.             perror(fname); fatal("File read error (text segment)");
  1194.         }
  1195.         lseek(fd, datasegp->xs_filpos, 0);
  1196.         if (read(fd, datap, datasegp->xs_psize) != datasegp->xs_psize) {
  1197.             perror(fname);
  1198.             fatal("File read error (data segment)");
  1199.         }
  1200.         textsize = textsegp->xs_vsize;
  1201.         datasize = datasegp->xs_vsize;
  1202.         database = datasegp->xs_rbase;
  1203.     } else if (magic == 0x5a4d) {
  1204.         /* msdos .exe file */
  1205.         if (read(fd, &exehdr, sizeof exehdr) != sizeof exehdr) {
  1206.             perror(fname); exit(1);
  1207.         }
  1208.         datasize = exehdr.csoff * 16;
  1209.         textsize = exehdr.lengthp * 512 - datasize - exehdr.hdrsize*16;
  1210.         if (exehdr.lengthb)
  1211.             textsize += exehdr.lengthb - 512;
  1212.         database = 0;
  1213.         textp = (unsigned char *)malloc(textsize);
  1214.         if (textp == NULL) fatal("Out of memory");
  1215.         xtextp = textp;
  1216.         datap = (unsigned char *)malloc(datasize);
  1217.         if (datap == NULL) fatal("Out of memory");
  1218.         lseek(fd, exehdr.hdrsize * 16, 0);
  1219.         if (read(fd, datap, datasize) != datasize) {
  1220.             perror(fname);
  1221.             fatal("File read error (data segment)");
  1222.         }
  1223.         if (read(fd, textp, textsize) != textsize) {
  1224.             perror(fname); fatal("File read error (text segment)");
  1225.         }
  1226.     } else
  1227.         fatal("Not a recognized executable file - %s\n", fname);
  1228.     close(fd);
  1229. }
  1230.  
  1231. readsymbols(fd)
  1232. {
  1233.     register char *symp;
  1234.     char *symendp;
  1235.     int type, seg, value;
  1236.     char *name;
  1237.     int i;
  1238.  
  1239.     symp = (char *)malloc(symsegp->xs_psize);
  1240.     if (symp == NULL) fatal("Out of memory");
  1241.     lseek(fd, symsegp->xs_filpos, 0);
  1242.     if ((i = read(fd, symp, symsegp->xs_psize)) != symsegp->xs_psize)
  1243.         fatal("Symbol Table read error");
  1244.     symendp = symp + symsegp->xs_psize;
  1245.     while (symp < symendp) {
  1246.         type =  ((struct sym *)symp)->s_type;
  1247.         seg =   ((struct sym *)symp)->s_seg;
  1248.         value = ((struct sym *)symp)->s_value;
  1249.         name = symp + sizeof(struct sym);
  1250.         symp += sizeof(struct sym) + strlen(name) + 1;
  1251.         if (seg == textseg)
  1252.             enter(name, value, TEXTSEG|DEFINED);
  1253.         else if (seg == dataseg)
  1254.             enter(name, value, DATASEG|DEFINED);
  1255.     }
  1256. }
  1257.  
  1258. fatal(f, args)
  1259. {
  1260.     vfprintf(stderr, f, &args);
  1261.     fprintf(stderr, "\n");
  1262.     exit(1);
  1263. }
  1264.  
  1265. /*
  1266.  * Look up a symbol in symboltable. 
  1267.  * Enter it as undefined if not
  1268.  * already there.
  1269.  */
  1270. struct symtab *lookup(addr, ref)
  1271.     unsigned int addr;
  1272. {
  1273.     register struct symtab *symtp,**symhp;
  1274.     int seg = ref & (TEXTSEG|DATASEG);
  1275.  
  1276.     symhp = &symhash[addr % SYMHS];
  1277.     while (symtp = *symhp) {
  1278.         if (addr == symtp->symval && (seg & symtp->symflags)) {
  1279.             if (!pass2) {
  1280.                 symtp->symflags |= ref;
  1281.                 symtp->symrefcount++;
  1282.             }
  1283.             return symtp;
  1284.         }
  1285.         if ((++symhp) >= &symhash[SYMHS]) 
  1286.             symhp = symhash;
  1287.     }
  1288.     if (pass2 || ref & NOENTER || !aflag && addr < THRESHOLD)
  1289.         return NULL;
  1290.     symtp = enter(NULL, addr, ref|GENERATED);
  1291.     symtp->symrefcount++;
  1292.     return symtp;
  1293. }
  1294.  
  1295. /*
  1296.  * enter a symbol into symboltable. 
  1297.  */
  1298. struct symtab *enter(id, addr, ref)
  1299.     char *id;
  1300.     unsigned addr;
  1301. {
  1302.     register struct symtab *symtp, **symhp, **osymhp;
  1303.     int seg = ref & (DATASEG|TEXTSEG);
  1304.  
  1305.     symcount++;
  1306.     osymhp = symhp = &symhash[addr % SYMHS];
  1307.     while (symtp = *symhp) {
  1308.         if (++symhp >= &symhash[SYMHS])
  1309.             symhp = symhash;
  1310.         if (symhp == osymhp)
  1311.             fatal("Symbol table overflow");
  1312.         if (addr == symtp->symval && (seg & symtp->symflags))
  1313.             return symtp;
  1314. /*            fprintf(stderr, "Multiple definitions of symbol %s addr=%x, seg=%d, ref=%d\n", id ? id : "", addr, seg, ref); */
  1315.     }
  1316.     symtp = (struct symtab *)malloc(sizeof(struct symtab));
  1317.     *symhp = symtp;
  1318.     symtp->symflags = ref;
  1319.     symtp->symval = addr;
  1320.     symtp->symrefcount = 0;
  1321.     if (id)
  1322.         symtp->symstring = strdup(id);
  1323.     else {
  1324.         symtp->symstring = NULL;
  1325.         symtp->symflags |= GENERATED;
  1326.     }
  1327.     return symtp;
  1328. }
  1329.  
  1330. char *
  1331. symname(symp)
  1332.     struct symtab *symp;
  1333. {
  1334.     static char id[20];
  1335.  
  1336.     if (symp->symstring)
  1337.         return symp->symstring;
  1338.     sprintf(id, "%s0%x", symp->symflags & TEXTSEG ? 
  1339.                 (symp->symflags & CALLREF ? "P_" : "L") :
  1340.                  symp->symflags & DATASEG ? "D" : "X", symp->symval);
  1341.     return id;
  1342. }
  1343.  
  1344. char *
  1345. getimmed(val)
  1346.     unsigned int val;
  1347. {
  1348.     static char scratch[20];
  1349.     register struct symtab *symp;
  1350.  
  1351.     if (*start_codep == 0x68) 
  1352.         sprintf(scratch, "$%s", datasymbol(val, PUSHLIMMED, 0));
  1353.     else
  1354.         sprintf(scratch, "$%s", datasymbol(val, 0, 0));
  1355.     return scratch;
  1356. }
  1357.  
  1358.  
  1359. char *
  1360. datasymbol(addr, ref, hexdef)
  1361.     unsigned int addr;
  1362. {
  1363.     register struct symtab *symp;
  1364.     static char scratch[20];
  1365.  
  1366.     if (addr == 0) {
  1367.         return "0";
  1368.     }
  1369.     if (addr >= database && addr < database + xoutx.x_data + xoutx.x_bss) {
  1370.         symp = lookup(addr, DATASEG|ref);
  1371.         if (pass2) {
  1372.             if (symp != NULL) {
  1373.                 if (symp->symflags & ASCIZ)
  1374.                     return ascizdata(addr);
  1375.                 if (symp->symstring)
  1376.                     return symp->symstring;
  1377.             }
  1378.             sprintf(scratch, "D_0%x", addr);
  1379.             return scratch;
  1380.         }
  1381.     }
  1382.     if (addr < 10 /* || !hexdef */)
  1383.         sprintf(scratch, "%d", addr);
  1384.     else
  1385.         sprintf(scratch, "%#x", addr);
  1386.     return scratch;
  1387. }
  1388.  
  1389. scomp(syp1, syp2)
  1390.     register struct symtab **syp1, **syp2;
  1391. {
  1392.     if ((*syp1)->symval < (*syp2)->symval)
  1393.         return -1;
  1394.     else if ((*syp1)->symval > (*syp2)->symval)
  1395.         return 1;
  1396.     return 0;
  1397. }
  1398.  
  1399. symtabpass()
  1400. {
  1401.     struct symtab *symarr[SYMHS];
  1402.     register int i, j;
  1403.     int labno;
  1404.     register struct symtab *symp;
  1405.     char id[20];
  1406.     int syc;
  1407.  
  1408.     /*
  1409.      * Look for "case" jump tables
  1410.      */
  1411.     for (i = 0; i < SYMHS; i++) {
  1412.         if ((symp = symhash[i]) && symp->symrefcount == 1 && symp->symflags & (WORDREF|DWORDREF) && !(symp->symflags & (CALLREF|JUMPREF))) {
  1413.             unsigned int addr = symp->symval;
  1414.             unsigned int disp;
  1415.             register struct symtab *labp;
  1416.             while (addr < textsize) {
  1417.                 register int j;
  1418.                 for (j = 1; j < 4; j++)
  1419.                     if (lookup(addr+j, NOENTER))
  1420.                         goto bloop;
  1421.                 disp = *(unsigned int *)(textp+addr);
  1422.                 if (disp > 0 && disp < textsize)
  1423.                     labp = lookup(disp, TEXTSEG|JUMPREF);
  1424.                 addr += 4;
  1425.             }
  1426.         bloop: ;
  1427.         }
  1428.     }
  1429.  
  1430.     syc = 0;
  1431.     for (i = 0; i < SYMHS; i++)
  1432.         if (symarr[syc] = symhash[i])
  1433.             syc++;
  1434.     qsort(symarr, syc, sizeof(struct symtab *), scomp);
  1435.     printf("%d symbols defined\n", syc);
  1436.  
  1437.     /*
  1438.      * Assign label names for code labels
  1439.      */
  1440.     labno = 0;
  1441.     for (i = 0; i < syc; i++) {
  1442.         if ((symp = symarr[i]) && symp->symstring == NULL
  1443.                            && symp->symflags & TEXTSEG) {
  1444.             
  1445.             sprintf(id, "L%d", ++labno);
  1446.             symp->symstring = strdup(id);
  1447.         }
  1448.     }
  1449.  
  1450.     /*
  1451.      * Look for asciz strings
  1452.      */
  1453.     for (i = 0; i < syc; i++) {
  1454.         unsigned addr1, addr2;
  1455.         if ((symp = symarr[i]) == NULL)
  1456.             continue;
  1457.         if (symp->symflags & DATASEG && symp->symflags & PUSHLIMMED
  1458.             && symp->symrefcount == 1) {
  1459.             for (j = i+1; j < syc; j++)
  1460.                 if (symarr[j] && symarr[j]->symflags & DATASEG)
  1461.                     break;
  1462.             if (j == syc)
  1463.                 break;
  1464.             addr1 = symp->symval;
  1465.             addr2 = symarr[j]->symval;
  1466.             if (addr2 > database + xoutx.x_data
  1467.                 || addr1 < database)
  1468.                 continue;
  1469.             for (j = addr1; j < addr2; j++)
  1470.                 if (datap[j - database] == '\0')
  1471.                     break;
  1472.             dummy();
  1473.             if (j < addr2 && ((j + 4) & ~3) == addr2) 
  1474. /*            if (j == addr2-1 || j == addr2-2 || j == addr2-3) */
  1475.                 symarr[i]->symflags |= ASCIZ;
  1476.             
  1477.         }
  1478.     }
  1479.  
  1480.     /*
  1481.      * Assign label names for data labels
  1482.      */
  1483.     labno = 0;
  1484.     for (i = 0; i < syc; i++) {
  1485.         if ((symp = symarr[i]) && symp->symstring == NULL
  1486.                            && symp->symflags & DATASEG) {
  1487.             
  1488.             sprintf(id, "D%d", ++labno);
  1489.             symp->symstring = strdup(id);
  1490.         }
  1491.     }
  1492. }
  1493.  
  1494. dummy() {}
  1495.  
  1496. char *
  1497. ascizdata(addr)
  1498. {
  1499.     register unsigned char *cp1 = datap + addr - database;
  1500.     static char buf[1000];
  1501.     register unsigned char *cp2 = buf;
  1502.     register c;
  1503.  
  1504.     *cp2++ = '"';
  1505.     while (c = *cp1++) {
  1506.         switch (c) {
  1507.         case '\n':    *cp2++ = '\\'; *cp2++ = 'n'; break;
  1508.         case '\t':    *cp2++ = '\\'; *cp2++ = 't'; break;
  1509.         case '\r':    *cp2++ = '\\'; *cp2++ = 'r'; break;
  1510.         default:
  1511.             if (c >= ' ' && c < 127)
  1512.                 *cp2++ = c;
  1513.             else {
  1514.                 *cp2++ = '\\';
  1515.                 if (c & 0300) *cp2++ = (c >> 6) + '0';
  1516.                 if (c & 0070) *cp2++ = ((c >> 3) & 7) + '0';
  1517.                 *cp2++ = (c & 7) + '\0';
  1518.             }
  1519.         }
  1520.         if (cp2 >= buf+sizeof(buf)-2)
  1521.             fatal("Too long asciz string");
  1522.     }
  1523.     *cp2++ = '"';
  1524.     *cp2++ = '\0';
  1525.     return buf;
  1526. }
  1527.