/************************************************************************ * File: disassemble.c * * Author: Karl Abrahamson * * Written: February 2002 * * Description: * * This program reads a byte-code program and prints it in symbolic * * form so that it is easier to read. * * Tab stops: Every 8 characters * ************************************************************************/ /************************************************************************* * Copyright 2002 Karl Abrahamson. All rights reserved. * * * * This software is provided by the author "as is" and any * * express or implied warranties, including, but not limited to, the * * implied warranties of merchantability and fitness for a particular * * purpose are disclaimed. In no event shall the author be liable * * for any direct, indirect, incidental, special, exemplary, or * * consequential damages (including, but not limited to, procurement * * of substitute goods or services; loss of use, data, or profits; or * * business interruption) however caused and on any theory of liability, * * whether in contract, strict liability, or tort (including negligence * * or otherwise) arising in any way out of the use of this software, * * even if advised of the possibility of such damage. * *************************************************************************/ #include #include "machinedefs.h" #define USE_INSTRUCTION_CLASS #define USE_INSTRUCTION_NAME #include "instinfo.c" /************************************************************************ * GET_NULL_TERMINATED_STRING * ************************************************************************ * Copy a null-terminated string from INF to OUTF. * ************************************************************************/ void get_null_terminated_string(FILE *inf, FILE *outf) { int c = getc(inf); while(c != 0 && c != EOF) { putc(c, outf); c = getc(inf); } if(c == EOF) fprintf(outf, " (no null terminator)"); } /************************************************************************ * GET_FUNCTION_BODY * ************************************************************************ * Read the code for a function body from INF and write it in * * symbolic form to OUTF. * ************************************************************************/ void get_function_body(FILE *inf, FILE *outf) { int instr,k; instr = getc(inf); while(instr != MS_END && instr != EOF) { if(instr < M_FIRST_EXECUTABLE_INSTRUCTION || instr > M_LAST_INSTRUCTION) { fprintf(outf, "UNKNOWN INSTRUCTION %d", instr); } else { int index = instr - M_FIRST_EXECUTABLE_INSTRUCTION; switch(instruction_class[index]) { case ONE_BYTE_INSTRUCTION: fprintf(outf, "%s", instruction_name[index]); break; case TWO_BYTE_INSTRUCTION: case LABEL_INSTRUCTION: case GOTO_INSTRUCTION: k = getc(inf); if(k == EOF) fprintf(outf, "(Premature end of file)"); else fprintf(outf, "%s %d", instruction_name[index], k); break; case CALL_INSTRUCTION: k = getc(inf); if(k == EOF) fprintf(outf, "(Premature end of file)"); else { fprintf(outf, "%s %d ", instruction_name[index], k); get_null_terminated_string(inf, outf); } } } fprintf(outf, "\n"); instr = getc(inf); } if(instr == MS_END) fprintf(outf, "MS_END\n"); } /************************************************************************ * DISASSEMBLE_SECTIONS * ************************************************************************ * Read the code for a program from INF and write it in * * symbolic form to OUTF. * ************************************************************************/ void disassemble_sections(FILE *inf, FILE *outf) { int cmd, k; cmd = getc(inf); while(cmd != EOF) { switch(cmd) { case MS_INTEGER_CONSTANT: fprintf(outf, "MS_INTEGER_CONSTANT "); get_null_terminated_string(inf,outf); break; case MS_REAL_CONSTANT: fprintf(outf, "MS_REAL_CONSTANT "); get_null_terminated_string(inf,outf); break; case MS_FUNCTION: fprintf(outf, "MS_FUNCTION "); get_null_terminated_string(inf,outf); fprintf(outf, "\n"); get_function_body(inf,outf); break; case MS_INTEGER_GLOBAL: fprintf(outf, "MS_INTEGER_GLOBAL"); break; case MS_REAL_GLOBAL: fprintf(outf, "MS_REAL_GLOBAL"); break; case MS_INTEGER_ARRAY_GLOBAL: k = getc(inf); fprintf(outf, "MS_INTEGER_ARRAY_GLOBAL %d", k); break; case MS_REAL_ARRAY_GLOBAL: k = getc(inf); fprintf(outf, "MS_REAL_ARRAY_GLOBAL %d", k); break; case MS_START: fprintf(outf, "MS_START "); get_null_terminated_string(inf,outf); break; default: fprintf(outf, "UNKNOWN SECTION HEADING %d", cmd); } fprintf(outf, "\n"); cmd = getc(inf); } } /************************************************************************ * MAIN * ************************************************************************/ int main(int argc, char **argv) { FILE *inf, *outf; if(argc != 3) { fprintf(stderr, "usage: disassemble file.m file.i\n"); return 1; } inf = fopen(argv[1], "rb"); if(inf == NULL) { fprintf(stderr, "Cannot open file %s for reading\n", argv[1]); return 1; } outf = fopen(argv[2], "w"); if(outf == NULL) { fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); return 1; } disassemble_sections(inf, outf); fclose(inf); fclose(outf); return 0; }