use clap::{Parser, Subcommand}; use disasm::Disassembler; use env_logger::Builder; use interpreter::interpreter::Interpreter; use std::io::Write; mod aout; mod disasm; mod disasm_macros; mod instructions; mod interpreter; mod operands; mod register; #[derive(Subcommand, Debug)] enum Command { /// Disassemble the binary into 8086 instructions Disasm, /// Interpret the 8086 instructions Interpret, } /// Simple program to disassemble and interpret 8086 a.out compilates, e.g. /// such for MINIX. #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { #[command(subcommand)] command: Command, /// Path of the binary #[arg(short, long, global = true)] path: Option, /// Dump progress of disassembly, in case of encountering an error. #[arg(short, long, global = true, action)] dump: bool, } fn main() { Builder::new() .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) .parse_default_env() .init(); let args = Args::parse(); log::debug!("{:?}", args); match args.command { Command::Disasm => { let mut disasm = Disassembler::new(&args); let instructions = disasm.disassemble(args.dump); match instructions { Ok(instrs) => instrs.iter().for_each(|i| println!("{i}")), _ => {} } } Command::Interpret => { let mut disasm = Disassembler::new(&args); let instructions = disasm.disassemble(args.dump); match instructions { Ok(instrs) => { let mut interpreter = Interpreter::new(instrs, disasm.aout.data); interpreter.interpret().unwrap(); } _ => {} } } } }