disassembler.rs:
use crate::instruction::Instruction;
use crate::parser::utilities::{
    read_i16_le, read_i32_le, read_i8, read_u16_le, read_u32_le, read_u8,
};
use colored::*;

pub fn disassemble(data: &[u8]) -> Result<Vec<Instruction>, String> {
    let mut instructions = Vec::new();
    let mut offset = 0;

    while offset < data.len() {
        let (instruction, size) = decode_instruction(data, offset)?;
        instructions.push(instruction);
        offset += size;
    }

    Ok(instructions)
}

fn decode_instruction(data: &[u8], offset: usize) -> Result<(Instruction, usize), String> {
    if offset >= data.len() {
        return Err("Unexpected end of data".to_string());
    }

    let mut current_offset = offset;
    let mut prefixes = Vec::new();

    // Handle prefixes (e.g., LOCK, REP, etc.)
    while current_offset < data.len() && is_prefix(data[current_offset]) {
        prefixes.push(data[current_offset]);
        current_offset += 1;
    }

    if !prefixes.is_empty() && current_offset >= data.len() {
        // Instruction ends with prefix, which is invalid
        println!("Current offset: {}", current_offset);
        println!("Data length: {}", data.len());
        println!(
            "Last Prefix: {:02X}",
            prefixes.last().unwrap()
        );
        return Err("Unexpected end of data after prefix".to_string());
    }


    if current_offset >= data.len() {
        return Err("Unexpected end of data in instruction".to_string());
    }

    let opcode = data[current_offset];
    let (mnemonic, operands, size) = match opcode {
        0x00 => (
            "ADD".to_string(),
            vec!["BYTE PTR [EAX]".to_string(), "AL".to_string()],
            1,
        ),
        0x01 => (
            "ADD".to_string(),
            vec!["DWORD PTR [EAX]".to_string(), "EAX".to_string()],
            1,
        ),
        0x03 => (
            "ADD".to_string(),
            vec!["EAX".to_string(), "DWORD PTR [EAX]".to_string()],
            1,
        ),
        0x05 => {
            let imm = read_u32_le(data, current_offset + 1)
                .ok_or("Unexpected end of data for ADD immediate")?;
            (
                "ADD".to_string(),
                vec!["EAX".to_string(), format!("0x{:X}", imm)],
                5,
            )
        }
        0x0F => return decode_two_byte_opcode(data, current_offset),
        0x20..=0x23 => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("AND".to_string(), vec![dst, src], 2)
        }
        0x28..=0x2B => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("SUB".to_string(), vec![dst, src], 2)
        }
        0x30..=0x33 => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("XOR".to_string(), vec![dst, src], 2)
        }
        0x38..=0x3B => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("CMP".to_string(), vec![dst, src], 2)
        }
        0x40..=0x47 => {
            let reg = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"]
                [opcode as usize - 0x40];
            ("INC".to_string(), vec![reg.to_string()], 1)
        }
        0x48..=0x4F => {
            let reg = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"]
                [opcode as usize - 0x48];
            ("DEC".to_string(), vec![reg.to_string()], 1)
        }
        0x50..=0x57 => {
            let reg = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"]
                [opcode as usize - 0x50];
            ("PUSH".to_string(), vec![reg.to_string()], 1)
        }
        0x58..=0x5F => {
            let reg = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"]
                [opcode as usize - 0x58];
            ("POP".to_string(), vec![reg.to_string()], 1)
        }
        0x68 => {
            let imm = read_u32_le(data, current_offset + 1)
                .ok_or("Unexpected end of data for PUSH immediate")?;
            ("PUSH".to_string(), vec![format!("0x{:X}", imm)], 5)
        }
        0x6A => {
            let imm = read_i8(data, current_offset + 1)
                .ok_or("Unexpected end of data for PUSH imm8")?;
            ("PUSH".to_string(), vec![format!("0x{:X}", imm)], 2)
        }
        0x70..=0x7F => {
            let disp = read_i8(data, current_offset + 1)
                .ok_or("Unexpected end of data for jump displacement")?;
            let condition = match opcode {
                0x70 => "JO",
                0x71 => "JNO",
                0x72 => "JB",
                0x73 => "JNB",
                0x74 => "JE",
                0x75 => "JNE",
                0x76 => "JBE",
                0x77 => "JA",
                0x78 => "JS",
                0x79 => "JNS",
                0x7A => "JP",
                0x7B => "JNP",
                0x7C => "JL",
                0x7D => "JGE",
                0x7E => "JLE",
                0x7F => "JG",
                _ => unreachable!(),
            };
            (condition.to_string(), vec![format!("${:+}", disp)], 2)
        }
        0x80 | 0x81 | 0x83 => {
            let (dst, src, size) = decode_immediate_arithmetic(data, current_offset)?;
            ("ADD".to_string(), vec![dst, src], size)
        }
        0x84 | 0x85 => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("TEST".to_string(), vec![dst, src], 2)
        }
        0x88..=0x8B => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("MOV".to_string(), vec![dst, src], 2)
        }
        0x8D => {
            let (src, dst) = decode_modrm(data, current_offset + 1)?;
            ("LEA".to_string(), vec![dst, src], 2)
        }
        0x90 => ("NOP".to_string(), vec![], 1),
        0xB0..=0xB7 => {
            let reg = ["AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"][opcode as usize - 0xB0];
            let imm = data[current_offset + 1];
            ("MOV".to_string(), vec![reg.to_string(), format!("0x{:X}", imm)], 2)
        }
        0xB8..=0xBF => {
            let reg = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"]
                [opcode as usize - 0xB8];
            let imm = read_u32_le(data, current_offset + 1)
                .ok_or("Unexpected end of data for MOV immediate")?;
            ("MOV".to_string(), vec![reg.to_string(), format!("0x{:X}", imm)], 5)
        }
        0xC3 => ("RET".to_string(), vec![], 1),
        0xC7 => {
            let (dst, _) = decode_modrm(data, current_offset + 1)?;
            let imm = read_u32_le(data, current_offset + 2)
                .ok_or("Unexpected end of data for MOV imm32")?;
            ("MOV".to_string(), vec![dst, format!("0x{:X}", imm)], 6)
        }
        0xE8 => {
            let disp = read_i32_le(data, current_offset + 1)
                .ok_or("Unexpected end of data for CALL")?;
            ("CALL".to_string(), vec![format!("${:+}", disp)], 5)
        }
        0xE9 => {
            let disp = read_i32_le(data, current_offset + 1)
                .ok_or("Unexpected end of data for JMP")?;
            ("JMP".to_string(), vec![format!("${:+}", disp)], 5)
        }
        0xEB => {
            let disp = read_i8(data, current_offset + 1)
                .ok_or("Unexpected end of data for JMP SHORT")?;
            ("JMP SHORT".to_string(), vec![format!("${:+}", disp)], 2)
        }
        0xF0 => { // LOCK prefix handling
            if current_offset + 1 >= data.len() {
                return Err("Unexpected end of data after LOCK prefix".to_string());
            }
            let next_opcode = data[current_offset + 1];
            match next_opcode {
                0x01 => { // ADD with LOCK
                    let (src, dst) = decode_modrm(data, current_offset + 2)?;
                    ("LOCK ADD".to_string(), vec![dst, src], 3)
                }
                0x29 => { // SUB with LOCK
                    let (src, dst) = decode_modrm(data, current_offset + 2)?;
                    ("LOCK SUB".to_string(), vec![dst, src], 3)
                }
                0x90 => { // LOCK NOP
                    ("LOCK NOP".to_string(), vec![], 2)
                }
                // Add more LOCK-prefixed instructions as needed
                _ => (
                    format!("LOCK OP 0x{:02X}", next_opcode),
                    vec![],
                    2,
                ),
            }
        }
        0xFF => {
            if current_offset + 1 >= data.len() {
                return Err("Unexpected end of data for FF opcode".to_string());
            }
            match data[current_offset + 1] & 0x38 {
                0x10 => (
                    "CALL".to_string(),
                    vec!["DWORD PTR [EAX]".to_string()],
                    2,
                ),
                0x20 => (
                    "JMP".to_string(),
                    vec!["DWORD PTR [EAX]".to_string()],
                    2,
                ),
                0x30 => (
                    "PUSH".to_string(),
                    vec!["DWORD PTR [EAX]".to_string()],
                    2,
                ),
                _ => (
                    format!("DB 0x{:02X}", opcode),
                    vec![],
                    1,
                ),
            }
        }
        _ => (format!("DB 0x{:02X}", opcode), vec![], 1),
    };


    let end = current_offset + size;
    if end > data.len() {
        return Err("Instruction size goes beyond data length".to_string());
    }

    let instruction = Instruction {
        opcode: opcode,
        mnemonic,
        operands,
        bytes: data[current_offset..end].to_vec(),
        address: current_offset,
    };

    Ok((instruction, size))
}


fn decode_two_byte_opcode(
    data: &[u8],
    offset: usize,
) -> Result<(Instruction, usize), String> {
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data in two-byte opcode".to_string());
    }
    let second_byte = data[offset + 1];
    match second_byte {
        0x84 => { // JE rel32
            let disp = read_i32_le(data, offset + 2)
                .ok_or("Unexpected end of data for JE rel32")?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "JE".to_string(),
                    operands: vec![format!("${:+}", disp)],
                    bytes: data[offset..offset + 6].to_vec(),
                    address: offset,
                },
                6,
            ))
        }
        0x85 => { // JNE rel32
            let disp = read_i32_le(data, offset + 2)
                .ok_or("Unexpected end of data for JNE rel32")?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "JNE".to_string(),
                    operands: vec![format!("${:+}", disp)],
                    bytes: data[offset..offset + 6].to_vec(),
                    address: offset,
                },
                6,
            ))
        }
        0xAF => { // IMUL r32, r/m32, imm8
            let (src, dst) = decode_modrm(data, offset + 2)?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "IMUL".to_string(),
                    operands: vec![dst, src],
                    bytes: data[offset..offset + 3].to_vec(),
                    address: offset,
                },
                3,
            ))
        }
        0xB6 => { // MOVZX r32, r/m8
            let (src, dst) = decode_modrm(data, offset + 2)?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "MOVZX".to_string(),
                    operands: vec![dst, src],
                    bytes: data[offset..offset + 3].to_vec(),
                    address: offset,
                },
                3,
            ))
        }
        0xB7 => { // MOVZX r32, r/m16
            let (src, dst) = decode_modrm(data, offset + 2)?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "MOVZX".to_string(),
                    operands: vec![dst, src],
                    bytes: data[offset..offset + 3].to_vec(),
                    address: offset,
                },
                3,
            ))
        }
        0xC1 => { // SAR r/m32, imm8
            let (src, dst) = decode_modrm(data, offset + 2)?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "SAR".to_string(),
                    operands: vec![dst, src],
                    bytes: data[offset..offset + 3].to_vec(),
                    address: offset,
                },
                3,
            ))
        }
        0xC7 => { // MOV r/m32, imm32
            let (src, dst) = decode_modrm(data, offset + 2)?;
            let imm = read_u32_le(data, offset + 3)
                .ok_or("Unexpected end of data for MOV r/m32, imm32")?;
            Ok((
                Instruction {
                    opcode: 0x0F,
                    mnemonic: "MOV".to_string(),
                    operands: vec![dst, format!("0x{:X}", imm)],
                    bytes: data[offset..offset + 7].to_vec(),
                    address: offset,
                },
                7,
            ))
        }
        // Add more two-byte opcodes here as needed
        _ => Ok((
            Instruction {
                opcode: 0x0F,
                mnemonic: format!("DB 0x0F 0x{:02X}", second_byte),
                operands: vec![],
                bytes: data[offset..offset + 2].to_vec(),
                address: offset,
            },
            2,
        )),
    }
}

fn decode_modrm(data: &[u8], offset: usize) -> Result<(String, String), String> {
    if offset >= data.len() {
        return Err("Unexpected end of data in MODRM".to_string());
    }
    let modrm = data[offset];
    let mod_bits = modrm >> 6;
    let reg = (modrm >> 3) & 0x07;
    let rm = modrm & 0x07;

    let reg_str = [
        "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI",
    ][reg as usize]
    .to_string();

    let rm_str = match mod_bits {
        0b00 => {
            if rm == 0b100 {
                decode_sib(data, offset + 1)?
            } else if rm == 0b101 {
                let disp = read_i32_le(data, offset + 1)
                    .ok_or("Unexpected end of data for MODRM disp32")?;
                format!("[0x{:X}]", disp)
            } else {
                format!(
                    "[{}]",
                    ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"][rm as usize]
                )
            }
        }
        0b01 => {
            let disp = read_i8(data, offset + 1)
                .ok_or("Unexpected end of data for MODRM disp8")?;
            if rm == 0b100 {
                let sib = decode_sib(data, offset + 2)?;
                format!("[{} + {}]", sib, disp)
            } else {
                format!(
                    "[{} + {}]",
                    ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"][rm as usize],
                    disp
                )
            }
        }
        0b10 => {
            let disp = read_i32_le(data, offset + 1)
                .ok_or("Unexpected end of data for MODRM disp32")?;
            if rm == 0b100 {
                let sib = decode_sib(data, offset + 5)?;
                format!("[{} + {}]", sib, disp)
            } else {
                format!(
                    "[{} + {}]",
                    ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"][rm as usize],
                    disp
                )
            }
        }
        0b11 => [
            "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI",
        ][rm as usize]
        .to_string(),
        _ => unreachable!(),
    };

    Ok((reg_str, rm_str))
}


fn decode_sib(data: &[u8], offset: usize) -> Result<String, String> {
    if offset >= data.len() {
        return Err("Unexpected end of data in SIB".to_string());
    }
    let sib = data[offset];
    let scale = match (sib >> 6) & 0x03 {
        0 => 1,
        1 => 2,
        2 => 4,
        3 => 8,
        _ => unreachable!(),
    };
    let index = (sib >> 3) & 0x07;
    let base = sib & 0x07;

    let index_str = if index != 0b100 {
        format!(
            "{} * {}",
            ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"][index as usize],
            scale
        )
    } else {
        String::new()
    };

    let base_str = match base {
        0b101 => {
            let disp = read_i32_le(data, offset + 1)
                .ok_or("Unexpected end of data for SIB disp32")?;
            format!("[0x{:X}]", disp)
        }
        _ => format!(
            "[{}]",
            ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"][base as usize]
        ),
    };

    if index_str.is_empty() {
        Ok(base_str)
    } else {
        Ok(format!(
            "[{} + {}]",
            base_str.trim_start_matches('[').trim_end_matches(']'),
            index_str
        ))
    }
}

fn decode_immediate_arithmetic(
    data: &[u8],
    offset: usize,
) -> Result<(String, String, usize), String> {
    let opcode = data[offset];
    let (dst, _) = decode_modrm(data, offset + 1)?;
    let (imm_str, size) = match opcode {
        0x80 | 0x82 => {
            let imm8 = read_i8(data, offset + 2)
                .ok_or("Unexpected end of data for immediate arithmetic (imm8)")?;
            (format!("0x{:X}", imm8), 3)
        }
        0x81 => {
            let imm32 = read_i32_le(data, offset + 2)
                .ok_or("Unexpected end of data for immediate arithmetic (imm32)")?;
            (format!("0x{:X}", imm32), 6)
        }
        0x83 => {
            let imm8 = read_i8(data, offset + 2)
                .ok_or("Unexpected end of data for immediate arithmetic (imm8)")?;
            (format!("0x{:X}", imm8), 3)
        }
        _ => unreachable!(),
    };

    Ok((dst, imm_str, size))
}

fn is_prefix(opcode: u8) -> bool {
    matches!(
        opcode,
        0xF0 | // LOCK
        0xF2 | // REPNE/REPNZ
        0xF3 | // REP/REPE/REPZ
        0x2E | // CS segment override
        0x36 | // SS segment override
        0x3E | // DS segment override
        0x26 | // ES segment override
        0x64 | // FS segment override
        0x65   // GS segment override
    )
}

pub fn format_disassembly(instructions: &[Instruction]) -> String {
    instructions
        .iter()
        .map(|instr| {
            format!(
                "{}: {} {}{}",
                format!("{:04X}", instr.address).yellow(),
                instr
                    .bytes
                    .iter()
                    .map(|b| format!("{:02X}", b))
                    .collect::<Vec<String>>()
                    .join(" ")
                    .cyan(),
                instr.mnemonic.green(),
                if instr.operands.is_empty() {
                    String::new()
                } else {
                    format!(" {}", instr.operands.join(", ").white())
                }
            )
        })
        .collect::<Vec<String>>()
        .join("\n")
}

instruction.rs:
use std::fmt;

#[derive(Debug, Clone)]
pub struct Instruction {
    pub opcode: u8,
    pub mnemonic: String,
    pub operands: Vec<String>,
    pub bytes: Vec<u8>,
    pub address: usize,
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{:04X}: {:10} {}",
            self.address,
            self.bytes.iter().map(|b| format!("{:02X}", b)).collect::<Vec<String>>().join(" "),
            self.mnemonic
        )?;
        if !self.operands.is_empty() {
            write!(f, " {}", self.operands.join(", "))?;
        }
        Ok(())
    }
}


Make this code more advanced and add way more instructions. Double check if for errors whilst your at it. Provide the full code. Advance it to new heights.