home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 348_01 / dis48.c < prev    next >
Text File  |  1991-05-02  |  5KB  |  279 lines

  1. /*
  2. **    Disassembler for 8048, 8041 microcode.
  3. **
  4. **    Copyright (c) 1990, Michael G. Panas
  5. **
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10.  
  11. #include "dis48.h"
  12.  
  13. int    infd, pc, lincnt, pass, eoflg;
  14. char    opcode, op2;
  15. char    infile[80], outfile[80], labelbuf[10];
  16. char    *lp, *label, *text, *operand, *tabzone, *hexdata;
  17. FILE    *outfd;
  18.  
  19. char    *prog = "8048/8041 Disassembler\n";
  20. char    *copy = "Copyright (c) 1990, Michael G. Panas\n";
  21. char    *tab = "\t";
  22. char    *nolabel = "";
  23.  
  24. struct    symbol    sym[SYMS];    /* the symbol table */
  25. int    symcnt = 0;        /* number of symbols used */
  26.  
  27. #include "dis48tbl.c"
  28.  
  29. int findlabel(), dolabel(), addlabel();
  30.  
  31. main(argc, argv)
  32. char **argv;
  33. int argc;
  34. {
  35.     if (argc == 1) { /* no args */
  36.         printf("%s%s", prog, copy);
  37.         printf("Input filename: ");
  38.         if (gets(infile) == NULL) {
  39.             perror("Line error:");
  40.             exit(1);
  41.         }
  42.         if (infile[0] == '\0')
  43.             exit(0);
  44.         printf("Output filename: ");
  45.         if (gets(outfile) == NULL) {
  46.             perror("Line error:");
  47.             exit(1);
  48.         }
  49.         if (outfile[0] == '\0')
  50.             exit(0);
  51.     }
  52.     else {
  53.         strcpy(infile, argv[1]);
  54.         strcpy(outfile, argv[2]);
  55.     }
  56.     
  57. #ifdef MSC
  58.     if ((infd = open(infile, O_RDONLY|O_BINARY)) == -1) {
  59. #else
  60.     if ((infd = open(infile, O_RDONLY)) == -1) {
  61. #endif
  62.         perror("Can't open input file:");
  63.         exit(1);
  64.     }
  65.     if ((outfd = fopen(outfile, "w")) == NULL) {
  66.         perror("Can't open output file:");
  67.         exit(1);
  68.     }
  69.     
  70.     prolog();            /* assembly startup stuff */
  71.  
  72.     pass = 0;
  73.     while (pass++ < 2) {        /* do 2 passes */
  74.         lseek(infd, 0, 0);    /* reset pointer */
  75.         eoflg = 0;
  76.         pc = 0;
  77.         lincnt = 0;
  78.         disasm();
  79.     }
  80.     
  81.     cleansym();
  82.  
  83.     epilog();            /* "END" statement */
  84.  
  85.     printf("Disassembly done, %d lines\n", lincnt);
  86. }
  87.  
  88. disasm()
  89. {
  90.     int address, len, origpc, nl;
  91.     unsigned char index, oper;
  92.     struct table *tb;
  93.     char buf[40], operbuf[10];
  94.  
  95.     do {
  96.         origpc = pc;
  97.         nl = 0;
  98.  
  99.         index = (unsigned char) getbyte();
  100.         if (eoflg) {
  101.             break;
  102.         }
  103.  
  104.         tb = &dis48[index];
  105.         
  106.         /* set up defaults */
  107.         label = nolabel;
  108.         text = tb->text;
  109.         operand = tab;
  110.         tabzone = tab;
  111.         sprintf(&buf[0], ";%04X %02X", pc-1, index);
  112.         hexdata = (char *) &buf[0];
  113.         
  114.         switch (tb->type) {
  115.  
  116.             case RET:
  117.                 nl = 1;
  118.             case NOP:
  119.             case DBC:
  120.                 break;
  121.  
  122.             case IMM:
  123.                 oper = (unsigned char) getbyte();
  124.                 sprintf(&operbuf[0], "0%02XH\t", oper);
  125.                 operand = &operbuf[0];
  126.                 sprintf(&buf[strlen(&buf[0])], " %02X", oper);
  127.                 if ((tb->width + 4) >= 8)
  128.                     tabzone = nolabel;
  129.                 break;
  130.  
  131.             case JMP:
  132.                 nl = 1;
  133.             case CAL:
  134.                 oper = (unsigned char) getbyte();
  135.                 sprintf(&buf[strlen(&buf[0])], " %02X", oper);
  136.                 address = ((index&0xe0) <<3) | oper;
  137.                 sprintf(&operbuf[0], "L%04X\t", address);
  138.                 operand = &operbuf[0];
  139.                 addlabel(address);
  140.                 break;
  141.  
  142.             case BRA:
  143.                 oper = (unsigned char) getbyte();
  144.                 sprintf(&buf[strlen(&buf[0])], " %02X", oper);
  145.                 address = ((pc-2) & 0xff00) | oper;
  146.                 sprintf(&operbuf[0], "L%04X\t", address);
  147.                 operand = &operbuf[0];
  148.                 addlabel(address);
  149.                 if ((tb->width + 5) >= 8)
  150.                     tabzone = nolabel;
  151.                 break;
  152.  
  153.         }
  154.  
  155.  
  156.         if (pass == 2) {
  157.             if (findlabel(origpc))
  158.                 dolabel(origpc);
  159.             putline();
  160.             if (nl)
  161.                 fprintf(outfd, "\n");
  162.         }
  163.     }
  164.     while (eoflg == 0);
  165. }
  166.  
  167. /*
  168. ** read the next byte from the input file
  169. */
  170. getbyte()
  171. {
  172.     char byte;
  173.     
  174.     if(read(infd, &byte, 1) == 0) {
  175.         eoflg = 1;
  176.     }
  177.     pc++;
  178.     return(byte);
  179. }
  180.  
  181. putline()
  182. {
  183.     fprintf(outfd, "%s%s%s%s%s\n", label, text, operand, tabzone, hexdata);
  184.     
  185.     lincnt++;
  186. }
  187.  
  188. addlabel(address)
  189. int address;
  190. {
  191.     int i;
  192.  
  193.     if (findlabel(address))
  194.         return;
  195.  
  196.     if ((i = symcnt++) == SYMS) {
  197.         printf("Symbol table overflow!\n");
  198.         exit(1);
  199.     }
  200.     
  201.     sym[i].flags |= USED;
  202.     sym[i].address = address;
  203. }
  204.  
  205. doref(address)
  206. int address;
  207. {
  208.     int i;
  209.  
  210.     i = findlabel(address) - 1;
  211.  
  212.     fprintf(outfd, "L%04X\tEQU\t%04XH\n", address, address);
  213.     sym[i].flags |= PRINT;
  214. }
  215.  
  216. dolabel(address)
  217. int address;
  218. {
  219.     int i;
  220.  
  221.     i = findlabel(address) - 1;
  222.  
  223.     sprintf(&labelbuf[0], "L%04X", address);
  224.     label = &labelbuf[0];
  225.     sym[i].flags |= PRINT;
  226. }
  227.  
  228. int
  229. findlabel(address)
  230. int address;
  231. {
  232.     int i;
  233.     for (i = 0; i <= symcnt; i++) {
  234.         if (address == sym[i].address) {
  235.             return(i+1);
  236.         }
  237.     }
  238.     return(0);
  239. }
  240.  
  241. cleansym()
  242. {
  243.     int i, k;
  244.  
  245.  
  246.     for (i = 0, k = 0; i <= symcnt; i++) {
  247.         if ((sym[i].flags & PRINT) == 0) {
  248.             k++;
  249.         }
  250.     }
  251.  
  252.     if (k == 0)
  253.         return;
  254.  
  255.     fprintf(outfd, "\n");
  256.     fprintf(outfd, ";    The following %d symbols are not within\n", k);
  257.     fprintf(outfd, ";    the address range of this file or are not\n");
  258.     fprintf(outfd, ";    on an instruction boundary.\n");
  259.  
  260.     for (i = 0; i <= symcnt; i++) {
  261.         if ((sym[i].flags & PRINT) == 0) {
  262.             doref(sym[i].address);
  263.         }
  264.     }
  265. }
  266.  
  267. prolog()
  268. {
  269.     fprintf(outfd, "\tORG\t0\n");
  270.     lincnt++;
  271. }
  272.  
  273. epilog()
  274. {
  275.     fprintf(outfd, "\tEND\n");
  276.     lincnt++;
  277. }
  278.  
  279.