all repos — 3ByteBadVM @ 1c8605952f985718532c998f9b042a08bf011628

3ByteBadVM

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
 100
 101
 102
/* x1phosura 2021 */

#include <assert.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "vm.h"
#include "emcalls.h"


char *usage = "Usage: %s [-z] [-s [start_addr]] -f [vmcodefile]\n"
              "-z (optional): don't display addresses next to disassembly\n"
	      "-s (optional): start disassembly at 'start_addr' in file\n"
	      "-f (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:f:")) != -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 'f':
				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;
}