Massively add to and improve disassembly logic. Make it beyond superior.
Improve the entire program. Add color add way better advanced logic. Go beyond. Make it as advanced as possible.
disassembler.rs:
use crate::instruction::{Instruction, Register, Operand};
use std::fmt;
use std::collections::{HashMap, HashSet};
use std::error::Error;

/// Opcode definitions for the instruction set.
mod opcodes {
    pub const LOAD: u8 = 0x01;
    pub const LOAD_ADDR: u8 = 0x02;
    pub const LOAD_MEM: u8 = 0x03;
    pub const STORE: u8 = 0x04;
    pub const STORE_MEM: u8 = 0x05;
    pub const ADD: u8 = 0x06;
    pub const ADDI: u8 = 0x07;
    pub const SUB: u8 = 0x08;
    pub const SUBI: u8 = 0x09;
    pub const MUL: u8 = 0x0A;
    pub const DIV: u8 = 0x0B;
    pub const AND: u8 = 0x0C;
    pub const OR: u8 = 0x0D;
    pub const XOR: u8 = 0x0E;
    pub const NOT: u8 = 0x0F;
    pub const SHL: u8 = 0x10;
    pub const SHR: u8 = 0x11;
    pub const MOV: u8 = 0x12;
    pub const MOVI: u8 = 0x13;
    pub const INC: u8 = 0x14;
    pub const DEC: u8 = 0x15;
    pub const JMP: u8 = 0x16;
    pub const CALL: u8 = 0x17;
    pub const RET: u8 = 0x18;
    pub const CMP: u8 = 0x19;
    pub const JE: u8 = 0x1A;
    pub const JNE: u8 = 0x1B;
    pub const PUSH: u8 = 0x1C;
    pub const POP: u8 = 0x1D;
    pub const PUSHF: u8 = 0x1E;
    pub const POPF: u8 = 0x1F;
    pub const NOP: u8 = 0x20;
    pub const HALT: u8 = 0x21;
    // Add more opcodes as needed...
}

use opcodes::*;

/// Represents the possible errors during disassembly.
#[derive(Debug, Clone)]
pub enum DisassembleError {
    /// Occurs when there are insufficient bytes to decode an instruction.
    UnexpectedEndOfData {
        address: usize,
        expected: usize,
        found: usize,
    },
    /// Occurs when an unknown opcode is encountered.
    UnknownOpcode {
        address: usize,
        opcode: u8,
    },
}

impl fmt::Display for DisassembleError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DisassembleError::UnexpectedEndOfData { address, expected, found } => {
                write!(
                    f,
                    "Unexpected end of data at address {}: expected {} bytes, found {}",
                    address, expected, found
                )
            }
            DisassembleError::UnknownOpcode { address, opcode } => {
                write!(
                    f,
                    "Unknown opcode 0x{:02X} encountered at address {}",
                    opcode, address
                )
            }
        }
    }
}

impl Error for DisassembleError {}

/// Represents a parsed instruction along with its address and size.
#[derive(Debug, Clone)]
pub struct ParsedInstruction {
    pub address: usize,
    pub instruction: Instruction,
    pub size: usize, // Number of bytes consumed
}

/// Decoding function type. Each opcode has an associated decoding function.
type DecodeFn = fn(&[u8], usize) -> Result<(Instruction, usize), DisassembleError>;

/// Lookup table mapping opcodes to their decoding functions.
fn get_opcode_table() -> [Option<DecodeFn>; 256] {
    // Initialize all entries to None
    let mut table: [Option<DecodeFn>; 256] = [None; 256];

    // Assign decoding functions to their respective opcodes
    table[LOAD as usize] = Some(decode_load);
    table[LOAD_ADDR as usize] = Some(decode_load_addr);
    table[LOAD_MEM as usize] = Some(decode_load_mem);
    table[STORE as usize] = Some(decode_store);
    table[STORE_MEM as usize] = Some(decode_store_mem);
    table[ADD as usize] = Some(decode_add);
    table[ADDI as usize] = Some(decode_addi);
    table[SUB as usize] = Some(decode_sub);
    table[SUBI as usize] = Some(decode_subi);
    table[MUL as usize] = Some(decode_mul);
    table[DIV as usize] = Some(decode_div);
    table[AND as usize] = Some(decode_and);
    table[OR as usize] = Some(decode_or);
    table[XOR as usize] = Some(decode_xor);
    table[NOT as usize] = Some(decode_not);
    table[SHL as usize] = Some(decode_shl);
    table[SHR as usize] = Some(decode_shr);
    table[MOV as usize] = Some(decode_mov);
    table[MOVI as usize] = Some(decode_movi);
    table[INC as usize] = Some(decode_inc);
    table[DEC as usize] = Some(decode_dec);
    table[JMP as usize] = Some(decode_jmp);
    table[CALL as usize] = Some(decode_call);
    table[RET as usize] = Some(decode_ret);
    table[CMP as usize] = Some(decode_cmp);
    table[JE as usize] = Some(decode_je);
    table[JNE as usize] = Some(decode_jne);
    table[PUSH as usize] = Some(decode_push);
    table[POP as usize] = Some(decode_pop);
    table[PUSHF as usize] = Some(decode_pushf);
    table[POPF as usize] = Some(decode_popf);
    table[NOP as usize] = Some(decode_nop);
    table[HALT as usize] = Some(decode_halt);

    table
}

/// Simple label resolver for addresses to labels.
/// Implements a two-pass disassembly process.
struct LabelResolver {
    labels: HashMap<u16, String>,
    resolved: bool,
}

impl LabelResolver {
    fn new() -> Self {
        Self {
            labels: HashMap::new(),
            resolved: false,
        }
    }

    /// Adds a label for the given address.
    fn add_label(&mut self, address: u16) {
        if !self.labels.contains_key(&address) {
            let label = format!("label_{:04X}", address);
            self.labels.insert(address, label);
        }
    }

    /// Retrieves the label for the given address, if it exists.
    fn get_label(&self, address: u16) -> Option<&String> {
        self.labels.get(&address)
    }
}

/// Disassembles binary data into a vector of parsed instructions.
///
/// # Arguments
///
/// * `data` - A slice of bytes representing the binary code.
///
/// # Returns
///
/// * A vector of `ParsedInstruction` structs or a disassembly error.
pub fn disassemble(data: &[u8]) -> Result<Vec<ParsedInstruction>, DisassembleError> {
    let opcode_table = get_opcode_table();
    let mut instructions = Vec::new();
    let mut pc = 0;

    // First pass: Identify all branch/call targets to generate labels
    let mut label_resolver = LabelResolver::new();
    let mut temp_pc = 0;
    while temp_pc < data.len() {
        let opcode = data[temp_pc];
        if let Some(decode_fn) = opcode_table[opcode as usize] {
            match decode_fn(data, temp_pc) {
                Ok((instr, bytes_consumed)) => {
                    match &instr {
                        Instruction::Jmp { address }
                        | Instruction::Je { address }
                        | Instruction::Jne { address }
                        | Instruction::Call { address } => {
                            label_resolver.add_label(*address);
                        }
                        _ => {}
                    }
                    temp_pc += bytes_consumed;
                }
                Err(_) => {
                    // Unknown opcode or incomplete data; skip to next byte
                    temp_pc += 1;
                }
            }
        } else {
            // Unknown opcode; skip to next byte
            temp_pc += 1;
        }
    }

    // Second pass: Actual disassembly with labels
    while pc < data.len() {
        let address = pc;
        let opcode = data[pc];
        if let Some(decode_fn) = opcode_table[opcode as usize] {
            match decode_fn(data, pc) {
                Ok((instruction, size)) => {
                    instructions.push(ParsedInstruction {
                        address,
                        instruction,
                        size,
                    });
                    pc += size;
                }
                Err(e) => {
                    // Handle error by inserting Unknown instruction and skipping one byte
                    instructions.push(ParsedInstruction {
                        address,
                        instruction: Instruction::Unknown {
                            opcode,
                            bytes: data[pc..].iter().copied().take(1).collect(),
                        },
                        size: 1,
                    });
                    pc += 1;
                }
            }
        } else {
            // Handle unknown opcode
            instructions.push(ParsedInstruction {
                address,
                instruction: Instruction::Unknown {
                    opcode,
                    bytes: data[pc..].iter().copied().take(1).collect(),
                },
                size: 1,
            });
            pc += 1;
        }
    }

    Ok(instructions)
}

/// Decodes the LOAD instruction.
/// Format: LOAD Register, Immediate
fn decode_load(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // LOAD is 1 byte opcode + 1 byte register + 2 bytes immediate
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    let imm = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    Ok((
        Instruction::Load {
            register: reg,
            value: imm,
        },
        expected_length,
    ))
}

/// Decodes the LOAD_ADDR instruction.
/// Format: LOAD Register, Address
fn decode_load_addr(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // LOAD_ADDR is 1 byte opcode + 1 byte register + 2 bytes address
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let address = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    let reg = decode_register(reg_code);
    Ok((
        Instruction::LoadAddress {
            register: reg,
            address,
        },
        expected_length,
    ))
}

/// Decodes the LOAD_MEM instruction.
/// Format: LOAD Register, Memory
fn decode_load_mem(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // LOAD_MEM is 1 byte opcode + 1 byte register + 1 byte base register + 2 bytes displacement
    let expected_length = 5;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let base_code = data[pc + 2];
    let disp = i16::from_be_bytes([data[pc + 3], data[pc + 4]]);
    let reg = decode_register(reg_code);
    let base = decode_register(base_code);
    let memory = Operand::Memory {
        base,
        displacement: disp,
    };
    Ok((
        Instruction::LoadMemory {
            register: reg,
            memory,
        },
        expected_length,
    ))
}

/// Decodes the STORE instruction.
/// Format: STORE Register, Address
fn decode_store(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // STORE is 1 byte opcode + 1 byte register + 2 bytes address
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let address = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Store {
            register: reg,
            address,
        },
        expected_length,
    ))
}

/// Decodes the STORE_MEM instruction.
/// Format: STORE Register, Memory
fn decode_store_mem(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // STORE_MEM is 1 byte opcode + 1 byte register + 1 byte base register + 2 bytes displacement
    let expected_length = 5;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let base_code = data[pc + 2];
    let disp = i16::from_be_bytes([data[pc + 3], data[pc + 4]]);
    let reg = decode_register(reg_code);
    let base = decode_register(base_code);
    let memory = Operand::Memory {
        base,
        displacement: disp,
    };
    Ok((
        Instruction::StoreMemory {
            register: reg,
            memory,
        },
        expected_length,
    ))
}

/// Decodes the ADD instruction.
/// Format: ADD Register, Register
fn decode_add(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // ADD is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Add { dest, src },
        expected_length,
    ))
}

/// Decodes the ADDI instruction.
/// Format: ADDI Register, Immediate
fn decode_addi(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // ADDI is 1 byte opcode + 1 byte dest + 2 bytes immediate
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let imm = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    let dest = decode_register(dest_code);
    Ok((
        Instruction::AddImmediate {
            dest,
            value: imm,
        },
        expected_length,
    ))
}

/// Decodes the SUB instruction.
/// Format: SUB Register, Register
fn decode_sub(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Sub { dest, src },
        expected_length,
    ))
}

/// Decodes the SUBI instruction.
/// Format: SUBI Register, Immediate
fn decode_subi(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADDI
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let imm = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    let dest = decode_register(dest_code);
    Ok((
        Instruction::SubImmediate {
            dest,
            value: imm,
        },
        expected_length,
    ))
}

/// Decodes the MUL instruction.
/// Format: MUL Register, Register
fn decode_mul(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Mul { dest, src },
        expected_length,
    ))
}

/// Decodes the DIV instruction.
/// Format: DIV Register, Register
fn decode_div(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Div { dest, src },
        expected_length,
    ))
}

/// Decodes the AND instruction.
/// Format: AND Register, Register
fn decode_and(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::And { dest, src },
        expected_length,
    ))
}

/// Decodes the OR instruction.
/// Format: OR Register, Register
fn decode_or(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Or { dest, src },
        expected_length,
    ))
}

/// Decodes the XOR instruction.
/// Format: XOR Register, Register
fn decode_xor(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // Similar to ADD
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Xor { dest, src },
        expected_length,
    ))
}

/// Decodes the NOT instruction.
/// Format: NOT Register
fn decode_not(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // NOT is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Not { register: reg },
        expected_length,
    ))
}

/// Decodes the SHL instruction.
/// Format: SHL Register, Immediate
fn decode_shl(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // SHL is 1 byte opcode + 1 byte register + 1 byte shift amount
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let shift = data[pc + 2];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Shl {
            register: reg,
            shift,
        },
        expected_length,
    ))
}

/// Decodes the SHR instruction.
/// Format: SHR Register, Immediate
fn decode_shr(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // SHR is 1 byte opcode + 1 byte register + 1 byte shift amount
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let shift = data[pc + 2];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Shr {
            register: reg,
            shift,
        },
        expected_length,
    ))
}

/// Decodes the MOV instruction.
/// Format: MOV Register, Register
fn decode_mov(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // MOV is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Mov { dest, src },
        expected_length,
    ))
}

/// Decodes the MOVI instruction.
/// Format: MOVI Register, Immediate
fn decode_movi(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // MOVI is 1 byte opcode + 1 byte dest + 2 bytes immediate
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let dest_code = data[pc + 1];
    let imm = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    let dest = decode_register(dest_code);
    Ok((
        Instruction::MovImmediate {
            dest,
            value: imm,
        },
        expected_length,
    ))
}

/// Decodes the INC instruction.
/// Format: INC Register
fn decode_inc(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // INC is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Inc { register: reg },
        expected_length,
    ))
}

/// Decodes the DEC instruction.
/// Format: DEC Register
fn decode_dec(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // DEC is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Dec { register: reg },
        expected_length,
    ))
}

/// Decodes the JMP instruction.
/// Format: JMP Address
fn decode_jmp(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JMP is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Jmp { address: addr },
        expected_length,
    ))
}

/// Decodes the CALL instruction.
/// Format: CALL Address
fn decode_call(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // CALL is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Call { address: addr },
        expected_length,
    ))
}

/// Decodes the RET instruction.
/// Format: RET
fn decode_ret(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // RET is 1 byte opcode
    Ok((Instruction::Ret, 1))
}

/// Decodes the CMP instruction.
/// Format: CMP Register, Register
fn decode_cmp(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // CMP is 1 byte opcode + 1 byte reg1 + 1 byte reg2
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg1_code = data[pc + 1];
    let reg2_code = data[pc + 2];
    let reg1 = decode_register(reg1_code);
    let reg2 = decode_register(reg2_code);
    Ok((
        Instruction::Cmp { reg1, reg2 },
        expected_length,
    ))
}

/// Decodes the JE instruction.
/// Format: JE Address
fn decode_je(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JE is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Je { address: addr },
        expected_length,
    ))
}

/// Decodes the JNE instruction.
/// Format: JNE Address
fn decode_jne(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JNE is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Jne { address: addr },
        expected_length,
    ))
}

/// Decodes the PUSH instruction.
/// Format: PUSH Register
fn decode_push(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // PUSH is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Push { register: reg },
        expected_length,
    ))
}

/// Decodes the POP instruction.
/// Format: POP Register
fn decode_pop(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // POP is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }

    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Pop { register: reg },
        expected_length,
    ))
}

/// Decodes the PUSHF instruction.
/// Format: PUSHF
fn decode_pushf(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // PUSHF is 1 byte opcode
    Ok((Instruction::Pushf, 1))
}

/// Decodes the POPF instruction.
/// Format: POPF
fn decode_popf(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // POPF is 1 byte opcode
    Ok((Instruction::Popf, 1))
}

/// Decodes the NOP instruction.
/// Format: NOP
fn decode_nop(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // NOP is 1 byte opcode
    Ok((Instruction::Nop, 1))
}

/// Decodes the HALT instruction.
/// Format: HALT
fn decode_halt(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // HALT is 1 byte opcode
    Ok((Instruction::Halt, 1))
}

/// Decodes a register code into a `Register` enum.
///
/// # Arguments
///
/// * `code` - The register code as a `u8`.
///
/// # Returns
///
/// * A `Register` enum variant.
fn decode_register(code: u8) -> Register {
    match code {
        0x00 => Register::R0,
        0x01 => Register::R1,
        0x02 => Register::R2,
        0x03 => Register::R3,
        0x04 => Register::R4,
        0x05 => Register::R5,
        0x06 => Register::R6,
        0x07 => Register::R7,
        unknown => Register::Unknown(unknown),
    }
}

/// Formats the disassembled instructions with labels.
///
/// # Arguments
///
/// * `instructions` - A slice of `ParsedInstruction` structs.
///
/// # Returns
///
/// * A formatted string representing the disassembled code.
pub fn format_disassembly(instructions: &[ParsedInstruction]) -> String {
    let mut output = String::new();
    let mut label_map: HashMap<u16, String> = HashMap::new();

    // First pass: Collect labels
    for instr in instructions {
        match &instr.instruction {
            Instruction::Jmp { address }
            | Instruction::Je { address }
            | Instruction::Jne { address }
            | Instruction::Call { address } => {
                if !label_map.contains_key(address) {
                    let label = format!("label_{:04X}", address);
                    label_map.insert(*address, label);
                }
            }
            _ => {}
        }
    }

    // Second pass: Print instructions with labels
    for instr in instructions {
        // Check if current address has a label
        if let Some(label) = label_map.get(&(instr.address as u16)) {
            output.push_str(&format!("{}:\n", label));
        }
        // Format instruction
        output.push_str(&format!("    {}    ; 0x{:04X}\n", instr.instruction, instr.address));
    }

    output
}

instruction.rs:
use std::fmt;

/// Defines the CPU registers.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Register {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    // Additional registers can be added here
    Unknown(u8),
}

impl fmt::Display for Register {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Register::R0 => write!(f, "R0"),
            Register::R1 => write!(f, "R1"),
            Register::R2 => write!(f, "R2"),
            Register::R3 => write!(f, "R3"),
            Register::R4 => write!(f, "R4"),
            Register::R5 => write!(f, "R5"),
            Register::R6 => write!(f, "R6"),
            Register::R7 => write!(f, "R7"),
            Register::Unknown(code) => write!(f, "R{}", code),
        }
    }
}

/// Defines various operand types for instructions.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operand {
    Register(Register),
    Immediate(u16),
    Address(u16),
    Memory {
        base: Register,
        displacement: i16,
    },
    Indirect {
        register: Register,
    },
    // Future extensions can include more complex operands
}

impl fmt::Display for Operand {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Operand::Register(reg) => write!(f, "{}", reg),
            Operand::Immediate(val) => write!(f, "0x{:04X}", val),
            Operand::Address(addr) => write!(f, "0x{:04X}", addr),
            Operand::Memory { base, displacement } => {
                if *displacement == 0 {
                    write!(f, "[{}]", base)
                } else {
                    write!(f, "[{} + {}]", base, displacement)
                }
            }
            Operand::Indirect { register } => write!(f, "*{}", register),
        }
    }
}

/// Defines the complete set of instructions supported by the CPU.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instruction {
    /// LOAD Register, Immediate
    Load { register: Register, value: u16 },
    /// LOAD Register, Address
    LoadAddress { register: Register, address: u16 },
    /// LOAD Register, Memory
    LoadMemory {
        register: Register,
        memory: Operand,
    },
    /// STORE Register, Address
    Store { register: Register, address: u16 },
    /// STORE Register, Memory
    StoreMemory {
        register: Register,
        memory: Operand,
    },
    /// ADD Register, Register
    Add { dest: Register, src: Register },
    /// ADD Register, Immediate
    AddImmediate { dest: Register, value: u16 },
    /// SUB Register, Register
    Sub { dest: Register, src: Register },
    /// SUB Register, Immediate
    SubImmediate { dest: Register, value: u16 },
    /// MUL Register, Register
    Mul { dest: Register, src: Register },
    /// DIV Register, Register
    Div { dest: Register, src: Register },
    /// AND Register, Register
    And { dest: Register, src: Register },
    /// OR Register, Register
    Or { dest: Register, src: Register },
    /// XOR Register, Register
    Xor { dest: Register, src: Register },
    /// NOT Register
    Not { register: Register },
    /// SHL Register, Immediate
    Shl { register: Register, shift: u8 },
    /// SHR Register, Immediate
    Shr { register: Register, shift: u8 },
    /// MOV Register, Register
    Mov { dest: Register, src: Register },
    /// MOV Register, Immediate
    MovImmediate { dest: Register, value: u16 },
    /// INC Register
    Inc { register: Register },
    /// DEC Register
    Dec { register: Register },
    /// JMP Address
    Jmp { address: u16 },
    /// CALL Address
    Call { address: u16 },
    /// RET
    Ret,
    /// CMP Register, Register
    Cmp { reg1: Register, reg2: Register },
    /// JE Address
    Je { address: u16 },
    /// JNE Address
    Jne { address: u16 },
    /// PUSH Register
    Push { register: Register },
    /// POP Register
    Pop { register: Register },
    /// PUSHF
    Pushf,
    /// POPF
    Popf,
    /// NOP
    Nop,
    /// HALT
    Halt,
    /// UNKNOWN or invalid instruction
    Unknown { opcode: u8, bytes: Vec<u8> },
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Instruction::Load { register, value } => write!(f, "LOAD {}, {}", register, value),
            Instruction::LoadAddress { register, address } => {
                write!(f, "LOAD {}, {}", register, address)
            }
            Instruction::LoadMemory { register, memory } => {
                write!(f, "LOAD {}, {}", register, memory)
            }
            Instruction::Store { register, address } => write!(f, "STORE {}, {}", register, address),
            Instruction::StoreMemory { register, memory } => {
                write!(f, "STORE {}, {}", register, memory)
            }
            Instruction::Add { dest, src } => write!(f, "ADD {}, {}", dest, src),
            Instruction::AddImmediate { dest, value } => write!(f, "ADDI {}, {}", dest, value),
            Instruction::Sub { dest, src } => write!(f, "SUB {}, {}", dest, src),
            Instruction::SubImmediate { dest, value } => write!(f, "SUBI {}, {}", dest, value),
            Instruction::Mul { dest, src } => write!(f, "MUL {}, {}", dest, src),
            Instruction::Div { dest, src } => write!(f, "DIV {}, {}", dest, src),
            Instruction::And { dest, src } => write!(f, "AND {}, {}", dest, src),
            Instruction::Or { dest, src } => write!(f, "OR {}, {}", dest, src),
            Instruction::Xor { dest, src } => write!(f, "XOR {}, {}", dest, src),
            Instruction::Not { register } => write!(f, "NOT {}", register),
            Instruction::Shl { register, shift } => write!(f, "SHL {}, {}", register, shift),
            Instruction::Shr { register, shift } => write!(f, "SHR {}, {}", register, shift),
            Instruction::Mov { dest, src } => write!(f, "MOV {}, {}", dest, src),
            Instruction::MovImmediate { dest, value } => write!(f, "MOVI {}, {}", dest, value),
            Instruction::Inc { register } => write!(f, "INC {}", register),
            Instruction::Dec { register } => write!(f, "DEC {}", register),
            Instruction::Jmp { address } => write!(f, "JMP {}", address),
            Instruction::Call { address } => write!(f, "CALL {}", address),
            Instruction::Ret => write!(f, "RET"),
            Instruction::Cmp { reg1, reg2 } => write!(f, "CMP {}, {}", reg1, reg2),
            Instruction::Je { address } => write!(f, "JE {}", address),
            Instruction::Jne { address } => write!(f, "JNE {}", address),
            Instruction::Push { register } => write!(f, "PUSH {}", register),
            Instruction::Pop { register } => write!(f, "POP {}", register),
            Instruction::Pushf => write!(f, "PUSHF"),
            Instruction::Popf => write!(f, "POPF"),
            Instruction::Nop => write!(f, "NOP"),
            Instruction::Halt => write!(f, "HALT"),
            Instruction::Unknown { opcode, bytes } => {
                write!(f, "UNKNOWN 0x{:02X} {:?}", opcode, bytes)
            }
        }
    }
}
parser.rs:
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

/// Reads a binary file and returns its content as a vector of bytes.
///
/// # Arguments
///
/// * `path` - The file path to read.
///
/// # Returns
///
/// * `Ok(Vec<u8>)` containing the file's bytes if successful.
/// * `Err(io::Error)` if an error occurs during file operations.
pub fn read_binary<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
    let file = File::open(path)?;
    let metadata = file.metadata()?;
    let file_size = metadata.len() as usize;
    let mut buffer = Vec::with_capacity(file_size);
    file.take(file_size as u64).read_to_end(&mut buffer)?;
    Ok(buffer)
}

/// Utility functions for reading multi-byte values from a byte slice.
pub mod utilities {
    /// Reads a little-endian u16 from the given byte slice at the specified offset.
    ///
    /// # Arguments
    ///
    /// * `data` - The byte slice.
    /// * `offset` - The starting index.
    ///
    /// # Returns
    ///
    /// * `Some(u16)` if successful.
    /// * `None` if there aren't enough bytes.
    pub fn read_u16_le(data: &[u8], offset: usize) -> Option<u16> {
        if offset + 1 < data.len() {
            Some(u16::from_le_bytes([data[offset], data[offset + 1]]))
        } else {
            None
        }
    }

    /// Reads a big-endian u16 from the given byte slice at the specified offset.
    ///
    /// # Arguments
    ///
    /// * `data` - The byte slice.
    /// * `offset` - The starting index.
    ///
    /// # Returns
    ///
    /// * `Some(u16)` if successful.
    /// * `None` if there aren't enough bytes.
    pub fn read_u16_be(data: &[u8], offset: usize) -> Option<u16> {
        if offset + 1 < data.len() {
            Some(u16::from_be_bytes([data[offset], data[offset + 1]]))
        } else {
            None
        }
    }

    /// Reads a little-endian i16 from the given byte slice at the specified offset.
    ///
    /// # Arguments
    ///
    /// * `data` - The byte slice.
    /// * `offset` - The starting index.
    ///
    /// # Returns
    ///
    /// * `Some(i16)` if successful.
    /// * `None` if there aren't enough bytes.
    pub fn read_i16_le(data: &[u8], offset: usize) -> Option<i16> {
        if offset + 1 < data.len() {
            Some(i16::from_le_bytes([data[offset], data[offset + 1]]))
        } else {
            None
        }
    }

    /// Reads a little-endian u32 from the given byte slice at the specified offset.
    ///
    /// # Arguments
    ///
    /// * `data` - The byte slice.
    /// * `offset` - The starting index.
    ///
    /// # Returns
    ///
    /// * `Some(u32)` if successful.
    /// * `None` if there aren't enough bytes.
    pub fn read_u32_le(data: &[u8], offset: usize) -> Option<u32> {
        if offset + 3 < data.len() {
            Some(u32::from_le_bytes([
                data[offset],
                data[offset + 1],
                data[offset + 2],
                data[offset + 3],
            ]))
        } else {
            None
        }
    }

    // Add more utility functions as needed...
}
main.rs:
mod disassembler;
mod instruction;
mod parser;

use crate::disassembler::disassemble;
use crate::instruction::Instruction;
use std::env;
use std::fmt;
use std::path::Path;

/// Represents a label in the disassembled code.
#[derive(Debug, Clone)]
struct Label {
    address: u16,
    name: String,
}

impl fmt::Display for Label {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:", self.name)
    }
}

fn main() {
    // Collect command-line arguments
    let args: Vec<String> = env::args().collect();

    if args.len() != 2 {
        eprintln!("Usage: {} <binary_file>", args[0]);
        std::process::exit(1);
    }

    let binary_path = &args[1];
    let path = Path::new(binary_path);

    // Read binary data
    let data = match parser::read_binary(path) {
        Ok(bytes) => bytes,
        Err(e) => {
            eprintln!("Failed to read file {}: {}", binary_path, e);
            std::process::exit(1);
        }
    };

    // Disassemble the binary data
    let parsed_instructions = disassemble(&data);
    // Identify jump addresses to create labels
    let labels = identify_labels(&parsed_instructions.as_ref().unwrap());

    // Print disassembled instructions with labels
    for instr in parsed_instructions.as_ref().unwrap() {
        if let Some(label) = labels.get(&(instr.address as usize)) {
            println!("{}", label);
        }
        println!("{:04X}: {}", instr.address, instr.instruction);
    }
}

/// Identifies all addresses that are targets of jump instructions and assigns labels.
///
/// # Arguments
///
/// * `instructions` - A slice of `ParsedInstruction` structs.
///
/// # Returns
///
/// * A `HashMap` mapping addresses to label names.
fn identify_labels(instructions: &[disassembler::ParsedInstruction]) -> std::collections::HashMap<usize, String> {
    let mut labels = std::collections::HashMap::new();
    let mut label_count = 0;

    for instr in instructions {
        match &instr.instruction {
            Instruction::Jmp { address }
            | Instruction::Je { address }
            | Instruction::Jne { address } => {
                if !labels.contains_key(&(*address as usize)) {
                    let label = format!("LABEL_{}", label_count);
                    labels.insert(*address as usize, label);
                    label_count += 1;
                }
            }
            _ => {}
        }
    }

    labels
}