src/disass.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
#include <assert.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vm.h"
char *usage = "Usage: %s [-z] [-s [start_addr]] -i [vmcodefile]\n"
"-z (optional): don't display addresses next to disassembly\n"
"-s (optional): start disassembly at 'start_addr' in file\n"
"-i (required): path to file to disassemble\n";
/* TODO: eventually reimplement assembler in C (going to be annoying) */
/* disassemble_file:
*/
void disassemble_file(FILE *fp, bool show_addr, uint16_t start_addr)
{
uint8_t instr[3];
uint16_t start = start_addr;
if (start_addr)
fseek(fp, (long)start, SEEK_SET);
while(!feof(fp)) {
if(!fread(instr, 1, 3, fp))
break;
if(show_addr) {
printf("0x%04x: ", start);
start += 3;
}
print_op_decoded(instr, true);
}
/*// keep in case I ever want to read instructions from a static buffer
for (uint16_t i = 0; i < code_length / 3; i += 3) {
instr[0] = rom[i]; instr[1] = rom[i+1]; instr[2] = rom[i+2];
print_decoded(instr);
}*/
}
int main(int argc, char *argv[])
{
int opt;
bool show_addr = true; // show address of instructions
int start_addr = 0x00; // by default, assume code starts here
char infile[4096]; // if file path > 4096, I mean...
if (argc < 2) { // expect at least one argument
fprintf(stderr, usage, argv[0]);
return EXIT_FAILURE;
}
while ((opt = getopt(argc, argv, "zs:i:")) != -1) {
switch (opt) {
case 'z':
show_addr = false;
break;
case 's':
if (sscanf(optarg, "%i", &start_addr) == EOF) {
fprintf(stderr, usage, argv[0]);
return EXIT_FAILURE;
}
break;
case 'i':
strncpy(infile, optarg, 4096-1);
break;
case '?':
default:
fprintf(stderr, usage, argv[0]);
return EXIT_FAILURE;
}
}
if (optind > argc) {
fprintf(stderr, "Expected arguments after option -i\n");
return EXIT_FAILURE;
}
FILE *fp = fopen(infile, "rb");
if (fp == NULL) {
perror("fopen() failed...");
return EXIT_FAILURE;
}
// TODO: maybe write assembler in C also, but I'll probably write it in
// another lang for now
printf("start_addr: %d\n", start_addr);
disassemble_file(fp, show_addr, (uint16_t)start_addr);
fclose(fp);
return EXIT_SUCCESS;
}
|