#include "Emulator.h"
#include <iostream>
#include <stdint.h>
#include <string>
#include "Logger.h"
#include "utils.h"
void Emulator::update_ZF_FLAG(uint32_t result) {
    if (result == 0)
        regs.EFLAGS |= ZF_FLAG;
    else
        regs.EFLAGS &= ~ZF_FLAG;
}
void Emulator::instr_IMUL_reg_rm32_imm8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint32_t* dest_reg = get_register_by_code(reg_code);
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in IMUL.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t operand = 0;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(rm_code);
        if (!src_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in IMUL.");
            error_flag = true;
            running = false;
            return;
        }
        operand = *src_reg;
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported addressing mode in IMUL.");
        error_flag = true;
        running = false;
        return;
    }
    int8_t imm8 = static_cast<int8_t>(fetch_byte());
    int32_t result = static_cast<int32_t>(operand) * imm8;
    *dest_reg = static_cast<uint32_t>(result);
    update_ZF_FLAG(*dest_reg);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IMUL reg, r/m32, imm8.");
}
void Emulator::instr_MOV_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX = imm;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV EAX, imm32.");
}
void Emulator::instr_PUSH_EAX() { push(regs.EAX); }
void Emulator::instr_PUSH_ECX() { push(regs.ECX); }
void Emulator::instr_PUSH_EDX() { push(regs.EDX); }
void Emulator::instr_PUSH_EBX() { push(regs.EBX); }
void Emulator::instr_PUSH_ESP() { push(regs.ESP); }
void Emulator::instr_PUSH_EBP() { push(regs.EBP); }
void Emulator::instr_PUSH_ESI() { push(regs.ESI); }
void Emulator::instr_PUSH_EDI() { push(regs.EDI); }
void Emulator::instr_CLD() {
    regs.EFLAGS &= ~DF_FLAG;
    Logger::get_instance().log(LogLevel::DEBUG, "Executed CLD (Direction Flag cleared).");
}
void Emulator::instr_PUSH_imm8() {
    int8_t imm8 = static_cast<int8_t>(fetch_byte());
    push(static_cast<uint32_t>(imm8));
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: PUSH imm8.");
}
void Emulator::push(uint32_t value) {
    if (regs.ESP < 4) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack overflow on push.");
        error_flag = true;
        running = false;
        return;
    }
    regs.ESP -= 4;
    write_memory_dword(regs.ESP, value);
}
void Emulator::instr_NOP_EAX() {
    Logger::get_instance().log(LogLevel::DEBUG, "Executed NOP [EAX].");
}
void Emulator::instr_POP_ESP() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP ESP.");
        error_flag = true;
        running = false;
        return;
    }
    regs.ESP = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP ESP.");
}
void Emulator::instr_POP_EBX() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP EBX.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EBX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP EBX.");
}
void Emulator::instr_POP_EDX() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP EDX.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EDX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP EDX.");
}
void Emulator::instr_POP_ECX() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP ECX.");
        error_flag = true;
        running = false;
        return;
    }
    regs.ECX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP ECX.");
}
void Emulator::instr_POP_EAX() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP EAX.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EAX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP EAX.");
}
void Emulator::instr_POP_ESI() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP ESI.");
        error_flag = true;
        running = false;
        return;
    }
    regs.ESI = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::DEBUG, "Executed instruction POP ESI.");
}
void Emulator::instr_POP_EDI() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP EDI.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EDI = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POP EDI.");
}
void Emulator::instr_MOV_Ev_Iv() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t immediate = fetch_dword();
    if (operand.is_memory) {
        write_memory_dword(operand.address, immediate);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MOV Ev, Iv.");
            error_flag = true;
            running = false;
            return;
        }
        *reg = immediate;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV Ev, Iv.");
}
void Emulator::instr_INC_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value++;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        (*reg)++;
        value = *reg;
    }
    update_ZF_FLAG(operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code));
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INC rm32.");
}
void Emulator::instr_DEC_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value--;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        (*reg)--;
        value = *reg;
    }
    update_ZF_FLAG(operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code));
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: DEC rm32.");
}
void Emulator::instr_IMUL_r32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    int32_t value;
    if (operand.is_memory) {
        value = static_cast<int32_t>(read_memory_dword(operand.address));
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in IMUL r32.");
            error_flag = true;
            running = false;
            return;
        }
        value = static_cast<int32_t>(*reg);
    }
    int64_t result = static_cast<int64_t>(static_cast<int32_t>(regs.EAX)) * value;
    regs.EAX = static_cast<uint32_t>(result & 0xFFFFFFFF);
    regs.EDX = static_cast<uint32_t>((result >> 32) & 0xFFFFFFFF);
    if (regs.EDX != 0) {
        regs.EFLAGS |= CF_FLAG | OF_FLAG;
    }
    else {
        regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    }
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IMUL r32.");
}
void Emulator::instr_DIV_r32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t divisor;
    uint64_t dividend = ((uint64_t)regs.EDX << 32) | regs.EAX;
    if (operand.is_memory) {
        divisor = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in DIV r32.");
            error_flag = true;
            running = false;
            return;
        }
        divisor = *reg;
    }
    if (divisor == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in DIV r32.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EAX = static_cast<uint32_t>(dividend / divisor);
    regs.EDX = static_cast<uint32_t>(dividend % divisor);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: DIV r32.");
}
void Emulator::instr_IDIV_r32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    int32_t divisor;
    int64_t dividend = ((int64_t)(int32_t)regs.EDX << 32) | regs.EAX;
    if (operand.is_memory) {
        divisor = static_cast<int32_t>(read_memory_dword(operand.address));
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in IDIV r32.");
            error_flag = true;
            running = false;
            return;
        }
        divisor = static_cast<int32_t>(*reg);
    }
    if (divisor == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in IDIV r32.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EAX = static_cast<uint32_t>(dividend / divisor);
    regs.EDX = static_cast<uint32_t>(dividend % divisor);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IDIV r32.");
}
void Emulator::instr_ROR_rm32_imm8() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t imm8 = fetch_byte() % 32;
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value = (value >> imm8) | (value << (32 - imm8));
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg = (*reg >> imm8) | (*reg << (32 - imm8));
        value = *reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ROR rm32, imm8.");
}
void Emulator::instr_RET_near_imm16() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on RET.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t return_address = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    uint16_t imm16 = fetch_word();
    regs.ESP += imm16;
    regs.EIP = return_address;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: RET_near_imm16.");
}
void Emulator::instr_PUSHF() {
    push(regs.EFLAGS);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: PUSHF.");
}
void Emulator::instr_POPF() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POPF.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EFLAGS = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: POPF.");
}
void Emulator::instr_IN_AL_DX() {
    uint16_t port = regs.EDX & 0xFFFF;
    uint8_t input_value = 0xFF;
    regs.EAX = (regs.EAX & 0xFFFFFF00) | input_value;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IN AL, DX.");
}
void Emulator::instr_OUT_DX_AL() {
    uint16_t port = regs.EDX & 0xFFFF;
    uint8_t value = regs.EAX & 0xFF;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: OUT DX, AL.");
}
void Emulator::instr_MOV_rm32_r32() {
    uint8_t modrm = fetch_byte();
    Operand dest = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* src_reg = get_register_by_code(reg_code);
    if (!src_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in MOV rm32, r32.");
        error_flag = true;
        running = false;
        return;
    }
    if (dest.is_memory) {
        write_memory_dword(dest.address, *src_reg);
    }
    else {
        uint32_t* dest_reg = get_register_by_code(dest.register_code);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV rm32, r32.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg = *src_reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV rm32, r32.");
}
void Emulator::instr_MOV_rm16_r16() {
    uint8_t modrm = fetch_byte();
    Operand dest = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint16_t* src_reg = reinterpret_cast<uint16_t*>(get_register_by_code(reg_code));
    if (!src_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in MOV rm16, r16.");
        error_flag = true;
        running = false;
        return;
    }
    if (dest.is_memory) {
        write_memory_byte(dest.address, *src_reg & 0xFF);
        write_memory_byte(dest.address + 1, (*src_reg >> 8) & 0xFF);
    }
    else {
        uint16_t* dest_reg = reinterpret_cast<uint16_t*>(get_register_by_code(dest.register_code));
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV rm16, r16.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg = *src_reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV rm16, r16.");
}
void Emulator::instr_MOV_r16_rm16() {
    uint8_t modrm = fetch_byte();
    Operand src = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint16_t* dest_reg = reinterpret_cast<uint16_t*>(get_register_by_code(reg_code));
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV r16, rm16.");
        error_flag = true;
        running = false;
        return;
    }
    if (src.is_memory) {
        uint16_t value = read_memory_byte(src.address) | (read_memory_byte(src.address + 1) << 8);
        *dest_reg = value;
    }
    else {
        uint16_t* src_reg = reinterpret_cast<uint16_t*>(get_register_by_code(src.register_code));
        if (!src_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in MOV r16, rm16.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg = *src_reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV r16, rm16.");
}
void Emulator::instr_LEA() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* dest_reg = get_register_by_code(reg_code);
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in LEA.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t address = calculate_address(modrm);
    if (error_flag)
        return;
    *dest_reg = address;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: LEA.");
}
void Emulator::instr_LEAVE() {
    regs.ESP = regs.EBP;
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on LEAVE.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EBP = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: LEAVE.");
}
void Emulator::instr_CALL_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint32_t address = operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code);
    push(regs.EIP);
    regs.EIP = address;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CALL rm32.");
}
void Emulator::instr_JMP_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint32_t address = operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code);
    regs.EIP = address;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JMP rm32.");
}
void Emulator::instr_PUSH_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint32_t value = operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code);
    push(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: PUSH rm32.");
}
void Emulator::instr_PUSH_imm32() {
    uint32_t imm32 = fetch_dword();
    push(imm32);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: PUSH imm32.");
}
void Emulator::instr_GROUP5() {
    uint8_t modrm = fetch_byte();
    uint8_t reg = (modrm >> 3) & 0x07;
    switch (reg) {
    case 0:
        instr_INC_rm32(modrm);
        break;
    case 1:
        instr_DEC_rm32(modrm);
        break;
    case 2:
        instr_CALL_rm32(modrm);
        break;
    case 3:
        Logger::get_instance().log(LogLevel::ERROR, "CALL far not supported.");
        error_flag = true;
        running = false;
        break;
    case 4:
        instr_JMP_rm32(modrm);
        break;
    case 5:
        Logger::get_instance().log(LogLevel::ERROR, "JMP far not supported.");
        error_flag = true;
        running = false;
        break;
    case 6:
        instr_PUSH_rm32(modrm);
        break;
    case 7:
        instr_NOT_rm32(modrm);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unknown subtype for 0xFF: " + std::to_string(reg));
        error_flag = true;
        running = false;
        break;
    }
}
void Emulator::instr_TEST_rm32_r32() {
    uint8_t modrm = fetch_byte(); 
    Operand operand = decode_operand(modrm);
    uint32_t* reg = nullptr;
    if (operand.is_memory) {
        reg = nullptr; 
    }
    else {
        reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in TEST r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    uint8_t reg_code_src = (modrm & 0x07); 
    uint32_t* reg_src = get_register_by_code(reg_code_src);
    if (!reg_src) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in TEST r/m32, r32.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(translate_virtual_address(operand.address));
    }
    else {
        value = *reg;
    }
    uint32_t src_value = *reg_src;
    uint32_t result = value & src_value;
    regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    if (result == 0) {
        regs.EFLAGS |= ZF_FLAG;
    }
    else {
        regs.EFLAGS &= ~ZF_FLAG;
    }
    if (result & 0x80000000) {
        regs.EFLAGS |= SF_FLAG;
    }
    else {
        regs.EFLAGS &= ~SF_FLAG;
    }
    update_PF(result & 0xFF); 
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: TEST r/m32, r32.");
}
void Emulator::instr_ENDBR32() {
    uint8_t last_byte = fetch_byte();
    if (last_byte != 0xFB) {
        Logger::get_instance().log(LogLevel::ERROR, "Expected byte 0xFB after opcode 0x1E for ENDBR32, found: 0x" + byte_to_hex(last_byte));
        error_flag = true;
        running = false;
        return;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ENDBR32.");
}
void Emulator::instr_STD() {
    regs.EFLAGS |= DF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: STD.");
}
void Emulator::instr_NOP() {
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: NOP.");
}
void Emulator::instr_PUSHAD() {
    uint32_t temp_esp = regs.ESP;
    push(regs.EAX);
    push(regs.ECX);
    push(regs.EDX);
    push(regs.EBX);
    push(temp_esp);
    push(regs.EBP);
    push(regs.ESI);
    push(regs.EDI);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: PUSHAD.");
}
void Emulator::instr_REP_MOVSB() {
    while (regs.ECX != 0) {
        uint8_t byte = read_memory_byte(regs.ESI);
        write_memory_byte(regs.EDI, byte);
        if (regs.EFLAGS & DF_FLAG) {
            regs.ESI -= 1;
            regs.EDI -= 1;
        }
        else {
            regs.ESI += 1;
            regs.EDI += 1;
        }
        regs.ECX -= 1;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: REP MOVSB.");
}
void Emulator::instr_NOT_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    if (operand.is_memory) {
        uint32_t value = read_memory_dword(operand.address);
        value = ~value;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in NOT r/m32.");
            error_flag = true;
            running = false;
            return;
        }
        *reg = ~(*reg);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: NOT r/m32.");
}
void Emulator::instr_NOP_m16_m32() {
    bool operand_size = regs.operand_size_override;
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    if (mod == 3) {
        uint8_t rm = modrm & 0x07;
        uint32_t* reg = get_register_by_code(rm);
        if (reg) {
            uint32_t temp = *reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in NOP r/m32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (operand_size) {
            uint16_t temp = read_memory_byte(address) | (read_memory_byte(address + 1) << 8);
        }
        else {
            uint32_t temp = read_memory_dword(address);
        }
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: NOP m16/m32.");
}
void Emulator::instr_MOV_EBX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EBX = imm;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV EBX, imm32.");
}
void Emulator::instr_MOV_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX = imm;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV ECX, imm32.");
}
void Emulator::instr_MOV_EDX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EDX = imm;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV EDX, imm32.");
}
void Emulator::instr_ADD_EAX_imm32() {
    if (regs.rep_prefix || regs.repne_prefix) {
        Logger::get_instance().log(LogLevel::ERROR, "REP prefix ignored for ADD EAX, imm32.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t imm = fetch_dword();
    regs.EAX += imm;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ADD EAX, imm32.");
}
void Emulator::instr_SUB_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX -= imm;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SUB EAX, imm32.");
}
void Emulator::instr_INC_EAX() {
    regs.EAX += 1;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INC EAX.");
}
void Emulator::instr_DEC_EAX() {
    regs.EAX -= 1;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: DEC EAX.");
}
void Emulator::instr_MUL_EAX() {
    uint8_t modrm = fetch_byte();
    if ((modrm & 0x38) == 0x20) {
        regs.EAX *= regs.EAX;
        update_ZF_FLAG(regs.EAX);
        Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MUL EAX.");
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "MUL instruction with unsupported operand.");
    }
}
void Emulator::instr_JMP_rel32() {
    int32_t rel = fetch_dword();
    regs.EIP += rel;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JMP rel32.");
}
void Emulator::instr_CMP_reg_imm8() {
    uint8_t modrm = fetch_byte();
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t imm8 = fetch_byte();
    uint32_t* reg_ptr = get_register_by_code(regm_rm(modrm));
    if (reg_ptr) {
        uint32_t result = *reg_ptr - imm8;
        if (result == 0)
            regs.EFLAGS |= ZF_FLAG;
        else
            regs.EFLAGS &= ~ZF_FLAG;
        if (*reg_ptr < imm8)
            regs.EFLAGS |= CF_FLAG;
        else
            regs.EFLAGS &= ~CF_FLAG;
        if (result & (1 << 31))
            regs.EFLAGS |= (1 << 7);
        else
            regs.EFLAGS &= ~(1 << 7);
        Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CMP reg, imm8.");
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "CMP instruction with unsupported register.");
        error_flag = true;
        running = false;
    }
}
void Emulator::instr_JE_rel8() {
    int8_t rel = fetch_byte();
    if (regs.EFLAGS & ZF_FLAG) {
        regs.EIP += rel;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JE rel8.");
}
void Emulator::instr_JNE_rel8() {
    int8_t rel = fetch_byte();
    if (!(regs.EFLAGS & ZF_FLAG)) {
        regs.EIP += rel;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JNE rel8.");
}
void Emulator::instr_AND_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX &= imm;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: AND EAX, imm32.");
}
void Emulator::instr_AND_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX &= imm;
    update_ZF_FLAG(regs.ECX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: AND ECX, imm32.");
}
void Emulator::instr_OR_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX |= imm;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: OR EAX, imm32.");
}
void Emulator::instr_OR_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX |= imm;
    update_ZF_FLAG(regs.ECX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: OR ECX, imm32.");
}
void Emulator::instr_XOR_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX ^= imm;
    update_ZF_FLAG(regs.EAX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: XOR EAX, imm32.");
}
void Emulator::instr_SUB_EBX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EBX -= imm;
    update_ZF_FLAG(regs.EBX);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SUB EBX, imm32.");
}
void Emulator::instr_CMP_EAX_imm32() {
    uint32_t imm = fetch_dword();
    uint32_t result = regs.EAX - imm;
    if (regs.EAX == imm)
        regs.EFLAGS |= ZF_FLAG;
    else
        regs.EFLAGS &= ~ZF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CMP EAX, imm32.");
}
void Emulator::instr_RET() {
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on RET.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t return_address = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    regs.EIP = return_address;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: RET.");
}
void Emulator::instr_SUB_r32_imm32() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    if (reg_opcode != 5) {
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported SUB instruction with reg opcode: " + std::to_string(reg_opcode));
        return;
    }
    uint32_t imm32 = fetch_dword();
    uint8_t rm = regm_rm(modrm);
    uint32_t* reg_ptr = get_register_by_code(rm);
    if (reg_ptr) {
        *reg_ptr -= imm32;
        update_ZF_FLAG(*reg_ptr);
        Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SUB r32, imm32.");
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "SUB instruction with unsupported register.");
    }
}
void Emulator::instr_CMP_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint32_t* reg = get_register_by_code(reg_code);
    uint32_t* rm;
    if (mod == 3) {
        rm = get_register_by_code(rm_code);
        if (!rm) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in CMP r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "Only register mode supported for CMP r/m32, r32.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t result = *rm - *reg;
    if (result == 0)
        regs.EFLAGS |= ZF_FLAG;
    else
        regs.EFLAGS &= ~ZF_FLAG;
    if (result & 0x80000000)
        regs.EFLAGS |= SF_FLAG;
    else
        regs.EFLAGS &= ~SF_FLAG;
    if (*rm < *reg)
        regs.EFLAGS |= CF_FLAG;
    else
        regs.EFLAGS &= ~CF_FLAG;
    uint32_t sign_rm = *rm & 0x80000000;
    uint32_t sign_reg = *reg & 0x80000000;
    uint32_t sign_result = result & 0x80000000;
    if ((sign_rm != sign_reg) && (sign_rm != sign_result))
        regs.EFLAGS |= OF_FLAG;
    else
        regs.EFLAGS &= ~OF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CMP r32, rm32.");
}
void Emulator::instr_JE_rel32() {
    int32_t displacement = fetch_dword(); 
    bool ZF = regs.EFLAGS & ZF_FLAG;
    if (ZF) {
        uint32_t new_eip = regs.EIP + displacement;
        Logger::get_instance().log(LogLevel::INFO, "JE taken. Jumping to " + addr_to_hex(new_eip) + ".");
        bool valid_address = false;
        for (const auto& segment : loaded_segments) {
            if (new_eip >= segment.p_vaddr && new_eip < (segment.p_vaddr + segment.p_memsz)) {
                valid_address = true;
                break;
            }
        }
        if (valid_address) {
            regs.EIP = new_eip;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Jump to invalid virtual address " + addr_to_hex(new_eip) + ".");
            error_flag = true;
            running = false;
        }
    }
    else {
        Logger::get_instance().log(LogLevel::INFO, "Condition for JE not met. No jump performed.");
    }
}
void Emulator::instr_JA_rel32() {
    int32_t rel32 = static_cast<int32_t>(fetch_dword());
    Logger::get_instance().log(LogLevel::DEBUG, "Executing JA rel32 with offset " + std::to_string(rel32));
    bool carry_flag = (regs.EFLAGS & CF_FLAG) != 0;
    bool zero_flag = (regs.EFLAGS & ZF_FLAG) != 0;
    if (!carry_flag && !zero_flag) {
        Logger::get_instance().log(LogLevel::DEBUG, "Condition for JA met. Jumping.");
        regs.EIP += rel32;
    }
    else {
        Logger::get_instance().log(LogLevel::DEBUG, "Condition for JA not met. Continuing.");
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JA rel32.");
}
void Emulator::instr_JNE_rel32() {
    int32_t rel32 = fetch_dword();
    if (!(regs.EFLAGS & ZF_FLAG)) {
        regs.EIP += rel32;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JNE rel32.");
}
void Emulator::instr_JG_rel32() {
    int32_t rel32 = fetch_dword();
    bool zf_flag = (regs.EFLAGS & ZF_FLAG) != 0;
    bool sf_flag = (regs.EFLAGS & SF_FLAG) != 0;
    bool of_flag = (regs.EFLAGS & OF_FLAG) != 0;
    if (!zf_flag && (sf_flag == of_flag)) {
        regs.EIP += rel32;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JG rel32.");
}
void Emulator::instr_MOV_rm8_imm8() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t imm8 = fetch_byte();
    if (operand.is_memory) {
        write_memory_byte(translate_virtual_address(operand.address), imm8);
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (reg) {
            *reg = imm8;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MOV r/m8, imm8.");
            error_flag = true;
            running = false;
            return;
        }
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV rm8, imm8.");
}
void Emulator::instr_MUL_rm32(uint8_t modrm) {
    uint8_t mod = (modrm & 0xC0) >> 6;
    uint8_t rm = (modrm & 0x07);
    uint32_t operand = 0;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(rm);
        if (src_reg) {
            operand = *src_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MUL r/m32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        operand = read_memory_dword(address);
    }
    uint64_t result = static_cast<uint64_t>(regs.EAX) * static_cast<uint64_t>(operand);
    regs.EAX = static_cast<uint32_t>(result & 0xFFFFFFFF);
    regs.EDX = static_cast<uint32_t>((result >> 32) & 0xFFFFFFFF);
    if (regs.EDX != 0) {
        regs.EFLAGS |= CF_FLAG | OF_FLAG;
    }
    else {
        regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MUL rm32.");
}
void Emulator::instr_DIV_rm32(uint8_t modrm) {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: DIV r/m32.");
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t rm = modrm & 0x07;
    uint32_t operand = 0;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(rm);
        if (src_reg) {
            operand = *src_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in DIV r/m32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        operand = read_memory_dword(address);
    }
    if (operand == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in DIV r/m32.");
        error_flag = true;
        running = false;
        return;
    }
    uint64_t dividend = ((uint64_t)regs.EDX << 32) | regs.EAX;
    regs.EAX = static_cast<uint32_t>(dividend / operand);
    regs.EDX = static_cast<uint32_t>(dividend % operand);
}
void Emulator::instr_LEA_r32_m() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: LEA r32, m.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    if (mod == 3) {
        Logger::get_instance().log(LogLevel::ERROR, "Invalid LEA instruction with mod == 3.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t address = calculate_address(modrm);
    if (error_flag)
        return;
    uint32_t* dest_reg = get_register_by_code(reg);
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in LEA.");
        error_flag = true;
        running = false;
        return;
    }
    *dest_reg = address;
}
void Emulator::instr_IDIV_rm32(uint8_t modrm) {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: IDIV r/m32.");
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t rm = modrm & 0x07;
    int32_t operand = 0;
    if (mod == 3) {
        int32_t* src_reg = reinterpret_cast<int32_t*>(get_register_by_code(rm));
        if (src_reg) {
            operand = *src_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in IDIV r/m32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        operand = read_memory_dword(address);
    }
    if (operand == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in IDIV r/m32.");
        error_flag = true;
        running = false;
        return;
    }
    int64_t dividend = ((int64_t)(int32_t)regs.EDX << 32) | regs.EAX;
    regs.EAX = static_cast<uint32_t>(dividend / operand);
    regs.EDX = static_cast<uint32_t>(dividend % operand);
}
void Emulator::instr_F7() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: F7.");
    uint8_t modrm = fetch_byte();
    uint8_t reg = (modrm >> 3) & 0x07;
    switch (reg) {
    case 4:
        instr_MUL_rm32(modrm);
        break;
    case 6:
        instr_DIV_rm32(modrm);
        break;
    case 7:
        instr_IDIV_rm32(modrm);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported operation in group 0xF7: " + std::to_string(reg));
        error_flag = true;
        running = false;
        break;
    }
}
void Emulator::instr_MOV_rm8_r8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV r/m8, r8.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint8_t* src_reg = get_register8_by_code(reg_code);
    if (!src_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in MOV r/m8, r8.");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t value = *src_reg;
    if (mod == 3) {
        uint8_t* dest_reg = get_register8_by_code(rm);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV r/m8, r8.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg = value;
    }
    else {
        uint32_t address_virtual = calculate_address(modrm);
        if (error_flag) {
            return;
        }
        uint32_t physical_address;
        try {
            physical_address = translate_virtual_address(address_virtual);
        }
        catch (const std::runtime_error& e) {
            throw std::runtime_error("MOV r/m8, r8: " + std::string(e.what()));
        }
        write_memory_byte(physical_address, value);
    }
}
void Emulator::instr_ADD_AL_imm8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: ADD AL, imm8.");
    uint8_t imm8 = fetch_byte();
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    *al += imm8;
    update_ZF_FLAG(*al);
}
void Emulator::instr_POP_EBP() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: POP EBP.");
    if (regs.ESP + 4 > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Stack underflow on POP EBP.");
        error_flag = true;
        running = false;
        return;
    }
    regs.EBP = read_memory_dword(regs.ESP);
    regs.ESP += 4;
    Logger::get_instance().log(LogLevel::INFO, "Executed POP EBP. EBP: " + addr_to_hex(regs.EBP));
}
void Emulator::instr_MOV_ESI_imm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV ESI, imm32.");
    regs.ESI = fetch_dword();
}
void Emulator::sys_read() {
    Logger::get_instance().log(LogLevel::INFO, "Executing syscall: sys_read.");
    uint32_t fd = regs.EBX;
    uint32_t buf = regs.ECX;
    uint32_t count = regs.EDX;
    if (fd != 0) {
        Logger::get_instance().log(LogLevel::ERROR, "sys_read: Only stdin (fd = 0) is supported.");
        regs.EAX = static_cast<uint32_t>(-1);
        return;
    }
    std::string input;
    std::getline(std::cin, input);
    if (input.size() < count) {
        input += '\n';
    }
    if (input.size() > count) {
        input = input.substr(0, count);
    }
    for (size_t i = 0; i < input.size(); ++i) {
        uint32_t virtual_addr = buf + static_cast<uint32_t>(i);
        uint32_t physical_addr = translate_virtual_address(virtual_addr);
        if (physical_addr >= memory.size()) {
            memory.resize(physical_addr + 1, 0);
        }
        memory[physical_addr] = static_cast<uint8_t>(input[i]);
    }
    regs.EAX = static_cast<uint32_t>(input.size());
}
void Emulator::instr_INT() {
    uint8_t int_number = fetch_byte();
    if (int_number == 0x80) {
        uint32_t syscall_number = regs.EAX;
        switch (syscall_number) {
        case 1:
            running = false;
            break;
        case 3:
            sys_read();
            break;
        case 4: {
            uint32_t fd = regs.EBX;
            uint32_t buf_virtual = regs.ECX;
            uint32_t count = regs.EDX;
            if (fd == 1) {
                try {
                    uint32_t buf_physical = translate_virtual_address(buf_virtual);
                    if (buf_physical + count > memory.size()) {
                        throw std::runtime_error("Buffer out of bounds in sys_write");
                    }
                    std::string output;
                    for (uint32_t i = 0; i < count; ++i) {
                        output += static_cast<char>(memory[buf_physical + i]);
                    }
                    std::cout << output;
                    regs.EAX = count;
                }
                catch (const std::exception& e) {
                    Logger::get_instance().log(LogLevel::ERROR, "Buffer out of bounds in sys_write: " + std::string(e.what()));
                    regs.EAX = -1;
                }
            }
            else {
                regs.EAX = -1;
            }
            break;
        }
        case 45: {
            uint32_t addr = regs.EBX;
            if (addr == 0) {
                regs.EAX = current_brk;
            }
            else {
                if (addr > current_brk) {
                    bool mapped = false;
                    for (const auto& seg : loaded_segments) {
                        if (addr >= seg.p_vaddr && addr <= (seg.p_vaddr + seg.p_memsz)) {
                            mapped = true;
                            break;
                        }
                    }
                    if (!mapped) {
                        uint32_t min_vaddr = ELF_BASE_ADDRESS;
                        uint32_t new_max_vaddr = addr;
                        uint32_t new_required_size = new_max_vaddr - min_vaddr;
                        if (new_required_size > memory.size()) {
                            resize_memory(new_required_size);
                            Logger::get_instance().log(LogLevel::DEBUG, "Emulator memory resized to " + addr_to_hex(new_required_size) + " bytes on brk() call.");
                        }
                        Segment heap_segment;
                        heap_segment.p_vaddr = current_brk;
                        heap_segment.p_memsz = addr - current_brk;
                        heap_segment.p_offset = current_brk - min_vaddr;
                        loaded_segments.push_back(heap_segment);
                        std::fill(memory.begin() + heap_segment.p_offset, memory.begin() + heap_segment.p_offset + heap_segment.p_memsz, 0);
                    }
                }
                current_brk = addr;
                regs.EAX = current_brk;
            }
            break;
        }
        case 91:
            regs.EAX = 0;
            break;
        case 5:
            regs.EAX = 3;
            break;
        case 6:
            regs.EAX = 0;
            break;
        case 197: {
            uint32_t fd = regs.EBX;
            uint32_t buf = regs.ECX;
            memset(&memory[buf], 0, 104);
            regs.EAX = 0;
            break;
        }
        default:
            Logger::get_instance().log(LogLevel::ERROR, "Unknown syscall: " + std::to_string(syscall_number));
            running = false;
            break;
        }
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown interrupt: INT " + std::to_string(int_number));
        error_flag = true;
        running = false;
    }
}
void Emulator::instr_MOV_MEM_EAX() {
    uint32_t address_virtual = fetch_dword();
    uint32_t physical_address = translate_virtual_address(address_virtual);
    write_memory_dword(physical_address, regs.EAX);
}
void Emulator::instr_MOV_EAX_MEM() {
    uint32_t address_virtual = fetch_dword();
    uint32_t physical_address = translate_virtual_address(address_virtual);
    regs.EAX = read_memory_dword(physical_address);
}
void Emulator::instr_CMP_EAX_EBX() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: CMP EAX, EBX.");
    uint8_t modrm = fetch_byte();
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    if (reg == 0 && rm == 3) {
        uint32_t result = regs.EAX - regs.EBX;
        if (result == 0)
            regs.EFLAGS |= ZF_FLAG;
        else
            regs.EFLAGS &= ~ZF_FLAG;
        if (result & 0x80000000)
            regs.EFLAGS |= SF_FLAG;
        else
            regs.EFLAGS &= ~SF_FLAG;
        if (regs.EAX < regs.EBX)
            regs.EFLAGS |= CF_FLAG;
        else
            regs.EFLAGS &= ~CF_FLAG;
        uint32_t sign_rm = regs.EAX & 0x80000000;
        uint32_t sign_reg = regs.EBX & 0x80000000;
        uint32_t sign_result = result & 0x80000000;
        if ((sign_rm != sign_reg) && (sign_rm != sign_result))
            regs.EFLAGS |= OF_FLAG;
        else
            regs.EFLAGS &= ~OF_FLAG;
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "CMP instruction with unsupported register combination.");
        error_flag = true;
        running = false;
    }
}
void Emulator::instr_JG_rel8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JG rel8.");
    int8_t rel = fetch_byte();
    bool zf_flag = (regs.EFLAGS & ZF_FLAG) != 0;
    bool sf_flag = (regs.EFLAGS & SF_FLAG) != 0;
    bool of_flag = (regs.EFLAGS & OF_FLAG) != 0;
    if (!zf_flag && (sf_flag == of_flag)) {
        regs.EIP += rel;
    }
}
void Emulator::instr_IMUL_reg_rm32_imm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: IMUL reg, r/m32, imm32.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint32_t* dest_reg = get_register_by_code(reg_code);
    uint32_t* src_reg = nullptr;
    if (mod == 3) {
        src_reg = get_register_by_code(rm_code);
        if (!src_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in IMUL.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported addressing mode in IMUL.");
        error_flag = true;
        running = false;
        return;
    }
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in IMUL.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t imm32 = fetch_dword();
    int32_t result = static_cast<int32_t>(*src_reg) * static_cast<int32_t>(imm32);
    *dest_reg = static_cast<uint32_t>(result);
    update_ZF_FLAG(*dest_reg);
}
void Emulator::instr_SUB_AL_imm8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: SUB AL, imm8.");
    uint8_t imm8 = fetch_byte();
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    *al -= imm8;
    update_ZF_FLAG(*al);
}
void Emulator::instr_JMP_rel8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JMP rel8.");
    int8_t rel = fetch_byte();
    regs.EIP += rel;
}
void Emulator::instr_JB_rel8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JB rel8.");
    int8_t rel = fetch_byte();
    if (regs.EFLAGS & CF_FLAG) {
        regs.EIP += rel;
    }
}
void Emulator::instr_JA_rel8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JA rel8.");
    int8_t rel = fetch_byte();
    bool cf_flag = (regs.EFLAGS & CF_FLAG) != 0;
    bool zf_flag = (regs.EFLAGS & ZF_FLAG) != 0;
    if (!cf_flag && !zf_flag) {
        regs.EIP += rel;
    }
}
void Emulator::instr_INC_ECX() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: INC ECX.");
    regs.ECX += 1;
    update_ZF_FLAG(regs.ECX);
}
void Emulator::instr_MOV_r8_imm8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV r8, imm8.");
    uint8_t opcode = memory[regs.EIP - 1];
    uint8_t reg_code = opcode - 0xB0;
    uint8_t imm8 = fetch_byte();
    uint8_t* reg = get_register8_by_code(reg_code);
    if (!reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MOV r8, imm8.");
        error_flag = true;
        running = false;
        return;
    }
    *reg = imm8;
}
void Emulator::instr_SUB_rm8_imm8() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    if (!operand.is_memory) {
        uint8_t* reg8 = get_register8_by_code(operand.register_code);
        if (reg8 == nullptr) {
            Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in SUB_rm8_imm8.");
            running = false;
            return;
        }
        uint8_t imm8 = static_cast<uint8_t>(fetch_byte());
        uint8_t result = *reg8 - imm8;
        *reg8 = result;
        update_ZF_FLAG(result);
        update_PF(result);
        Logger::get_instance().log(LogLevel::DEBUG, "Executed SUB r/m8, imm8: " +
            std::to_string(*reg8) + " - " + std::to_string(imm8) + " = " + std::to_string(result));
    }
    else {
        uint8_t imm8 = static_cast<uint8_t>(fetch_byte());
        uint8_t value = read_memory_byte(operand.address);
        uint8_t result = value - imm8;
        write_memory_byte(operand.address, result);
        update_ZF_FLAG(result);
        update_PF(result);
        Logger::get_instance().log(LogLevel::DEBUG, "Executed SUB [0x" +
            addr_to_hex(operand.address) + "], imm8: " +
            std::to_string(value) + " - " + std::to_string(imm8) + " = " + std::to_string(result));
    }
}
void Emulator::instr_MOV_r8_r8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV r8, r8.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    if (mod != 3) {
        Logger::get_instance().log(LogLevel::ERROR, "Operands must be registers (mod != 3).");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint8_t* src_reg = get_register8_by_code(reg_code);
    uint8_t* dest_reg = get_register8_by_code(rm_code);
    if (!src_reg || !dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown register code.");
        error_flag = true;
        running = false;
        return;
    }
    *dest_reg = *src_reg;
    Logger::get_instance().log(
        LogLevel::DEBUG,
        std::string("Moved value 0x") + byte_to_hex(*src_reg) +
        " from register " + register_name(reg_code, true) +
        " to register " + register_name(rm_code, true) + "."
    );
}
void Emulator::instr_MOV_r8_rm8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV r8, r/m8.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint8_t* reg = get_register8_by_code(reg_code);
    if (!reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV r8, r/m8.");
        error_flag = true;
        running = false;
        return;
    }
    if (mod == 3) {
        uint8_t* rm_reg = get_register8_by_code(rm);
        if (rm_reg) {
            *reg = *rm_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in MOV r8, r/m8.");
            error_flag = true;
            running = false;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        uint8_t value = read_memory_byte(address);
        *reg = value;
    }
}
void Emulator::instr_MOV_EBP_imm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV EBP, imm32.");
    uint32_t imm = fetch_dword();
    regs.EBP = imm;
}
void Emulator::instr_MOV_ESP_imm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV ESP, imm32.");
    uint32_t imm = fetch_dword();
    regs.ESP = imm;
}
void Emulator::instr_MOV_EDI_imm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV EDI, imm32.");
    uint32_t imm = fetch_dword();
    regs.EDI = imm;
}
void Emulator::instr_MOV_r32_r_m32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOV r32, r/m32.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint32_t* dest_reg = get_register_by_code(reg);
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(rm);
        if (dest_reg && src_reg) {
            *dest_reg = *src_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MOV r32, r/m32.");
            error_flag = true;
            running = false;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        uint32_t value = read_memory_dword(address);
        if (dest_reg) {
            *dest_reg = value;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV r32, r/m32.");
            error_flag = true;
            running = false;
        }
    }
}
void Emulator::instr_ADD_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint32_t* reg_ptr = get_register_by_code((modrm >> 3) & 0x07);
    if (!reg_ptr) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in ADD r32, r/m32.");
        error_flag = true;
        running = false;
        return;
    }
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in ADD r32, r/m32.");
            error_flag = true;
            running = false;
            return;
        }
        value = *reg;
    }
    *reg_ptr += value;
    update_ZF_FLAG(*reg_ptr);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ADD r32, r/m32.");
}
void Emulator::instr_ADD_rm32_r32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: ADD r/m32, r32.");
    bool is_locked = regs.lock_prefix;
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint32_t* src_reg = get_register_by_code(reg_code);
    if (!src_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in ADD r/m32, r32.");
        error_flag = true;
        running = false;
        return;
    }
    if (mod == 3) {
        uint32_t* dest_reg = get_register_by_code(rm_code);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in ADD r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
        if (is_locked) {
            Logger::get_instance().log(LogLevel::DEBUG, "LOCK prefix applied to ADD r/m32, r32.");
        }
        *dest_reg += *src_reg;
        update_ZF_FLAG(*dest_reg);
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        uint32_t value = read_memory_dword(address);
        value += *src_reg;
        write_memory_dword(address, value);
        update_ZF_FLAG(value);
    }
    reset_prefixes();
}
void Emulator::instr_CMP_AL_imm8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: CMP AL, imm8.");
    uint8_t imm8 = fetch_byte();
    uint8_t al = regs.EAX & 0xFF;
    uint8_t result = al - imm8;
    if (result == 0)
        regs.EFLAGS |= ZF_FLAG;
    else
        regs.EFLAGS &= ~ZF_FLAG;
    if (result & 0x80)
        regs.EFLAGS |= SF_FLAG;
    else
        regs.EFLAGS &= ~SF_FLAG;
    if (al < imm8)
        regs.EFLAGS |= CF_FLAG;
    else
        regs.EFLAGS &= ~CF_FLAG;
    bool overflow = ((al ^ imm8) & (al ^ result) & 0x80) != 0;
    if (overflow)
        regs.EFLAGS |= OF_FLAG;
    else
        regs.EFLAGS &= ~OF_FLAG;
    Logger::get_instance().log(
        LogLevel::DEBUG,
        "Compared AL (0x" + byte_to_hex(al) + ") with imm8 (0x" + byte_to_hex(imm8) +
        "), result: 0x" + byte_to_hex(result) + "."
    );
}
void Emulator::instr_JL_rel8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JL rel8.");
    int8_t rel = fetch_byte();
    bool sf_flag = (regs.EFLAGS & SF_FLAG) != 0;
    bool of_flag = (regs.EFLAGS & OF_FLAG) != 0;
    if (sf_flag != of_flag) {
        regs.EIP += rel;
        Logger::get_instance().log(LogLevel::DEBUG, "Jumping to EIP: " + addr_to_hex(regs.EIP));
    }
}
void Emulator::instr_XOR_r32_rm32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: XOR r32, r/m32.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint32_t src_value;
    uint32_t* dest_reg = nullptr;
    uint32_t address = 0;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(reg);
        dest_reg = get_register_by_code(rm);
        if (!src_reg || !dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in XOR r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
        src_value = *src_reg;
    }
    else {
        address = calculate_address(modrm);
        try {
            src_value = read_memory_dword(address);
        }
        catch (const std::runtime_error& e) {
            Logger::get_instance().log(LogLevel::ERROR, std::string("Memory read error in XOR: ") + e.what());
            error_flag = true;
            running = false;
            return;
        }
    }
    if (mod == 3) {
        *dest_reg ^= src_value;
        update_ZF_FLAG(*dest_reg);
        Logger::get_instance().log(
            LogLevel::DEBUG,
            std::string("XORed value 0x") + addr_to_hex(src_value) +
            " from register " + register_name(reg, false) +
            " with register " + register_name(rm, false) +
            ", result: " + addr_to_hex(*dest_reg) + "."
        );
    }
    else {
        uint32_t dest_value = read_memory_dword(address);
        dest_value ^= src_value;
        try {
            write_memory_dword(address, dest_value);
        }
        catch (const std::runtime_error& e) {
            Logger::get_instance().log(LogLevel::ERROR, std::string("Memory write error in XOR: ") + e.what());
            error_flag = true;
            running = false;
            return;
        }
        update_ZF_FLAG(dest_value);
        Logger::get_instance().log(
            LogLevel::DEBUG,
            std::string("XORed value 0x") + addr_to_hex(src_value) +
            " from register " + register_name(reg, false) +
            " with memory at " + addr_to_hex(address) +
            ", result: " + addr_to_hex(dest_value) + "."
        );
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: XOR r32, r/m32.");
}
void Emulator::instr_CALL_rel32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: CALL rel32.");
    int32_t rel32 = fetch_dword();
    push(regs.EIP);
    regs.EIP += rel32;
    Logger::get_instance().log(LogLevel::DEBUG, "Calling function, jumped to EIP: " + addr_to_hex(regs.EIP));
}
void Emulator::instr_GROUP1_Ev_Iz_81() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: Group 1 Ev, Iz (opcode 0x81).");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint32_t* dest_reg = nullptr;
    if (mod == 3) {
        dest_reg = get_register_by_code(rm);
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "Memory operands not implemented for opcode 0x81.");
        error_flag = true;
        running = false;
        return;
    }
    uint32_t imm32 = fetch_dword();
    switch (reg_opcode) {
    case 0: 
        *dest_reg += imm32;
        update_ZF_FLAG(*dest_reg);
        Logger::get_instance().log(LogLevel::DEBUG, "Added " + addr_to_hex(imm32) + " to register " + register_name(rm,false) + ".");
        break;
    case 1: 
        *dest_reg |= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 4: 
        *dest_reg &= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 5: 
        *dest_reg -= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 6: 
        *dest_reg ^= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 7: 
    {
        uint32_t result = *dest_reg - imm32;
        update_ZF_FLAG(result);
        Logger::get_instance().log(LogLevel::DEBUG, "Compared register " + register_name(rm,false) + " with " + addr_to_hex(imm32) + ".");
        break;
    }
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported reg opcode in opcode 0x81: " + std::to_string(reg_opcode));
        error_flag = true;
        running = false;
        break;
    }
}
void Emulator::instr_GROUP1_Ev_Iz_83() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: Group 1 Ev, Iz (opcode 0x83).");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    int8_t imm8 = static_cast<int8_t>(fetch_byte());
    int32_t sign_extended_imm = static_cast<int32_t>(imm8);
    Operand operand = decode_operand(modrm);
    if (operand.is_memory) {
        uint32_t value = read_memory_dword(operand.address);
        switch (reg_opcode) {
        case 0: 
            value += sign_extended_imm;
            write_memory_dword(operand.address, value);
            update_ZF_FLAG(value);
            Logger::get_instance().log(LogLevel::DEBUG, "Added sign-extended imm8 (0x" + byte_to_hex(imm8) + ") to memory address " + addr_to_hex(operand.address) + ".");
            break;
        case 1: 
            value |= sign_extended_imm;
            write_memory_dword(operand.address, value);
            update_ZF_FLAG(value);
            Logger::get_instance().log(LogLevel::DEBUG, "OR'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with memory address " + addr_to_hex(operand.address) + ".");
            break;
        case 4: 
            value &= sign_extended_imm;
            write_memory_dword(operand.address, value);
            update_ZF_FLAG(value);
            Logger::get_instance().log(LogLevel::DEBUG, "AND'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with memory address " + addr_to_hex(operand.address) + ".");
            break;
        case 5: 
            value -= sign_extended_imm;
            write_memory_dword(operand.address, value);
            update_ZF_FLAG(value);
            Logger::get_instance().log(LogLevel::DEBUG, "SUB'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") from memory address " + addr_to_hex(operand.address) + ".");
            break;
        case 6: 
            value ^= sign_extended_imm;
            write_memory_dword(operand.address, value);
            update_ZF_FLAG(value);
            Logger::get_instance().log(LogLevel::DEBUG, "XOR'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with memory address " + addr_to_hex(operand.address) + ".");
            break;
        case 7: 
        {
            uint32_t result = value - sign_extended_imm;
            update_ZF_FLAG(result);
            Logger::get_instance().log(LogLevel::DEBUG, "Compared memory address " + addr_to_hex(operand.address) + " with sign-extended imm8 (0x" + byte_to_hex(imm8) + ").");
        }
        break;
        default:
            Logger::get_instance().log(LogLevel::ERROR, "Unsupported reg opcode in opcode 0x83: " + std::to_string(reg_opcode));
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t* dest_reg = get_register_by_code(rm);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in Group 1 opcode 0x83.");
            error_flag = true;
            running = false;
            return;
        }
        switch (reg_opcode) {
        case 0: 
            *dest_reg += sign_extended_imm;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(LogLevel::DEBUG, "Added sign-extended imm8 (0x" + byte_to_hex(imm8) + ") to register " + register_name(rm, true) + ".");
            break;
        case 1: 
            *dest_reg |= sign_extended_imm;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(LogLevel::DEBUG, "OR'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with register " + register_name(rm, true) + ".");
            break;
        case 4: 
            *dest_reg &= sign_extended_imm;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(LogLevel::DEBUG, "AND'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with register " + register_name(rm, true) + ".");
            break;
        case 5: 
            *dest_reg -= sign_extended_imm;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(LogLevel::DEBUG, "SUB'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") from register " + register_name(rm, true) + ".");
            break;
        case 6: 
            *dest_reg ^= sign_extended_imm;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(LogLevel::DEBUG, "XOR'ed sign-extended imm8 (0x" + byte_to_hex(imm8) + ") with register " + register_name(rm, true) + ".");
            break;
        case 7: 
        {
            uint32_t result = *dest_reg - sign_extended_imm;
            update_ZF_FLAG(result);
            Logger::get_instance().log(LogLevel::DEBUG, "Compared register " + register_name(rm, true) + " with sign-extended imm8 (0x" + byte_to_hex(imm8) + ").");
        }
        break;
        default:
            Logger::get_instance().log(LogLevel::ERROR, "Unsupported reg opcode in opcode 0x83: " + std::to_string(reg_opcode));
            error_flag = true;
            running = false;
            return;
        }
    }
}
void Emulator::instr_JL_rel32() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: JL rel32.");
    int32_t rel32 = fetch_dword();
    bool sf_flag = (regs.EFLAGS & SF_FLAG) != 0;
    bool of_flag = (regs.EFLAGS & OF_FLAG) != 0;
    if (sf_flag != of_flag) {
        regs.EIP += rel32;
        Logger::get_instance().log(LogLevel::DEBUG, "Jumping to EIP: " + addr_to_hex(regs.EIP));
    }
}
void Emulator::instr_MOVSB() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: MOVSB.");
    if (regs.rep_prefix || regs.repne_prefix) {
        bool is_rep = regs.rep_prefix;
        bool is_repne = regs.repne_prefix;
        while (regs.ECX != 0) {
            uint8_t byte = read_memory_byte(regs.ESI);
            write_memory_byte(regs.EDI, byte);
            regs.ESI += 1;
            regs.EDI += 1;
            regs.ECX -= 1;
            update_ZF_FLAG(byte);
            if (is_repne && (regs.EFLAGS & ZF_FLAG)) {
                break;
            }
            if (is_rep && regs.ECX == 0) {
                break;
            }
        }
        reset_prefixes();
    }
    else {
        uint8_t byte = read_memory_byte(regs.ESI);
        write_memory_byte(regs.EDI, byte);
        regs.ESI += 1;
        regs.EDI += 1;
        update_ZF_FLAG(byte);
    }
    Logger::get_instance().log(LogLevel::DEBUG, "MOVSB completed, updated ESI: " + addr_to_hex(regs.ESI) + ", EDI: " + addr_to_hex(regs.EDI));
}
void Emulator::instr_ADD_rm8_r8() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: ADD r/m8, r8.");
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint8_t* src_reg = get_register8_by_code(reg_code);
    if (!src_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in ADD r/m8, r8.");
        error_flag = true;
        running = false;
        return;
    }
    if (mod == 3) {
        uint8_t* dest_reg = get_register8_by_code(rm);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in ADD r/m8, r8.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg += *src_reg;
        update_ZF_FLAG(*dest_reg);
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        uint8_t value = read_memory_byte(address);
        value += *src_reg;
        write_memory_byte(address, value);
        update_ZF_FLAG(value);
    }
}
void Emulator::instr_XOR_AL_imm8() {
    uint8_t imm8 = fetch_byte();
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    *al ^= imm8;
    if (*al == 0)
        regs.EFLAGS |= ZF_FLAG;
    else
        regs.EFLAGS &= ~ZF_FLAG;
    if (*al & 0x80)
        regs.EFLAGS |= SF_FLAG;
    else
        regs.EFLAGS &= ~SF_FLAG;
    update_PF(*al);
    regs.EFLAGS &= ~CF_FLAG;
    regs.EFLAGS &= ~OF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: XOR AL, imm8.");
}
void Emulator::instr_SETcc(uint8_t condition_code) {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    bool set = false;
    switch (condition_code) {
    case 0x0: 
        set = regs.EFLAGS & OF_FLAG;
        break;
    case 0x1: 
        set = !(regs.EFLAGS & OF_FLAG);
        break;
    case 0x2: 
        set = regs.EFLAGS & CF_FLAG;
        break;
    case 0x3: 
        set = !(regs.EFLAGS & CF_FLAG);
        break;
    case 0x4: 
        set = regs.EFLAGS & ZF_FLAG;
        break;
    case 0x5: 
        set = !(regs.EFLAGS & ZF_FLAG);
        break;
    case 0x6: 
        set = (regs.EFLAGS & CF_FLAG) || (regs.EFLAGS & ZF_FLAG);
        break;
    case 0x7: 
        set = !(regs.EFLAGS & CF_FLAG) && !(regs.EFLAGS & ZF_FLAG);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unknown condition code for SETcc: " + std::to_string(condition_code));
        running = false;
        return;
    }
    uint8_t value = set ? 1 : 0;
    if (operand.is_memory) {
        write_memory_byte(operand.address, value);
        Logger::get_instance().log(LogLevel::DEBUG, "Executed SETcc [0x" +
            addr_to_hex(operand.address) + "], set to " + std::to_string(value) + ".");
    }
    else {
        uint8_t* reg8 = get_register8_by_code(reg_code);
        if (reg8 == nullptr) {
            Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in SETcc.");
            running = false;
            return;
        }
        *reg8 = value;
        Logger::get_instance().log(LogLevel::DEBUG, "Executed SETcc " + register_name(reg_code, true) + ", set to " + std::to_string(value) + ".");
    }
}
void Emulator::instr_SETA_rm8() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* reg_dest = get_register_by_code(reg_code);
    if (reg_dest == nullptr && !operand.is_memory) {
        Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in SETA_rm8.");
        running = false;
        return;
    }
    bool CF = regs.EFLAGS & CF_FLAG;
    bool ZF = regs.EFLAGS & ZF_FLAG;
    bool condition = !CF && !ZF;
    if (condition) {
        uint8_t value = 1;
        if (operand.is_memory) {
            write_memory_byte(operand.address, value);
            Logger::get_instance().log(LogLevel::DEBUG, "Executed SETA [0x" +
                addr_to_hex(operand.address) + "], set to 1.");
        }
        else {
            uint8_t* reg8 = get_register8_by_code(reg_code);
            if (reg8 == nullptr) {
                Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in SETA_rm8.");
                running = false;
                return;
            }
            *reg8 = value;
            Logger::get_instance().log(LogLevel::DEBUG, "Executed SETA " + register_name(reg_code, true) + ", set to 1.");
        }
    }
    else {
        uint8_t value = 0;
        if (operand.is_memory) {
            write_memory_byte(operand.address, value);
            Logger::get_instance().log(LogLevel::DEBUG, "Executed SETA [0x" +
                addr_to_hex(operand.address) + "], set to 0.");
        }
        else {
            uint8_t* reg8 = get_register8_by_code(reg_code);
            if (reg8 == nullptr) {
                Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in SETA_rm8.");
                running = false;
                return;
            }
            *reg8 = value;
            Logger::get_instance().log(LogLevel::DEBUG, "Executed SETA " + register_name(reg_code, true) + ", set to 0.");
        }
    }
}
void Emulator::instr_CMOVZ() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* reg_dest = get_register_by_code(reg_code);
    if (reg_dest == nullptr) {
        Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in CMOVZ.");
        running = false;
        return;
    }
    uint32_t value = 0;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg_src = get_register_by_code(operand.register_code);
        if (reg_src == nullptr) {
            Logger::get_instance().log(LogLevel::ERROR, "Invalid source register code in CMOVZ.");
            running = false;
            return;
        }
        value = *reg_src;
    }
    bool ZF = regs.EFLAGS & ZF_FLAG;
    if (ZF) {
        *reg_dest = value;
        Logger::get_instance().log(LogLevel::DEBUG, "Executed CMOVZ: Moved value 0x" +
            byte_to_hex(value) + " to " + register_name(reg_code, false));
    }
    else {
        Logger::get_instance().log(LogLevel::DEBUG, "CMOVZ condition not met (ZF=0). No action taken.");
    }
}
void Emulator::instr_CMOVB() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* reg_dest = get_register_by_code(reg_code);
    if (reg_dest == nullptr) {
        Logger::get_instance().log(LogLevel::ERROR, "Invalid register code in CMOVB.");
        running = false;
        return;
    }
    uint32_t value = 0;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg_src = get_register_by_code(operand.register_code);
        if (reg_src == nullptr) {
            Logger::get_instance().log(LogLevel::ERROR, "Invalid source register code in CMOVB.");
            running = false;
            return;
        }
        value = *reg_src;
    }
    bool CF = regs.EFLAGS & CF_FLAG;
    if (CF) {
        *reg_dest = value;
        Logger::get_instance().log(LogLevel::DEBUG, "Executed CMOVB: Moved value 0x" +
            byte_to_hex(value) + " to " + register_name(reg_code, false));
    }
    else {
        Logger::get_instance().log(LogLevel::DEBUG, "CMOVB condition not met (CF=0). No action taken.");
    }
}
void Emulator::instr_TEST_rm8_r8() {
    uint8_t modrm = fetch_byte(); 
    Operand operand = decode_operand(modrm);
    uint8_t* reg = nullptr;
    if (operand.is_memory) {
        reg = nullptr; 
    }
    else {
        reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in TEST r/m8, r8.");
            error_flag = true;
            running = false;
            return;
        }
    }
    uint8_t reg_code_src = (modrm & 0x07); 
    uint8_t* reg_src = get_register8_by_code(reg_code_src);
    if (!reg_src) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in TEST r/m8, r8.");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t value;
    if (operand.is_memory) {
        value = read_memory_byte(translate_virtual_address(operand.address));
    }
    else {
        value = *reg;
    }
    uint8_t src_value = *reg_src;
    uint8_t result = value & src_value;
    regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    if (result == 0) {
        regs.EFLAGS |= ZF_FLAG;
    }
    else {
        regs.EFLAGS &= ~ZF_FLAG;
    }
    if (result & 0x80) {
        regs.EFLAGS |= SF_FLAG;
    }
    else {
        regs.EFLAGS &= ~SF_FLAG;
    }
    update_PF(result);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: TEST r/m8, r8.");
}
void Emulator::update_PF(uint8_t result) {
    uint8_t count = 0;
    for (int i = 0; i < 8; ++i) {
        if (result & (1 << i))
            count++;
    }
    if (count % 2 == 0)
        regs.EFLAGS |= PF_FLAG;
    else
        regs.EFLAGS &= ~PF_FLAG;
}
void Emulator::instr_AND_rm8_r8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint8_t* reg = get_register8_by_code(reg_code);
    if (!reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in AND r/m8, r8.");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t value;
    if (mod == 3) {
        uint8_t* dest_reg = get_register8_by_code(rm);
        if (!dest_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in AND r/m8, r8.");
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg &= *reg;
        value = *dest_reg;
        update_ZF_FLAG(value);
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        value = read_memory_byte(address);
        value &= *reg;
        write_memory_byte(address, value);
        update_ZF_FLAG(value);
    }
    regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    if ((value & 0x80) != 0)
        regs.EFLAGS |= SF_FLAG;
    else
        regs.EFLAGS &= ~SF_FLAG;
    update_PF(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: AND r/m8, r8.");
}
void Emulator::instr_INSB() {
    try {
        uint32_t port = regs.EDX;
        uint32_t address = regs.EDI;
        uint8_t input_byte = 0x00;
        write_memory_byte(address, input_byte);
        if (regs.EFLAGS & DF_FLAG) regs.EDI -= 1;
        else regs.EDI += 1;
        Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INSB.");
    }
    catch (const std::exception& e) {
        Logger::get_instance().log(LogLevel::ERROR, std::string("Exception in INSB handler: ") + e.what());
        error_flag = true;
        running = false;
    }
}
void Emulator::instr_IMUL_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    uint32_t* dest_reg = get_register_by_code(reg_code);
    uint32_t operand = 0;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(rm_code);
        if (!src_reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown source register in IMUL r32, r/m32.");
            error_flag = true;
            running = false;
            return;
        }
        operand = *src_reg;
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        operand = read_memory_dword(address);
    }
    if (!dest_reg) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in IMUL r32, r/m32.");
        error_flag = true;
        running = false;
        return;
    }
    int64_t result = static_cast<int64_t>(static_cast<int32_t>(*dest_reg)) * static_cast<int64_t>(static_cast<int32_t>(operand));
    *dest_reg = static_cast<uint32_t>(result & 0xFFFFFFFF);
    if (result == static_cast<int64_t>(static_cast<int32_t>(*dest_reg))) {
        regs.EFLAGS &= ~CF_FLAG;
        regs.EFLAGS &= ~OF_FLAG;
    }
    else {
        regs.EFLAGS |= CF_FLAG;
        regs.EFLAGS |= OF_FLAG;
    }
    update_ZF_FLAG(*dest_reg);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IMUL r32, r/m32.");
}
void Emulator::instr_INC_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t value;
    if (operand.is_memory) {
        value = read_memory_byte(operand.address);
        value++;
        write_memory_byte(operand.address, value);
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        (*reg)++;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INC r/m8.");
}
void Emulator::instr_DEC_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t value;
    if (operand.is_memory) {
        value = read_memory_byte(operand.address);
        value--;
        write_memory_byte(operand.address, value);
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        (*reg)--;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: DEC r/m8.");
}
void Emulator::instr_SUB_rm32_imm32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t imm32 = fetch_dword();
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value -= imm32;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        (*reg) -= imm32;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SUB r/m32, imm32.");
}
void Emulator::instr_OR_rm32_r32() {
    uint8_t modrm = fetch_byte();
    Operand dest = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* src_reg = get_register_by_code(reg_code);
    uint32_t value;
    if (dest.is_memory) {
        value = read_memory_dword(dest.address);
        value |= *src_reg;
        write_memory_dword(dest.address, value);
    }
    else {
        uint32_t* dest_reg = get_register_by_code(dest.register_code);
        *dest_reg |= *src_reg;
        value = *dest_reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: OR r/m32, r32.");
}
void Emulator::instr_AND_rm32_r32() {
    uint8_t modrm = fetch_byte();
    Operand dest = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* src_reg = get_register_by_code(reg_code);
    uint32_t value;
    if (dest.is_memory) {
        value = read_memory_dword(dest.address);
        value &= *src_reg;
        write_memory_dword(dest.address, value);
    }
    else {
        uint32_t* dest_reg = get_register_by_code(dest.register_code);
        *dest_reg &= *src_reg;
        value = *dest_reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: AND r/m32, r32.");
}
void Emulator::instr_XOR_rm32_r32() {
    uint8_t modrm = fetch_byte();
    Operand dest = decode_operand(modrm);
    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint32_t* src_reg = get_register_by_code(reg_code);
    uint32_t value;
    if (dest.is_memory) {
        value = read_memory_dword(dest.address);
        value ^= *src_reg;
        write_memory_dword(dest.address, value);
    }
    else {
        uint32_t* dest_reg = get_register_by_code(dest.register_code);
        *dest_reg ^= *src_reg;
        value = *dest_reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: XOR r/m32, r32.");
}
void Emulator::instr_ROL_rm32_imm8(uint8_t modrm, uint8_t imm8) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value = (value << imm8) | (value >> (32 - imm8));
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg = (*reg << imm8) | (*reg >> (32 - imm8));
        value = *reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ROL r/m32, imm8.");
}
void Emulator::instr_ROR_rm32_imm8(uint8_t modrm, uint8_t imm8) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value = (value >> imm8) | (value << (32 - imm8));
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg = (*reg >> imm8) | (*reg << (32 - imm8));
        value = *reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ROR r/m32, imm8.");
}
void Emulator::instr_SAR_rm32_imm8(uint8_t modrm, uint8_t imm8) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value = static_cast<int32_t>(value) >> imm8;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg = static_cast<int32_t>(*reg) >> imm8;
        value = *reg;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SAR r/m32, imm8.");
}
void Emulator::instr_SHL_rm32_imm8(uint8_t modrm, uint8_t imm8) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value <<= imm8;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg <<= imm8;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SHL r/m32, imm8.");
}
void Emulator::instr_SHR_rm32_imm8(uint8_t modrm, uint8_t imm8) {
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value >>= imm8;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        *reg >>= imm8;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SHR r/m32, imm8.");
}
void Emulator::instr_SHR_rm32_imm8() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint8_t imm8 = fetch_byte();
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value >>= imm8;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        (*reg) >>= imm8;
        value = *reg;
    }
    update_ZF_FLAG(value);
}
void Emulator::instr_JMP_rel16() {
    int16_t rel16 = static_cast<int16_t>(fetch_word());
    regs.EIP += rel16;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JMP rel16.");
}
void Emulator::instr_JZ_rel8() {
    int8_t rel8 = static_cast<int8_t>(fetch_byte());
    if (regs.EFLAGS & ZF_FLAG) {
        regs.EIP += rel8;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JZ rel8.");
}
void Emulator::instr_JNZ_rel8() {
    int8_t rel8 = static_cast<int8_t>(fetch_byte());
    if (!(regs.EFLAGS & ZF_FLAG)) {
        regs.EIP += rel8;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JNZ rel8.");
}
void Emulator::instr_CLC() {
    regs.EFLAGS &= ~CF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CLC.");
}
void Emulator::instr_STC() {
    regs.EFLAGS |= CF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: STC.");
}
void Emulator::instr_CLI() {
    regs.EFLAGS &= ~IF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: CLI.");
}
void Emulator::instr_STI() {
    regs.EFLAGS |= IF_FLAG;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: STI.");
}
void Emulator::instr_HLT() {
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: HLT. Stopping emulator.");
    running = false;
}
void Emulator::instr_INC_DEC_group() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    switch (reg_opcode) {
    case 0:
        instr_INC_rm8(modrm);
        break;
    case 1:
        instr_DEC_rm8(modrm);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported operation in group 0xFE: " + std::to_string(reg_opcode));
        error_flag = true;
        running = false;
        break;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INC/DEC group.");
}
void Emulator::instr_GROUP2_Ev_Ib() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    uint8_t imm8 = fetch_byte();
    switch (reg_opcode) {
    case 0:
        instr_ROL_rm32_imm8(modrm, imm8);
        break;
    case 1:
        instr_ROR_rm32_imm8(modrm, imm8);
        break;
    case 4:
        instr_SHL_rm32_imm8(modrm, imm8);
        break;
    case 5:
        instr_SHR_rm32_imm8(modrm, imm8);
        break;
    case 7:
        instr_SAR_rm32_imm8(modrm, imm8);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported operation in group 0xC1: " + std::to_string(reg_opcode));
        error_flag = true;
        running = false;
        break;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: GROUP2 Ev, Ib.");
}
void Emulator::instr_INT3() {
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: INT3. Breakpoint encountered.");
    running = false;
}
void Emulator::instr_MUL_r32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        value = *reg;
    }
    uint64_t result = static_cast<uint64_t>(regs.EAX) * value;
    regs.EAX = static_cast<uint32_t>(result & 0xFFFFFFFF);
    regs.EDX = static_cast<uint32_t>((result >> 32) & 0xFFFFFFFF);
    if (regs.EDX != 0) {
        regs.EFLAGS |= CF_FLAG | OF_FLAG;
    }
    else {
        regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MUL r32.");
}
void Emulator::instr_ADD_rm32_imm32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t imm32 = fetch_dword();
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
        value += imm32;
        write_memory_dword(operand.address, value);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        (*reg) += imm32;
        value = *reg;
    }
    update_ZF_FLAG(value);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: ADD r/m32, imm32.");
}
void Emulator::instr_LOOP_rel8() {
    int8_t rel8 = static_cast<int8_t>(fetch_byte());
    regs.ECX -= 1;
    if (regs.ECX != 0) {
        regs.EIP += rel8;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: LOOP rel8.");
}
void Emulator::instr_JECXZ_rel8() {
    int8_t rel8 = static_cast<int8_t>(fetch_byte());
    if (regs.ECX == 0) {
        regs.EIP += rel8;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JECXZ rel8.");
}
void Emulator::instr_TEST_rm8_imm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t imm8 = fetch_byte();
    uint8_t value;
    if (operand.is_memory) {
        value = read_memory_byte(translate_virtual_address(operand.address));
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in TEST r/m8, imm8.");
            error_flag = true;
            running = false;
            return;
        }
        value = *reg;
    }
    uint8_t result = value & imm8;
    regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    if (result == 0) {
        regs.EFLAGS |= ZF_FLAG;
    }
    else {
        regs.EFLAGS &= ~ZF_FLAG;
    }
    if (result & 0x80) {
        regs.EFLAGS |= SF_FLAG;
    }
    else {
        regs.EFLAGS &= ~SF_FLAG;
    }
    update_PF(result);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: TEST r/m8, imm8.");
}
void Emulator::instr_NOT_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    if (operand.is_memory) {
        uint8_t value = read_memory_byte(translate_virtual_address(operand.address));
        value = ~value;
        write_memory_byte(translate_virtual_address(operand.address), value);
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in NOT r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        *reg = ~(*reg);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: NOT r/m8.");
}
void Emulator::instr_NEG_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t value;
    if (operand.is_memory) {
        value = read_memory_byte(translate_virtual_address(operand.address));
        uint8_t result = -value;
        write_memory_byte(translate_virtual_address(operand.address), result);
        if (value != 0) {
            regs.EFLAGS |= CF_FLAG;
        }
        else {
            regs.EFLAGS &= ~CF_FLAG;
        }
        if (result == 0) {
            regs.EFLAGS |= ZF_FLAG;
        }
        else {
            regs.EFLAGS &= ~ZF_FLAG;
        }
        if (result & 0x80) {
            regs.EFLAGS |= SF_FLAG;
        }
        else {
            regs.EFLAGS &= ~SF_FLAG;
        }
        bool overflow = ((value & result & 0x80) != 0);
        if (overflow) {
            regs.EFLAGS |= OF_FLAG;
        }
        else {
            regs.EFLAGS &= ~OF_FLAG;
        }
        update_PF(result);
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in NEG r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        uint8_t result = -(*reg);
        *reg = result;
        if (*reg != 0) {
            regs.EFLAGS |= CF_FLAG;
        }
        else {
            regs.EFLAGS &= ~CF_FLAG;
        }
        if (result == 0) {
            regs.EFLAGS |= ZF_FLAG;
        }
        else {
            regs.EFLAGS &= ~ZF_FLAG;
        }
        if (result & 0x80) {
            regs.EFLAGS |= SF_FLAG;
        }
        else {
            regs.EFLAGS &= ~SF_FLAG;
        }
        bool overflow = ((*reg) & result & 0x80) != 0;
        if (overflow) {
            regs.EFLAGS |= OF_FLAG;
        }
        else {
            regs.EFLAGS &= ~OF_FLAG;
        }
        update_PF(result);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: NEG r/m8.");
}
void Emulator::instr_MUL_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t value;
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    if (operand.is_memory) {
        value = read_memory_byte(translate_virtual_address(operand.address));
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MUL r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        value = *reg;
    }
    uint16_t result = (*al) * value;
    regs.EAX = (regs.EAX & 0xFFFF0000) | result;
    if (result > 0xFF) {
        regs.EFLAGS |= CF_FLAG | OF_FLAG;
    }
    else {
        regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MUL r/m8.");
}
void Emulator::instr_IMUL_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    int8_t value;
    int8_t al = static_cast<int8_t>(regs.EAX & 0xFF);
    if (operand.is_memory) {
        value = static_cast<int8_t>(read_memory_byte(translate_virtual_address(operand.address)));
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in IMUL r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        value = static_cast<int8_t>(*reg);
    }
    int16_t result = al * value;
    regs.EAX = (regs.EAX & 0xFFFF0000) | static_cast<uint16_t>(result);
    if (result > 127 || result < -128) {
        regs.EFLAGS |= CF_FLAG | OF_FLAG;
    }
    else {
        regs.EFLAGS &= ~(CF_FLAG | OF_FLAG);
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IMUL r/m8.");
}
void Emulator::instr_DIV_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    uint8_t divisor;
    uint16_t ax = regs.EAX & 0xFFFF;
    if (operand.is_memory) {
        divisor = read_memory_byte(translate_virtual_address(operand.address));
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in DIV r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        divisor = *reg;
    }
    if (divisor == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in DIV r/m8.");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t quotient = ax / divisor;
    uint8_t remainder = ax % divisor;
    regs.EAX = (regs.EAX & 0xFFFF0000) | quotient;
    regs.EDX = (regs.EDX & 0xFFFFFF00) | remainder;
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: DIV r/m8.");
}
void Emulator::instr_IDIV_rm8(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    int8_t divisor;
    int16_t ax = static_cast<int16_t>(regs.EAX & 0xFFFF);
    if (operand.is_memory) {
        divisor = static_cast<int8_t>(read_memory_byte(translate_virtual_address(operand.address)));
    }
    else {
        uint8_t* reg = get_register8_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in IDIV r/m8.");
            error_flag = true;
            running = false;
            return;
        }
        divisor = static_cast<int8_t>(*reg);
    }
    if (divisor == 0) {
        Logger::get_instance().log(LogLevel::ERROR, "Division by zero in IDIV r/m8.");
        error_flag = true;
        running = false;
        return;
    }
    int8_t quotient = ax / divisor;
    int8_t remainder = ax % divisor;
    regs.EAX = (regs.EAX & 0xFFFF0000) | static_cast<uint8_t>(quotient);
    regs.EDX = (regs.EDX & 0xFFFFFF00) | static_cast<uint8_t>(remainder);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: IDIV r/m8.");
}
void Emulator::instr_F6() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_opcode = (modrm >> 3) & 0x07;
    switch (reg_opcode) {
    case 0:
        instr_TEST_rm8_imm8(modrm);
        break;
    case 2:
        instr_NOT_rm8(modrm);
        break;
    case 3:
        instr_NEG_rm8(modrm);
        break;
    case 4:
        instr_MUL_rm8(modrm);
        break;
    case 5:
        instr_IMUL_rm8(modrm);
        break;
    case 6:
        instr_DIV_rm8(modrm);
        break;
    case 7:
        instr_IDIV_rm8(modrm);
        break;
    default:
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported operation in group 0xF6: " + std::to_string(reg_opcode));
        error_flag = true;
        running = false;
        return;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: F6 group.");
}
void Emulator::instr_MOV_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    if (mod == 3) {
        uint32_t* src_reg = get_register_by_code(reg);
        uint32_t* dest_reg = get_register_by_code(rm);
        if (src_reg && dest_reg) {
            *dest_reg = *src_reg;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in MOV r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        uint32_t value = read_memory_dword(address);
        uint32_t* reg_ptr = get_register_by_code(reg);
        if (reg_ptr) {
            *reg_ptr = value;
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in MOV r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: MOV r/m32, r32.");
}
void Emulator::instr_SUB_r32_rm32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm);
    uint32_t value;
    if (operand.is_memory) {
        value = read_memory_dword(operand.address);
    }
    else {
        uint32_t* reg = get_register_by_code(operand.register_code);
        if (!reg) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in SUB r32, rm32.");
            error_flag = true;
            running = false;
            return;
        }
        value = *reg;
    }
    uint32_t* reg_ptr = get_register_by_code((modrm >> 3) & 0x07);
    if (!reg_ptr) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown destination register in SUB r32, rm32.");
        error_flag = true;
        running = false;
        return;
    }
    *reg_ptr -= value;
    update_ZF_FLAG(*reg_ptr);
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: SUB r32, rm32.");
}
#include "Emulator.h"
#include <algorithm>
#include <stdexcept>
#include <format>
#include <sstream>
#include "Logger.h"
#include "utils.h"
Emulator::Emulator(size_t memory_size) : memory(0) {
    memory.resize(memory_size, 0);
    ELF_BASE_ADDRESS = 0x08048000;
    initialize_instruction_set();
    regs.EAX = regs.EBX = regs.ECX = regs.EDX = regs.ESI = regs.EDI = 0;
    if (memory_size > 0) {
        regs.ESP = static_cast<uint32_t>(memory_size - 16);
        initialize_stack();
    }
    else {
        regs.ESP = 0;
    }
    regs.CS = regs.DS = regs.SS = regs.ES = regs.FS = regs.GS = ELF_BASE_ADDRESS;
    reset_segment_override();
    current_brk = data_segment_start;
    Logger::get_instance().log(LogLevel::DEBUG, "Emulator initialized with memory size: " + std::to_string(memory_size) + " bytes.");
}
void Emulator::initialize_after_resize() {
    if (memory.size() > 0 && regs.ESP == 0) {
        regs.ESP = static_cast<uint32_t>(memory.size() - 16);
        initialize_stack();
        Logger::get_instance().log(LogLevel::INFO, "Stack initialized after memory resize.");
    }
}
void Emulator::initialize_stack() {
    regs.ESP = STACK_BASE_VADDR;
    uint32_t required_memory_size = STACK_BASE_VADDR - ELF_BASE_ADDRESS;
    if (memory.size() < required_memory_size + STACK_SIZE) {
        memory.resize(required_memory_size + STACK_SIZE, 0);
        Logger::get_instance().log(LogLevel::INFO, "Memory resized to " + std::to_string(required_memory_size + STACK_SIZE) + " bytes to accommodate the stack.");
    }
    Segment stack_seg;
    stack_seg.p_vaddr = STACK_BASE_VADDR;
    stack_seg.p_memsz = STACK_SIZE;
    stack_seg.p_offset = required_memory_size;
    loaded_segments.push_back(stack_seg);
    uint32_t return_address = 0x08048310;
    write_memory_dword(regs.ESP - 4, return_address);
    regs.ESP -= 4;
    Logger::get_instance().log(LogLevel::DEBUG, "Stack initialized at ESP = " + addr_to_hex(regs.ESP));
}
void Emulator::resize_memory(uint32_t new_size) {
    if (new_size > memory.size()) {
        memory.resize(new_size, 0);
        Logger::get_instance().log(LogLevel::INFO, "Memory resized to " + std::to_string(new_size) + " bytes.");
    }
}
uint32_t Emulator::allocate_memory(uint32_t addr, uint32_t length) {
    uint32_t new_addr = current_brk;
    current_brk += length;
    if (current_brk > memory.size()) {
        resize_memory(current_brk);
        Logger::get_instance().log(LogLevel::DEBUG, "Allocated memory up to " + addr_to_hex(current_brk));
    }
    return new_addr;
}
void Emulator::write_memory(uint32_t address, const uint8_t* data, size_t size) {
    if (address + size > memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Attempted to write beyond memory bounds. Address: " + addr_to_hex(address) + ", Size: " + std::to_string(size));
        error_flag = true;
        running = false;
        return;
    }
    std::memcpy(&memory[address], data, size);
    Logger::get_instance().log(LogLevel::DEBUG, "Wrote " + std::to_string(size) + " bytes to address " + addr_to_hex(address));
}
void Emulator::set_eip(uint32_t address) {
    try {
        uint32_t physical_address = translate_virtual_address(address);
        regs.EIP = address;
        Logger::get_instance().log(LogLevel::INFO, "EIP set to virtual address " + addr_to_hex(regs.EIP) + ", physical address " + addr_to_hex(physical_address));
    }
    catch (const std::runtime_error& e) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to set EIP to address " + addr_to_hex(address) + ": " + e.what());
        error_flag = true;
        running = false;
    }
}
void Emulator::load_program(const std::vector<uint8_t>& program, uint32_t segment_vaddr, uint32_t segment_offset, bool set_eip_flag) {
    uint32_t required_memory_size = segment_offset + program.size();
    if (required_memory_size > memory.size()) {
        memory.resize(required_memory_size, 0);
        Logger::get_instance().log(LogLevel::INFO, "Memory resized to " + std::to_string(required_memory_size) + " bytes to load the program.");
    }
    std::copy(program.begin(), program.end(), memory.begin() + segment_offset);
    Logger::get_instance().log(LogLevel::DEBUG, "Program loaded at segment offset " + addr_to_hex(segment_offset) + " with size " + std::to_string(program.size()) + " bytes.");
    bool segment_exists = false;
    for (const auto& seg : loaded_segments) if (seg.p_vaddr == segment_vaddr) { segment_exists = true; break; }
    if (!segment_exists) {
        Segment seg; seg.p_vaddr = segment_vaddr; seg.p_memsz = program.size(); seg.p_offset = segment_offset; loaded_segments.push_back(seg);
        Logger::get_instance().log(LogLevel::DEBUG, "New segment added: vaddr=" + addr_to_hex(seg.p_vaddr) + ", size=" + std::to_string(seg.p_memsz) + " bytes.");
    }
    if (set_eip_flag) {
        if (segment_vaddr >= ELF_BASE_ADDRESS && (segment_vaddr - ELF_BASE_ADDRESS) < memory.size()) {
            regs.EIP = segment_vaddr;
            Logger::get_instance().log(LogLevel::INFO, "EIP set to program entry point at " + addr_to_hex(regs.EIP));
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Ошибка: Установка EIP за пределами памяти. Адрес: " + addr_to_hex(segment_vaddr));
            error_flag = true;
            running = false;
        }
    }
}
void Emulator::run() {
    running = true;
    Logger::get_instance().log(LogLevel::INFO, "Emulation started.");
    while (running) {
        try {
            bool prefix_present;
            do {
                prefix_present = false;
                uint8_t prefix = fetch_byte();
                switch (prefix) {
                case 0xF0: regs.lock_prefix = true; prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "LOCK prefix detected."); break;
                case 0xF2: regs.repne_prefix = true; prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "REPNE prefix detected."); break;
                case 0xF3: regs.rep_prefix = true; prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "REP prefix detected."); break;
                case 0x2E: case 0x36: case 0x3E: case 0x26: case 0x64: case 0x65: set_segment_override(prefix); prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "Segment override prefix detected: 0x" + byte_to_hex(prefix)); break;
                case 0x66: regs.operand_size_override = true; prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "Operand-size override prefix detected."); break;
                case 0x67: regs.address_size_override = true; prefix_present = true; Logger::get_instance().log(LogLevel::DEBUG, "Address-size override prefix detected."); break;
                default: regs.EIP--; prefix_present = false; break;
                }
            } while (prefix_present);
            uint8_t opcode = fetch_byte();
            Logger::get_instance().log(LogLevel::DEBUG, "Fetched opcode: 0x" + byte_to_hex(opcode));
            if (opcode == 0x0F) {
                uint8_t ext_opcode = fetch_byte();
                Logger::get_instance().log(LogLevel::DEBUG, "Fetched extended opcode: 0x" + byte_to_hex(ext_opcode));
                auto it = extended_instruction_set.find(ext_opcode);
                if (it != extended_instruction_set.end()) (this->*(it->second))();
                else { Logger::get_instance().log(LogLevel::ERROR, "Unknown extended opcode: 0x0F 0x" + byte_to_hex(ext_opcode)); error_flag = true; running = false; }
            }
            else {
                auto it = instruction_set.find(opcode);
                if (it != instruction_set.end()) (this->*(it->second))();
                else { Logger::get_instance().log(LogLevel::ERROR, "Unknown opcode: 0x" + byte_to_hex(opcode)); error_flag = true; running = false; }
            }
            reset_prefixes();
        }
        catch (const std::exception& e) {
            Logger::get_instance().log(LogLevel::ERROR, std::string("Exception caught: ") + e.what());
            error_flag = true;
            running = false;
        }
    }
    Logger::get_instance().log(LogLevel::INFO, "Emulation stopped.");
}
void Emulator::print_registers(bool hex_output) const {
    std::ostringstream oss;
    if (hex_output) {
        oss << std::hex << "EAX: 0x" << regs.EAX << ", " << "EBX: 0x" << regs.EBX << ", " << "ECX: 0x" << regs.ECX << ", " << "EDX: 0x" << regs.EDX << ", " << "ESI: 0x" << regs.ESI << ", " << "EDI: 0x" << regs.EDI << ", " << "ESP: 0x" << regs.ESP << ", " << "EBP: 0x" << regs.EBP << ", " << "EIP: 0x" << regs.EIP << ", " << "EFLAGS: 0x" << regs.EFLAGS << std::dec;
    }
    else {
        oss << "EAX: " << regs.EAX << ", " << "EBX: " << regs.EBX << ", " << "ECX: " << regs.ECX << ", " << "EDX: " << regs.EDX << ", " << "ESI: " << regs.ESI << ", " << "EDI: " << regs.EDI << ", " << "ESP: " << regs.ESP << ", " << "EBP: " << regs.EBP << ", " << "EIP: " << regs.EIP << ", " << "EFLAGS: " << regs.EFLAGS;
    }
    Logger::get_instance().log(LogLevel::INFO, "Register States: " + oss.str());
}
void Emulator::reset_prefixes() {
    regs.lock_prefix = false;
    regs.rep_prefix = false;
    regs.repne_prefix = false;
    regs.operand_size_override = false;
    regs.address_size_override = false;
}
void Emulator::reset_segment_override() {
    current_data_segment = &regs.DS;
    current_code_segment = &regs.CS;
    Logger::get_instance().log(LogLevel::DEBUG, "Segment overrides reset to default segments.");
}
void Emulator::set_segment_override(uint8_t prefix) {
    switch (prefix) {
    case 0x2E: current_code_segment = &regs.CS; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: CS"); break;
    case 0x36: current_data_segment = &regs.SS; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: SS"); break;
    case 0x3E: current_data_segment = &regs.DS; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: DS"); break;
    case 0x26: current_data_segment = &regs.ES; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: ES"); break;
    case 0x64: current_data_segment = &regs.FS; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: FS"); break;
    case 0x65: current_data_segment = &regs.GS; Logger::get_instance().log(LogLevel::DEBUG, "Segment override: GS"); break;
    default: Logger::get_instance().log(LogLevel::WARNING, "Unknown segment override prefix: 0x" + byte_to_hex(prefix)); break;
    }
}
uint8_t Emulator::fetch_byte() {
    uint32_t virtual_address = regs.EIP;
    uint32_t physical_address;
    try {
        physical_address = translate_virtual_address(virtual_address);
    }
    catch (const std::runtime_error& e) {
        throw std::runtime_error(std::string("EIP out of bounds: ") + e.what());
    }
    if (physical_address >= memory.size()) throw std::runtime_error("Address out of bounds: " + addr_to_hex(physical_address));
    uint8_t byte = memory[physical_address];
    regs.EIP += 1;
    Logger::get_instance().log(LogLevel::DEBUG, "Fetched byte " + byte_to_hex(byte) + " from virtual address " + addr_to_hex(virtual_address) + " (physical address " + addr_to_hex(physical_address) + ")");
    return byte;
}
uint16_t Emulator::fetch_word() {
    uint32_t virtual_address = regs.EIP;
    uint32_t physical_address;
    try {
        physical_address = translate_virtual_address(virtual_address);
    }
    catch (const std::runtime_error& e) {
        throw std::runtime_error(std::string("EIP вне границ памяти: ") + e.what());
    }
    if (physical_address + 2 > memory.size()) throw std::runtime_error("Address out of bounds for word: " + addr_to_hex(physical_address));
    uint16_t value = static_cast<uint16_t>(memory[physical_address]) | (static_cast<uint16_t>(memory[physical_address + 1]) << 8);
    regs.EIP += 2;
    Logger::get_instance().log(LogLevel::DEBUG, "Fetched word 0x" + byte_to_hex(value) + " from physical address " + addr_to_hex(physical_address));
    return value;
}
std::string Emulator::register_name(uint8_t code, bool is_8bit) const {
    if (is_8bit) {
        static const std::string reg_names_8bit[8] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
        if (code < 8) {
            return reg_names_8bit[code];
        }
    }
    else {
        static const std::string reg_names_32bit[8] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
        if (code < 8) {
            return reg_names_32bit[code];
        }
    }
    return "UNKNOWN";
}
uint32_t Emulator::fetch_dword() {
    uint32_t virtual_address = regs.EIP;
    uint32_t physical_address;
    try {
        physical_address = translate_virtual_address(virtual_address);
    }
    catch (const std::runtime_error& e) {
        throw std::runtime_error(std::string("EIP вне границ памяти: ") + e.what());
    }
    if (physical_address + 4 > memory.size()) throw std::runtime_error("Address out of bounds for dword: " + addr_to_hex(physical_address));
    uint32_t value = static_cast<uint32_t>(memory[physical_address]) | (static_cast<uint32_t>(memory[physical_address + 1]) << 8) | (static_cast<uint32_t>(memory[physical_address + 2]) << 16) | (static_cast<uint32_t>(memory[physical_address + 3]) << 24);
    regs.EIP += 4;
    Logger::get_instance().log(LogLevel::DEBUG, "Fetched dword 0x" + byte_to_hex(value) + " from physical address " + addr_to_hex(physical_address));
    return value;
}
uint32_t* Emulator::get_register_by_code(uint8_t code) {
    switch (code) {
    case 0: return &regs.EAX;
    case 1: return &regs.ECX;
    case 2: return &regs.EDX;
    case 3: return &regs.EBX;
    case 4: return &regs.ESP;
    case 5: return &regs.EBP;
    case 6: return &regs.ESI;
    case 7: return &regs.EDI;
    default: return nullptr;
    }
}
uint8_t* Emulator::get_register8_by_code(uint8_t code) {
    switch (code) {
    case 0: return reinterpret_cast<uint8_t*>(&regs.EAX);
    case 1: return reinterpret_cast<uint8_t*>(&regs.ECX);
    case 2: return reinterpret_cast<uint8_t*>(&regs.EDX);
    case 3: return reinterpret_cast<uint8_t*>(&regs.EBX);
    case 4: return reinterpret_cast<uint8_t*>(&regs.EAX) + 1;
    case 5: return reinterpret_cast<uint8_t*>(&regs.ECX) + 1;
    case 6: return reinterpret_cast<uint8_t*>(&regs.EDX) + 1;
    case 7: return reinterpret_cast<uint8_t*>(&regs.EBX) + 1;
    default: return nullptr;
    }
}
uint8_t Emulator::regm_rm(uint8_t modrm) {
    return modrm & 0x07;
}
uint32_t Emulator::translate_virtual_address(uint32_t virtual_addr) const {
    Logger::get_instance().log(LogLevel::DEBUG, "Translating virtual address: " + addr_to_hex(virtual_addr));
    for (const auto& segment : loaded_segments) {
        if (virtual_addr >= segment.p_vaddr && virtual_addr < (segment.p_vaddr + segment.p_memsz)) {
            uint32_t physical_address = virtual_addr - segment.p_vaddr + segment.p_offset;
            if (physical_address >= memory.size()) throw std::runtime_error("Physical address out of bounds during translation.");
            Logger::get_instance().log(LogLevel::DEBUG, "Translated virtual address " + addr_to_hex(virtual_addr) + " to physical address " + addr_to_hex(physical_address));
            return physical_address;
        }
    }
    Logger::get_instance().log(LogLevel::ERROR, "Virtual address " + addr_to_hex(virtual_addr) + " does not map to any loaded segment.");
    throw std::runtime_error("Virtual address " + addr_to_hex(virtual_addr) + " does not map to any loaded segment.");
}
void Emulator::set_elf_base_address(uint32_t address) {
    ELF_BASE_ADDRESS = address;
    Logger::get_instance().log(LogLevel::INFO, "ELF_BASE_ADDRESS установлен на " + addr_to_hex(ELF_BASE_ADDRESS));
}
void Emulator::write_memory_dword(uint32_t address, uint32_t value) {
    if (address + 3 >= memory.size()) {
        memory.resize(address + 4, 0);
        Logger::get_instance().log(LogLevel::WARNING, "Memory resized to " + std::to_string(address + 4) + " bytes to accommodate dword write.");
    }
    memory[address] = value & 0xFF;
    memory[address + 1] = (value >> 8) & 0xFF;
    memory[address + 2] = (value >> 16) & 0xFF;
    memory[address + 3] = (value >> 24) & 0xFF;
    Logger::get_instance().log(LogLevel::DEBUG, "Wrote dword 0x" + byte_to_hex(value) + " to address " + addr_to_hex(address));
}
void Emulator::write_memory_byte(uint32_t address, uint8_t value) {
    if (address >= memory.size()) {
        memory.resize(address + 1, 0);
        Logger::get_instance().log(LogLevel::WARNING, "Memory resized to " + std::to_string(address + 1) + " bytes to accommodate byte write.");
    }
    memory[address] = value;
    Logger::get_instance().log(LogLevel::DEBUG, "Wrote byte 0x" + byte_to_hex(value) + " to address " + addr_to_hex(address));
}
uint8_t Emulator::read_memory_byte(uint32_t virtual_addr) {
    uint32_t physical_address = translate_virtual_address(virtual_addr);
    if (physical_address >= memory.size()) {
        Logger::get_instance().log(LogLevel::ERROR, "Memory access out of bounds in read_memory_byte at virtual address " + addr_to_hex(virtual_addr) + " (physical address " + addr_to_hex(physical_address) + ").");
        error_flag = true;
        running = false;
        return 0;
    }
    uint8_t value = memory[physical_address];
    Logger::get_instance().log(LogLevel::DEBUG, "Read byte 0x" + byte_to_hex(value) + " from address " + addr_to_hex(virtual_addr) + " (physical address " + addr_to_hex(physical_address) + ")");
    return value;
}
uint32_t Emulator::read_memory_dword(uint32_t address) const {
    if (address + 3 >= memory.size()) {
        Logger::get_instance().log(LogLevel::WARNING, "Attempted to read dword from out-of-bounds address " + addr_to_hex(address));
        return 0;
    }
    uint32_t value = 0;
    value |= static_cast<uint32_t>(memory[address]);
    value |= static_cast<uint32_t>(memory[address + 1]) << 8;
    value |= static_cast<uint32_t>(memory[address + 2]) << 16;
    value |= static_cast<uint32_t>(memory[address + 3]) << 24;
    Logger::get_instance().log(LogLevel::DEBUG, "Read dword 0x" + byte_to_hex(value) + " from address " + addr_to_hex(address));
    return value;
}
uint32_t Emulator::calculate_sib_address(uint8_t mod, uint8_t sib, int32_t displacement) {
    uint8_t scale = (sib >> 6) & 0x03, index = (sib >> 3) & 0x07, base = sib & 0x07;
    uint32_t base_value = (base == 5 && mod == 0) ? 0 : *get_register_by_code(base);
    uint32_t index_value = (index != 4) ? (*get_register_by_code(index) << scale) : 0;
    uint32_t address = base_value + index_value + displacement;
    Logger::get_instance().log(LogLevel::DEBUG, "Calculated SIB address: base=" + addr_to_hex(base_value) + ", index=" + addr_to_hex(index_value) + ", displacement=" + std::to_string(displacement) + ", resulting address=" + addr_to_hex(address));
    return address;
}
uint32_t Emulator::calculate_address(uint8_t modrm) {
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t rm = modrm & 0x07;
    uint32_t effective_address = 0;
    if (rm == 4) { 
        uint8_t sib = fetch_byte();
        int32_t displacement = 0;
        if (mod == 0 && (sib & 0x07) == 5) {
            displacement = static_cast<int32_t>(fetch_dword());
        }
        else if (mod == 1) {
            displacement = static_cast<int32_t>(static_cast<int8_t>(fetch_byte()));
        }
        else if (mod == 2) {
            displacement = static_cast<int32_t>(fetch_dword());
        }
        effective_address = calculate_sib_address(mod, sib, displacement);
    }
    else {
        int32_t displacement = 0;
        if (mod == 0 && rm == 5) {
            displacement = static_cast<int32_t>(fetch_dword());
            effective_address = displacement;
        }
        else if (mod == 1) {
            displacement = static_cast<int32_t>(static_cast<int8_t>(fetch_byte()));
            effective_address = *get_register_by_code(rm) + displacement;
        }
        else if (mod == 2) {
            displacement = static_cast<int32_t>(fetch_dword());
            effective_address = *get_register_by_code(rm) + displacement;
        }
        else { 
            effective_address = *get_register_by_code(rm);
        }
    }
    uint32_t segment_base = *current_data_segment;
    uint32_t virtual_address = segment_base + effective_address;
    Logger::get_instance().log(LogLevel::DEBUG, "Segment base: " + addr_to_hex(segment_base) + ", Effective address: " + addr_to_hex(effective_address) + ", Virtual address: " + addr_to_hex(virtual_address));
    return virtual_address;
}
void Emulator::set_segment_register(const std::string& segment, uint32_t value) {
    if (segment == "CS") regs.CS = value;
    else if (segment == "DS") regs.DS = value;
    else if (segment == "SS") regs.SS = value;
    else if (segment == "ES") regs.ES = value;
    else if (segment == "FS") regs.FS = value;
    else if (segment == "GS") regs.GS = value;
    else { Logger::get_instance().log(LogLevel::ERROR, "Unknown segment register: " + segment); return; }
    Logger::get_instance().log(LogLevel::INFO, "Segment register " + segment + " set to " + addr_to_hex(value));
}
Emulator::Operand Emulator::decode_operand(uint8_t modrm) {
    Operand operand;
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t rm = modrm & 0x07;
    if (mod == 3) {
        operand.is_memory = false;
        operand.register_code = rm;
    }
    else {
        operand.is_memory = true;
        operand.address = calculate_address(modrm);
        operand.register_code = 0; 
    }
    Logger::get_instance().log(LogLevel::DEBUG, "Decoded operand: is_memory=" + std::to_string(operand.is_memory) + ", address=" + (operand.is_memory ? addr_to_hex(operand.address) : "N/A") + ", register_code=" + std::to_string(operand.register_code));
    return operand;
}
void Emulator::initialize_instruction_set() {
    instruction_set[0x00] = &Emulator::instr_ADD_rm8_r8;
    instruction_set[0x01] = &Emulator::instr_ADD_rm32_r32;
    instruction_set[0x03] = &Emulator::instr_ADD_r32_rm32;
    instruction_set[0x04] = &Emulator::instr_ADD_AL_imm8;
    instruction_set[0x05] = &Emulator::instr_ADD_EAX_imm32;
    instruction_set[0x09] = &Emulator::instr_OR_rm32_r32;
    instruction_set[0x0D] = &Emulator::instr_OR_EAX_imm32;
    instruction_set[0x0E] = &Emulator::instr_OR_ECX_imm32;
    instruction_set[0x20] = &Emulator::instr_AND_rm8_r8;
    instruction_set[0x21] = &Emulator::instr_AND_rm32_r32;
    instruction_set[0x25] = &Emulator::instr_AND_EAX_imm32;
    instruction_set[0x29] = &Emulator::instr_SUB_r32_rm32;
    instruction_set[0x2C] = &Emulator::instr_SUB_AL_imm8;
    instruction_set[0x2D] = &Emulator::instr_SUB_EAX_imm32;
    instruction_set[0x31] = &Emulator::instr_XOR_r32_rm32;
    instruction_set[0x33] = &Emulator::instr_XOR_r32_rm32;
    instruction_set[0x34] = &Emulator::instr_XOR_AL_imm8;
    instruction_set[0x35] = &Emulator::instr_XOR_EAX_imm32;
    instruction_set[0x39] = &Emulator::instr_CMP_r32_rm32;
    instruction_set[0x3C] = &Emulator::instr_CMP_AL_imm8;
    instruction_set[0x3D] = &Emulator::instr_CMP_EAX_imm32;
    instruction_set[0x40] = &Emulator::instr_INC_EAX;
    instruction_set[0x41] = &Emulator::instr_INC_ECX;
    instruction_set[0x48] = &Emulator::instr_DEC_EAX;
    instruction_set[0x50] = &Emulator::instr_PUSH_EAX;
    instruction_set[0x51] = &Emulator::instr_PUSH_ECX;
    instruction_set[0x52] = &Emulator::instr_PUSH_EDX;
    instruction_set[0x53] = &Emulator::instr_PUSH_EBX;
    instruction_set[0x54] = &Emulator::instr_PUSH_ESP;
    instruction_set[0x55] = &Emulator::instr_PUSH_EBP;
    instruction_set[0x56] = &Emulator::instr_PUSH_ESI;
    instruction_set[0x57] = &Emulator::instr_PUSH_EDI;
    instruction_set[0x58] = &Emulator::instr_POP_EAX;
    instruction_set[0x59] = &Emulator::instr_POP_ECX;
    instruction_set[0x5A] = &Emulator::instr_POP_EDX;
    instruction_set[0x5B] = &Emulator::instr_POP_EBX;
    instruction_set[0x5C] = &Emulator::instr_POP_ESP;
    instruction_set[0x5D] = &Emulator::instr_POP_EBP;
    instruction_set[0x5E] = &Emulator::instr_POP_ESI;
    instruction_set[0x5F] = &Emulator::instr_POP_EDI;
    instruction_set[0x60] = &Emulator::instr_PUSHAD;
    instruction_set[0x68] = &Emulator::instr_PUSH_imm32;
    instruction_set[0x6A] = &Emulator::instr_PUSH_imm8;
    instruction_set[0x69] = &Emulator::instr_IMUL_reg_rm32_imm32;
    instruction_set[0x6B] = &Emulator::instr_IMUL_reg_rm32_imm8;
    instruction_set[0x6C] = &Emulator::instr_INSB;
    instruction_set[0x72] = &Emulator::instr_JB_rel8;
    instruction_set[0x74] = &Emulator::instr_JE_rel8;
    instruction_set[0x75] = &Emulator::instr_JNE_rel8;
    instruction_set[0x77] = &Emulator::instr_JA_rel8;
    instruction_set[0x7C] = &Emulator::instr_JL_rel8;
    instruction_set[0x7F] = &Emulator::instr_JG_rel8;
    instruction_set[0x80] = &Emulator::instr_SUB_rm8_imm8;
    instruction_set[0x81] = &Emulator::instr_GROUP1_Ev_Iz_81;
    instruction_set[0x83] = &Emulator::instr_GROUP1_Ev_Iz_83;
    instruction_set[0x84] = &Emulator::instr_TEST_rm8_r8;
    instruction_set[0x85] = &Emulator::instr_TEST_rm32_r32;
    instruction_set[0x88] = &Emulator::instr_MOV_rm8_r8;
    instruction_set[0x89] = &Emulator::instr_MOV_rm32_r32;
    instruction_set[0x8A] = &Emulator::instr_MOV_r8_rm8;
    instruction_set[0x8B] = &Emulator::instr_MOV_r32_r_m32;
    instruction_set[0x8D] = &Emulator::instr_LEA_r32_m;
    instruction_set[0x90] = &Emulator::instr_NOP;
    instruction_set[0xA1] = &Emulator::instr_MOV_EAX_MEM;
    instruction_set[0xA3] = &Emulator::instr_MOV_MEM_EAX;
    instruction_set[0xA4] = &Emulator::instr_MOVSB;
    instruction_set[0xB7] = &Emulator::instr_MOV_r8_imm8;
    instruction_set[0xB8] = &Emulator::instr_MOV_EAX_imm32;
    instruction_set[0xB9] = &Emulator::instr_MOV_ECX_imm32;
    instruction_set[0xBA] = &Emulator::instr_MOV_EDX_imm32;
    instruction_set[0xBB] = &Emulator::instr_MOV_EBX_imm32;
    instruction_set[0xBC] = &Emulator::instr_MOV_ESP_imm32;
    instruction_set[0xBD] = &Emulator::instr_MOV_EBP_imm32;
    instruction_set[0xBE] = &Emulator::instr_MOV_ESI_imm32;
    instruction_set[0xBF] = &Emulator::instr_MOV_EDI_imm32;
    instruction_set[0xC1] = &Emulator::instr_GROUP2_Ev_Ib;
    instruction_set[0xC2] = &Emulator::instr_RET_near_imm16;
    instruction_set[0xC3] = &Emulator::instr_RET;
    instruction_set[0xC6] = &Emulator::instr_MOV_rm8_imm8;
    instruction_set[0xC7] = &Emulator::instr_MOV_Ev_Iv;
    instruction_set[0xC9] = &Emulator::instr_LEAVE;
    instruction_set[0xCD] = &Emulator::instr_INT;
    instruction_set[0xCC] = &Emulator::instr_INT3;
    instruction_set[0xD0] = &Emulator::instr_GROUP2_Ev_Ib;
    instruction_set[0xE2] = &Emulator::instr_LOOP_rel8;
    instruction_set[0xE3] = &Emulator::instr_JECXZ_rel8;
    instruction_set[0xE8] = &Emulator::instr_CALL_rel32;
    instruction_set[0xE9] = &Emulator::instr_JMP_rel32;
    instruction_set[0xEB] = &Emulator::instr_JMP_rel8;
    instruction_set[0xEC] = &Emulator::instr_IN_AL_DX;
    instruction_set[0xEE] = &Emulator::instr_OUT_DX_AL;
    instruction_set[0xF4] = &Emulator::instr_HLT;
    instruction_set[0xF6] = &Emulator::instr_F6;
    instruction_set[0xF7] = &Emulator::instr_F7;
    instruction_set[0xF8] = &Emulator::instr_CLC;
    instruction_set[0xF9] = &Emulator::instr_STC;
    instruction_set[0xFA] = &Emulator::instr_CLI;
    instruction_set[0xFB] = &Emulator::instr_STI;
    instruction_set[0xFC] = &Emulator::instr_CLD;
    instruction_set[0xFD] = &Emulator::instr_STD;
    instruction_set[0xFE] = &Emulator::instr_INC_DEC_group;
    instruction_set[0xFF] = &Emulator::instr_GROUP5;
    extended_instruction_set[0x1E] = &Emulator::instr_ENDBR32;
    extended_instruction_set[0x44] = &Emulator::instr_CMOVZ;
    extended_instruction_set[0x82] = &Emulator::instr_CMOVB;
    extended_instruction_set[0x84] = &Emulator::instr_JE_rel32;
    extended_instruction_set[0x85] = &Emulator::instr_JNE_rel32;
    extended_instruction_set[0x87] = &Emulator::instr_JA_rel32;
    extended_instruction_set[0x97] = &Emulator::instr_SETA_rm8;
    extended_instruction_set[0x8C] = &Emulator::instr_JL_rel32;
    extended_instruction_set[0x8F] = &Emulator::instr_JG_rel32;
    extended_instruction_set[0xAF] = &Emulator::instr_IMUL_r32_rm32;
    Logger::get_instance().log(LogLevel::DEBUG, "Instruction set initialized with " + std::to_string(instruction_set.size()) + " instructions and " + std::to_string(extended_instruction_set.size()) + " extended instructions.");
}
#include "elf_loader.h"
#include "file_utils.h"
#include "utils.h"
#include "Emulator.h"
#include "elf_structs.h"
#include <fstream>
#include <iostream>
#include <vector>
#include <cstdint>
#include <string>
#include <cstring>
#include "Logger.h"
bool load_elf(const std::string& filename, Emulator& emulator) {
    std::ifstream infile(filename, std::ios::binary);
    if (!infile) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to open ELF file: " + filename);
        return false;
    }
    Elf32_Ehdr ehdr;
    infile.read(reinterpret_cast<char*>(&ehdr), sizeof(Elf32_Ehdr));
    if (!infile) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to read ELF header.");
        return false;
    }
    if (std::memcmp(ehdr.e_ident, "\x7F" "ELF", 4) != 0) {
        Logger::get_instance().log(LogLevel::ERROR, "File is not a valid ELF file.");
        return false;
    }
    infile.seekg(ehdr.e_phoff, std::ios::beg);
    if (!infile) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to seek to program headers.");
        return false;
    }
    std::vector<Elf32_Phdr> phdrs(ehdr.e_phnum);
    infile.read(reinterpret_cast<char*>(phdrs.data()), ehdr.e_phnum * sizeof(Elf32_Phdr));
    if (!infile) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to read program headers.");
        return false;
    }
    uint32_t min_p_vaddr = UINT32_MAX;
    for (const auto& phdr : phdrs) {
        if (phdr.p_type != PT_LOAD)
            continue;
        if (phdr.p_vaddr < min_p_vaddr)
            min_p_vaddr = phdr.p_vaddr;
    }
    if (min_p_vaddr == UINT32_MAX) {
        Logger::get_instance().log(LogLevel::ERROR, "No loadable segments found in ELF file.");
        return false;
    }
    emulator.set_elf_base_address(min_p_vaddr & 0xFFFFF000); 
    for (const auto& phdr : phdrs) {
        if (phdr.p_type != PT_LOAD)
            continue;
        uint32_t required_memory_size = (phdr.p_vaddr - emulator.ELF_BASE_ADDRESS) + phdr.p_memsz;
        if (required_memory_size > emulator.get_memory_size()) {
            emulator.resize_memory(required_memory_size);
            Logger::get_instance().log(LogLevel::INFO, "Resized memory to accommodate segment at 0x" +
                byte_to_hex(phdr.p_vaddr));
        }
        std::vector<uint8_t> segment_data(phdr.p_filesz, 0);
        infile.seekg(phdr.p_offset, std::ios::beg);
        infile.read(reinterpret_cast<char*>(segment_data.data()), phdr.p_filesz);
        if (!infile) {
            Logger::get_instance().log(LogLevel::ERROR, "Failed to read segment data from ELF file.");
            return false;
        }
        uint32_t segment_offset = phdr.p_vaddr - emulator.ELF_BASE_ADDRESS;
        emulator.write_memory(segment_offset, segment_data.data(), phdr.p_filesz);
        if (phdr.p_memsz > phdr.p_filesz) {
            uint32_t bss_size = phdr.p_memsz - phdr.p_filesz;
            std::vector<uint8_t> bss_data(bss_size, 0);
            emulator.write_memory(segment_offset + phdr.p_filesz, bss_data.data(), bss_size);
        }
        Emulator::Segment segment;
        segment.p_vaddr = phdr.p_vaddr;
        segment.p_memsz = phdr.p_memsz;
        segment.p_offset = segment_offset;
        emulator.loaded_segments.push_back(segment);
        Logger::get_instance().log(LogLevel::DEBUG, "Loaded segment: VAddr=0x" +
            byte_to_hex(phdr.p_vaddr) + ", Size=0x" + byte_to_hex(phdr.p_memsz));
    }
    uint32_t return_address = 0x08048310;
    emulator.write_memory_byte(return_address, 0xF4);
    Logger::get_instance().log(LogLevel::DEBUG, "Wrote HLT opcode to return address 0x" + byte_to_hex(return_address));
    bool gs_segment_found = false;
    uint32_t gs_segment_vaddr = 0;
    uint32_t gs_segment_size = 0;
    for (const auto& segment : emulator.loaded_segments) {
        if (segment.p_vaddr <= 0x00000014 && (segment.p_vaddr + segment.p_memsz) > 0x00000014) {
            gs_segment_found = true;
            gs_segment_vaddr = segment.p_vaddr;
            gs_segment_size = segment.p_memsz;
            break;
        }
    }
    if (!gs_segment_found) {
        Emulator::Segment gs_segment;
        gs_segment.p_vaddr = 0x00000000; 
        gs_segment.p_memsz = 0x00000020; 
        gs_segment.p_offset = emulator.loaded_segments.empty() ? 0 : emulator.loaded_segments.back().p_offset + emulator.loaded_segments.back().p_memsz;
        uint32_t required_memory_size = gs_segment.p_offset + gs_segment.p_memsz;
        if (required_memory_size > emulator.get_memory_size()) {
            emulator.resize_memory(required_memory_size);
            Logger::get_instance().log(LogLevel::INFO, "Resized memory to accommodate GS segment at 0x" +
                byte_to_hex(gs_segment.p_vaddr));
        }
        std::vector<uint8_t> gs_data(gs_segment.p_memsz, 0);
        emulator.write_memory(gs_segment.p_offset, gs_data.data(), gs_segment.p_memsz);
        emulator.loaded_segments.push_back(gs_segment);
        Logger::get_instance().log(LogLevel::DEBUG, "Added GS segment: VAddr=0x" +
            byte_to_hex(gs_segment.p_vaddr) + ", Size=0x" + byte_to_hex(gs_segment.p_memsz));
        emulator.set_segment_register("GS", gs_segment.p_vaddr);
    }
    else {
        emulator.set_segment_register("GS", gs_segment_vaddr);
        Logger::get_instance().log(LogLevel::INFO, "GS register set to existing segment: VAddr=0x" +
            byte_to_hex(gs_segment_vaddr));
    }
    emulator.set_eip(ehdr.e_entry);
    emulator.initialize_stack();
    Logger::get_instance().log(LogLevel::INFO, "ELF file loaded successfully. Entry point at EIP=0x" +
        byte_to_hex(ehdr.e_entry));
    return true;
}
#include "elf_loader.h"
#include "file_utils.h"
#include "Emulator.h"
#include "elf_structs.h"
#include "Logger.h"
#include "utils.h"
#include <iostream>
#include <vector>
#include <cstdint>
#include <string>
bool run_program_from_elf(const std::string& filename) {
    Emulator emulator(0);
    bool load_result = load_elf(filename, emulator);
    if (!load_result) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to load ELF file.");
        return false;
    }
    emulator.run();
    if (!emulator.has_error()) {
        Logger::get_instance().log(LogLevel::INFO, "ELF program executed successfully.");
    }
    else {
        Logger::get_instance().log(LogLevel::ERROR, "ELF program execution failed.");
    }
    return !emulator.has_error();
}
int main(int argc, char* argv[]) {
    Logger::get_instance().set_log_level(LogLevel::DEBUG);
    Logger::get_instance().enable_file_logging("emulator.log");
    if (argc > 1) {
        std::string program_filename = argv[1];
        if (program_filename.size() >= 4 &&
            program_filename.substr(program_filename.size() - 4) == ".elf") {
            Logger::get_instance().log(LogLevel::INFO, "Running ELF file: " + program_filename);
            run_program_from_elf(program_filename);
        }
        else {
            Logger::get_instance().log(LogLevel::INFO, "Running flat binary file: " + program_filename);
            Emulator emulator(0);
            std::vector<uint8_t> program = load_program_from_file(program_filename);
            if (program.empty()) {
                Logger::get_instance().log(LogLevel::ERROR, "Failed to load program from file: " + program_filename);
                return -1;
            }
            emulator.load_program(program, 0, 0, true);
            emulator.run();
            if (!emulator.has_error()) {
                Logger::get_instance().log(LogLevel::INFO, "Program executed successfully!");
            }
            else {
                Logger::get_instance().log(LogLevel::ERROR, "Program execution failed.");
            }
        }
    }
    else {
        std::cout << "Usage " + std::string(argv[0]) + " <filename.(elf|bin)>";
    }
    return 0;
}
#ifndef EMULATOR_H
#define EMULATOR_H
#include <vector>
#include <unordered_map>
#include <functional>
#include <cstdint>
#include <string>
class Emulator {
public:
    uint32_t ELF_BASE_ADDRESS; 
    struct Segment {
        uint32_t p_vaddr;
        uint32_t p_memsz;
        uint32_t p_offset;  
    };
    std::vector<Segment> loaded_segments;
    Emulator(size_t memory_size);
    void load_program(const std::vector<uint8_t>& program, uint32_t segment_vaddr, uint32_t segment_offset, bool set_eip);
    void run();
    void print_registers(bool hex_output = false) const;
    bool has_error() const { return error_flag; }
    void write_memory(uint32_t address, const uint8_t* data, size_t size);
    size_t get_memory_size() const { return memory.size(); }
    void resize_memory(uint32_t new_size);
    uint8_t read_memory_byte(uint32_t virtual_addr);
    uint32_t read_memory_dword(uint32_t address) const;
    void write_memory_dword(uint32_t address, uint32_t value);
    void write_memory_byte(uint32_t address, uint8_t value);
    void set_eip(uint32_t address);
    void set_elf_base_address(uint32_t address);
    void set_segment_register(const std::string& segment, uint32_t value);
    void initialize_after_resize();
    uint32_t allocate_memory(uint32_t addr, uint32_t length);
    void initialize_stack();
    static const uint32_t STACK_BASE_VADDR = 0x0804A000; 
    static const uint32_t STACK_SIZE = 0x2000;          
    static const uint32_t STACK_START_VADDR = STACK_BASE_VADDR - STACK_SIZE; 
private:
    struct Operand {
        bool is_memory;
        uint32_t address;
        uint32_t register_code;
    };
    enum SegmentOverride {
        SEGMENT_NONE,
        SEGMENT_CS,
        SEGMENT_DS,
        SEGMENT_SS,
        SEGMENT_ES,
        SEGMENT_FS,
        SEGMENT_GS
    } current_segment_override = SEGMENT_NONE;
    struct Registers {
        uint32_t EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP;
        uint32_t EIP;
        uint32_t EFLAGS;
        uint32_t CS, DS, SS, ES, FS, GS;
        bool lock_prefix = false;
        bool rep_prefix = false;
        bool repne_prefix = false;
        bool operand_size_override = false;
        bool address_size_override = false;
        Registers() : EAX(0), EBX(0), ECX(0), EDX(0),
            ESI(0), EDI(0), ESP(0), EBP(0),
            EIP(0), EFLAGS(0),
            CS(0), DS(0), SS(0), ES(0), FS(0), GS(0) {}
    } regs;
    std::vector<uint8_t> memory;
    bool running = false;
    bool error_flag = false;
    uint32_t current_brk = 0;
    uint32_t data_segment_start = 0x08000000; 
    typedef void (Emulator::* InstructionHandler)();
    std::unordered_map<uint8_t, InstructionHandler> instruction_set;
    std::unordered_map<uint8_t, InstructionHandler> extended_instruction_set;
    void initialize_instruction_set();
    void reset_prefixes();
    void reset_segment_override();
    void set_segment_override(uint8_t prefix);
    const uint32_t CF_FLAG = 1 << 0;    
    const uint32_t PF_FLAG = 1 << 2;    
    const uint32_t AF_FLAG = 1 << 4;    
    const uint32_t ZF_FLAG = 1 << 6;    
    const uint32_t SF_FLAG = 1 << 7;    
    const uint32_t OF_FLAG = 1 << 11;   
    const uint32_t DF_FLAG = 1 << 10;   
    const uint32_t IF_FLAG = 1 << 9;    
    uint32_t* current_data_segment;
    uint32_t* current_code_segment;
    void instr_MOV_Ev_Iv();
    void instr_MOV_EAX_imm32();
    void instr_MOV_EBX_imm32();
    void instr_MOV_ECX_imm32();
    void instr_MOV_EDX_imm32();
    void instr_ADD_EAX_imm32();
    void instr_SUB_EAX_imm32();
    void instr_INC_EAX();
    void instr_DEC_EAX();
    void instr_MUL_EAX();
    void instr_JMP_rel32();
    void instr_CMP_reg_imm8();
    void instr_JE_rel8();
    void instr_JNE_rel8();
    void instr_AND_EAX_imm32();
    void instr_AND_ECX_imm32();
    void instr_OR_EAX_imm32();
    void instr_XOR_EAX_imm32();
    void instr_SUB_r32_imm32();
    void instr_CMP_EAX_imm32();
    void instr_OR_ECX_imm32();
    void instr_RET();
    void instr_MOV_MEM_EAX();
    void instr_MOV_EAX_MEM();
    void instr_CMP_EAX_EBX();
    void instr_JG_rel8();
    void instr_JL_rel8();
    void instr_CMP_r32_rm32();
    void instr_IMUL_reg_rm32_imm32();
    void instr_JB_rel8();
    void instr_JA_rel8();
    void instr_INC_ECX();
    void instr_JMP_rel8();
    void instr_MOV_r8_imm8();
    void instr_SUB_AL_imm8();
    void instr_SUB_rm8_imm8();
    void instr_MOV_rm8_imm8();
    void instr_ADD_AL_imm8();
    void instr_MOV_ESI_imm32();
    void instr_INT();
    void instr_F7();
    void instr_MUL_rm32(uint8_t modrm);
    void instr_DIV_rm32(uint8_t modrm);
    void instr_IDIV_rm32(uint8_t modrm);
    void instr_XOR_r32_rm32();
    void instr_ADD_rm32_r32();
    void instr_CMP_AL_imm8();
    void instr_ADD_r32_rm32();
    void instr_SUB_EBX_imm32();
    void instr_IMUL_reg_rm32_imm8();
    void instr_MOV_r32_r_m32();
    void instr_MOV_EBP_imm32();
    void instr_MOV_ESP_imm32();
    void instr_MOV_EDI_imm32();
    void instr_CALL_rel32();
    void instr_GROUP1_Ev_Iz_81();
    void instr_GROUP1_Ev_Iz_83();
    void instr_LEA_r32_m();
    void instr_MOVSB();
    void instr_JNE_rel32();
    void instr_JG_rel32();
    void instr_JE_rel32();
    void instr_NOP_EAX();
    void instr_NOP_m16_m32();
    void instr_JL_rel32();
    void instr_ENDBR32();
    void instr_PUSH_EDI();
    void instr_PUSH_ESI();
    void instr_PUSH_EBP();
    void instr_PUSH_EBX();
    void instr_PUSH_EDX();
    void instr_PUSH_ECX();
    void instr_PUSH_EAX();
    void instr_PUSH_ESP();
    void instr_POP_EAX();
    void instr_POP_ECX();
    void instr_POP_EDX();
    void instr_POP_EBX();
    void instr_POP_ESP();
    void instr_POP_EBP();
    void instr_POP_ESI();
    void instr_POP_EDI();
    void instr_PUSH_imm8();
    void instr_GROUP5();
    void instr_INC_rm32(uint8_t modrm);
    void instr_DEC_rm32(uint8_t modrm);
    void instr_JMP_rm32(uint8_t modrm);
    void instr_PUSH_rm32(uint8_t modrm);
    void instr_PUSH_imm32();
    void instr_ADD_rm8_r8();
    void instr_NOP();
    void instr_PUSHAD();
    void instr_REP_MOVSB();
    void instr_XOR_AL_imm8();
    void instr_LEAVE();
    void instr_AND_rm8_r8();
    void instr_NOT_rm32(uint8_t modrm);
    void instr_TEST_rm32_r32();
    void instr_INSB();
    void instr_IMUL_r32_rm32();
    void instr_INC_DEC_group();
    void instr_GROUP2_Ev_Ib();
    void instr_F6();
    void instr_LOOP_rel8();
    void instr_JECXZ_rel8();
    void instr_SUB_r32_rm32();
    void instr_JA_rel32();
    void instr_CMOVZ();
    void instr_SETA_rm8();
    void instr_SETcc(uint8_t condition_code);
    void instr_CMOVB();
    void instr_TEST_rm8_r8();
    void instr_ROL_rm32_imm8(uint8_t modrm, uint8_t imm8);
    void instr_ROR_rm32_imm8(uint8_t modrm, uint8_t imm8);
    void instr_SAR_rm32_imm8(uint8_t modrm, uint8_t imm8);
    void instr_SHL_rm32_imm8(uint8_t modrm, uint8_t imm8);
    void instr_SHR_rm32_imm8(uint8_t modrm, uint8_t imm8);
    void instr_TEST_rm8_imm8(uint8_t modrm);
    void instr_NEG_rm8(uint8_t modrm);
    void instr_MUL_rm8(uint8_t modrm);
    void instr_IMUL_rm8(uint8_t modrm);
    void instr_DIV_rm8(uint8_t modrm);
    void instr_IDIV_rm8(uint8_t modrm);
    void instr_INC_rm8(uint8_t modrm);
    void instr_DEC_rm8(uint8_t modrm);
    void instr_ADD_rm32_imm32();
    void instr_SUB_rm32_imm32();
    void instr_MUL_r32();
    void instr_IMUL_r32();
    void instr_DIV_r32();
    void instr_IDIV_r32();
    void instr_OR_rm32_r32();
    void instr_AND_rm32_r32();
    void instr_XOR_rm32_r32();
    void instr_NOT_rm8(uint8_t modrm);
    void instr_ROR_rm32_imm8();
    void instr_SHL_rm32_imm8();
    void instr_SHR_rm32_imm8();
    void instr_JMP_rel16();
    void instr_JZ_rel8();
    void instr_JNZ_rel8();
    void instr_CALL_rm32(uint8_t modrm);
    void instr_RET_near_imm16();
    void instr_CLC();
    void instr_STC();
    void instr_CLI();
    void instr_STI();
    void instr_CLD();
    void instr_STD();
    void instr_PUSHF();
    void instr_POPF();
    void instr_IN_AL_DX();
    void instr_OUT_DX_AL();
    void instr_MOV_rm32_r32();
    void instr_MOV_r32_rm32();
    void instr_MOV_rm16_r16();
    void instr_MOV_r16_rm16();
    void instr_MOV_rm8_r8();
    void instr_MOV_r8_rm8();
    void instr_MOV_r8_r8();
    void instr_LEA();
    void instr_HLT();
    void instr_INT3();
    std::string register_name(uint8_t code, bool is_8bit) const;
    uint8_t fetch_byte();
    uint32_t fetch_dword();
    uint16_t fetch_word();
    uint32_t* get_register_by_code(uint8_t code);
    uint8_t* get_register8_by_code(uint8_t code);
    uint8_t regm_rm(uint8_t modrm);
    uint32_t calculate_address(uint8_t modrm);
    uint32_t calculate_sib_address(uint8_t mod, uint8_t sib, int32_t displacement);
    void update_ZF_FLAG(uint32_t result);
    void update_PF(uint8_t result);
    void push(uint32_t value);
    uint32_t translate_virtual_address(uint32_t virtual_addr) const;
    Operand decode_operand(uint8_t modrm);
    void sys_read();
};
#endif 
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
#include "Emulator.h"
#include "elf_structs.h"
#include <string>
#include <vector>
bool load_elf(const std::string& filename, Emulator& emulator);
#endif 
#ifndef ELF_STRUCTS_H
#define ELF_STRUCTS_H
#include <cstdint>
#pragma pack(push, 1)
struct Elf32_Ehdr {
    unsigned char e_ident[16]; 
    uint16_t e_type;           
    uint16_t e_machine;        
    uint32_t e_version;        
    uint32_t e_entry;          
    uint32_t e_phoff;          
    uint32_t e_shoff;          
    uint32_t e_flags;          
    uint16_t e_ehsize;         
    uint16_t e_phentsize;      
    uint16_t e_phnum;          
    uint16_t e_shentsize;      
    uint16_t e_shnum;          
    uint16_t e_shstrndx;       
};
struct Elf32_Phdr {
    uint32_t p_type;    
    uint32_t p_offset;  
    uint32_t p_vaddr;   
    uint32_t p_paddr;   
    uint32_t p_filesz;  
    uint32_t p_memsz;   
    uint32_t p_flags;   
    uint32_t p_align;   
};
#pragma pack(pop)
#define PT_NULL    0
#define PT_LOAD    1
#define PT_DYNAMIC 2
#define PT_INTERP  3
#define PT_NOTE    4
#define PT_SHLIB   5
#define PT_PHDR    6
static_assert(sizeof(Elf32_Ehdr) == 52, "Elf32_Ehdr размер некорректен");
static_assert(sizeof(Elf32_Phdr) == 32, "Elf32_Phdr размер некорректен");
#endif 
C:\Users\Swed\source\repos\x86_Emulator\x64\Debug>x86_Emulator.exe hello_world_c.elf
2024-10-12 15:11:42.462 [INFO] JE taken. Jumping to 0x805c0c0.
2024-10-12 15:11:42.462 [DEBUG] Translating virtual address: 0x805c0c0
2024-10-12 15:11:42.462 [DEBUG] Translated virtual address 0x805c0c0 to physical address 0x140c0
2024-10-12 15:11:42.462 [DEBUG] Fetched byte 65 from virtual address 0x805c0c0 (physical address 0x140c0)
2024-10-12 15:11:42.462 [DEBUG] Segment override: GS
2024-10-12 15:11:42.462 [DEBUG] Segment override prefix detected: 0x65
2024-10-12 15:11:42.462 [DEBUG] Translating virtual address: 0x805c0c1
2024-10-12 15:11:42.462 [DEBUG] Translated virtual address 0x805c0c1 to physical address 0x140c1
2024-10-12 15:11:42.462 [DEBUG] Fetched byte 80 from virtual address 0x805c0c1 (physical address 0x140c1)
2024-10-12 15:11:42.462 [DEBUG] Translating virtual address: 0x805c0c1
2024-10-12 15:11:42.462 [DEBUG] Translated virtual address 0x805c0c1 to physical address 0x140c1
2024-10-12 15:11:42.462 [DEBUG] Fetched byte 80 from virtual address 0x805c0c1 (physical address 0x140c1)
2024-10-12 15:11:42.462 [DEBUG] Fetched opcode: 0x80
2024-10-12 15:11:42.462 [DEBUG] Translating virtual address: 0x805c0c2
2024-10-12 15:11:42.462 [DEBUG] Translated virtual address 0x805c0c2 to physical address 0x140c2
2024-10-12 15:11:42.462 [DEBUG] Fetched byte 3D from virtual address 0x805c0c2 (physical address 0x140c2)
2024-10-12 15:11:42.463 [DEBUG] Translating virtual address: 0x805c0c3
2024-10-12 15:11:42.463 [DEBUG] Translated virtual address 0x805c0c3 to physical address 0x140c3
2024-10-12 15:11:42.463 [DEBUG] Fetched dword 0xE8 from physical address 0x140c3
2024-10-12 15:11:42.463 [DEBUG] Segment base: 0x0, Effective address: 0xffffffe8, Virtual address: 0xffffffe8
2024-10-12 15:11:42.463 [DEBUG] Decoded operand: is_memory=1, address=0xffffffe8, register_code=0
2024-10-12 15:11:42.463 [DEBUG] Translating virtual address: 0x805c0c7
2024-10-12 15:11:42.463 [DEBUG] Translated virtual address 0x805c0c7 to physical address 0x140c7
2024-10-12 15:11:42.463 [DEBUG] Fetched byte 00 from virtual address 0x805c0c7 (physical address 0x140c7)
2024-10-12 15:11:42.463 [DEBUG] Translating virtual address: 0xffffffe8
2024-10-12 15:11:42.463 [ERROR] Virtual address 0xffffffe8 does not map to any loaded segment.
2024-10-12 15:11:42.463 [ERROR] Exception caught: Virtual address 0xffffffe8 does not map to any loaded segment.
2024-10-12 15:11:42.463 [INFO] Emulation stopped.
2024-10-12 15:11:42.463 [ERROR] ELF program execution failed.
INFO: 225
DEBUG: 3431
ERROR: 3
swed@DESKTOP-K5N5PON:~$ objdump -d hello_world_c
hello_world_c:     file format elf32-i386
Disassembly of section .init:
080482a8 <_init>:
 80482a8:       53                      push   %ebx
 80482a9:       83 ec 08                sub    $0x8,%esp
 80482ac:       e8 af 00 00 00          call   8048360 <__x86.get_pc_thunk.bx>
 80482b1:       81 c3 4f 1d 00 00       add    $0x1d4f,%ebx
 80482b7:       8b 83 fc ff ff ff       mov    -0x4(%ebx),%eax
 80482bd:       85 c0                   test   %eax,%eax
 80482bf:       74 05                   je     80482c6 <_init+0x1e>
 80482c1:       e8 3a 00 00 00          call   8048300 <__gmon_start__@plt>
 80482c6:       83 c4 08                add    $0x8,%esp
 80482c9:       5b                      pop    %ebx
 80482ca:       c3                      ret
Disassembly of section .plt:
080482d0 <.plt>:
 80482d0:       ff 35 04 a0 04 08       pushl  0x804a004
 80482d6:       ff 25 08 a0 04 08       jmp    *0x804a008
 80482dc:       00 00                   add    %al,(%eax)
        ...
080482e0 <puts@plt>:
 80482e0:       ff 25 0c a0 04 08       jmp    *0x804a00c
 80482e6:       68 00 00 00 00          push   $0x0
 80482eb:       e9 e0 ff ff ff          jmp    80482d0 <.plt>
080482f0 <__libc_start_main@plt>:
 80482f0:       ff 25 10 a0 04 08       jmp    *0x804a010
 80482f6:       68 08 00 00 00          push   $0x8
 80482fb:       e9 d0 ff ff ff          jmp    80482d0 <.plt>
Disassembly of section .plt.got:
08048300 <__gmon_start__@plt>:
 8048300:       ff 25 fc 9f 04 08       jmp    *0x8049ffc
 8048306:       66 90                   xchg   %ax,%ax
Disassembly of section .text:
08048310 <_start>:
 8048310:       31 ed                   xor    %ebp,%ebp
 8048312:       5e                      pop    %esi
 8048313:       89 e1                   mov    %esp,%ecx
 8048315:       83 e4 f0                and    $0xfffffff0,%esp
 8048318:       50                      push   %eax
 8048319:       54                      push   %esp
 804831a:       52                      push   %edx
 804831b:       e8 23 00 00 00          call   8048343 <_start+0x33>
 8048320:       81 c3 e0 1c 00 00       add    $0x1ce0,%ebx
 8048326:       8d 83 d0 e4 ff ff       lea    -0x1b30(%ebx),%eax
 804832c:       50                      push   %eax
 804832d:       8d 83 70 e4 ff ff       lea    -0x1b90(%ebx),%eax
 8048333:       50                      push   %eax
 8048334:       51                      push   %ecx
 8048335:       56                      push   %esi
 8048336:       c7 c0 26 84 04 08       mov    $0x8048426,%eax
 804833c:       50                      push   %eax
 804833d:       e8 ae ff ff ff          call   80482f0 <__libc_start_main@plt>
 8048342:       f4                      hlt
 8048343:       8b 1c 24                mov    (%esp),%ebx
 8048346:       c3                      ret
 8048347:       66 90                   xchg   %ax,%ax
 8048349:       66 90                   xchg   %ax,%ax
 804834b:       66 90                   xchg   %ax,%ax
 804834d:       66 90                   xchg   %ax,%ax
 804834f:       90                      nop
08048350 <_dl_relocate_static_pie>:
 8048350:       f3 c3                   repz ret
 8048352:       66 90                   xchg   %ax,%ax
 8048354:       66 90                   xchg   %ax,%ax
 8048356:       66 90                   xchg   %ax,%ax
 8048358:       66 90                   xchg   %ax,%ax
 804835a:       66 90                   xchg   %ax,%ax
 804835c:       66 90                   xchg   %ax,%ax
 804835e:       66 90                   xchg   %ax,%ax
08048360 <__x86.get_pc_thunk.bx>:
 8048360:       8b 1c 24                mov    (%esp),%ebx
 8048363:       c3                      ret
 8048364:       66 90                   xchg   %ax,%ax
 8048366:       66 90                   xchg   %ax,%ax
 8048368:       66 90                   xchg   %ax,%ax
 804836a:       66 90                   xchg   %ax,%ax
 804836c:       66 90                   xchg   %ax,%ax
 804836e:       66 90                   xchg   %ax,%ax
08048370 <deregister_tm_clones>:
 8048370:       b8 1c a0 04 08          mov    $0x804a01c,%eax
 8048375:       3d 1c a0 04 08          cmp    $0x804a01c,%eax
 804837a:       74 24                   je     80483a0 <deregister_tm_clones+0x30>
 804837c:       b8 00 00 00 00          mov    $0x0,%eax
 8048381:       85 c0                   test   %eax,%eax
 8048383:       74 1b                   je     80483a0 <deregister_tm_clones+0x30>
 8048385:       55                      push   %ebp
 8048386:       89 e5                   mov    %esp,%ebp
 8048388:       83 ec 14                sub    $0x14,%esp
 804838b:       68 1c a0 04 08          push   $0x804a01c
 8048390:       ff d0                   call   *%eax
 8048392:       83 c4 10                add    $0x10,%esp
 8048395:       c9                      leave
 8048396:       c3                      ret
 8048397:       89 f6                   mov    %esi,%esi
 8048399:       8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
 80483a0:       f3 c3                   repz ret
 80483a2:       8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
 80483a9:       8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
080483b0 <register_tm_clones>:
 80483b0:       b8 1c a0 04 08          mov    $0x804a01c,%eax
 80483b5:       2d 1c a0 04 08          sub    $0x804a01c,%eax
 80483ba:       c1 f8 02                sar    $0x2,%eax
 80483bd:       89 c2                   mov    %eax,%edx
 80483bf:       c1 ea 1f                shr    $0x1f,%edx
 80483c2:       01 d0                   add    %edx,%eax
 80483c4:       d1 f8                   sar    %eax
 80483c6:       74 20                   je     80483e8 <register_tm_clones+0x38>
 80483c8:       ba 00 00 00 00          mov    $0x0,%edx
 80483cd:       85 d2                   test   %edx,%edx
 80483cf:       74 17                   je     80483e8 <register_tm_clones+0x38>
 80483d1:       55                      push   %ebp
 80483d2:       89 e5                   mov    %esp,%ebp
 80483d4:       83 ec 10                sub    $0x10,%esp
 80483d7:       50                      push   %eax
 80483d8:       68 1c a0 04 08          push   $0x804a01c
 80483dd:       ff d2                   call   *%edx
 80483df:       83 c4 10                add    $0x10,%esp
 80483e2:       c9                      leave
 80483e3:       c3                      ret
 80483e4:       8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
 80483e8:       f3 c3                   repz ret
 80483ea:       8d b6 00 00 00 00       lea    0x0(%esi),%esi
080483f0 <__do_global_dtors_aux>:
 80483f0:       80 3d 1c a0 04 08 00    cmpb   $0x0,0x804a01c
 80483f7:       75 17                   jne    8048410 <__do_global_dtors_aux+0x20>
 80483f9:       55                      push   %ebp
 80483fa:       89 e5                   mov    %esp,%ebp
 80483fc:       83 ec 08                sub    $0x8,%esp
 80483ff:       e8 6c ff ff ff          call   8048370 <deregister_tm_clones>
 8048404:       c6 05 1c a0 04 08 01    movb   $0x1,0x804a01c
 804840b:       c9                      leave
 804840c:       c3                      ret
 804840d:       8d 76 00                lea    0x0(%esi),%esi
 8048410:       f3 c3                   repz ret
 8048412:       8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
 8048419:       8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
08048420 <frame_dummy>:
 8048420:       55                      push   %ebp
 8048421:       89 e5                   mov    %esp,%ebp
 8048423:       5d                      pop    %ebp
 8048424:       eb 8a                   jmp    80483b0 <register_tm_clones>
08048426 <main>:
 8048426:       8d 4c 24 04             lea    0x4(%esp),%ecx
 804842a:       83 e4 f0                and    $0xfffffff0,%esp
 804842d:       ff 71 fc                pushl  -0x4(%ecx)
 8048430:       55                      push   %ebp
 8048431:       89 e5                   mov    %esp,%ebp
 8048433:       53                      push   %ebx
 8048434:       51                      push   %ecx
 8048435:       e8 24 00 00 00          call   804845e <__x86.get_pc_thunk.ax>
 804843a:       05 c6 1b 00 00          add    $0x1bc6,%eax
 804843f:       83 ec 0c                sub    $0xc,%esp
 8048442:       8d 90 f0 e4 ff ff       lea    -0x1b10(%eax),%edx
 8048448:       52                      push   %edx
 8048449:       89 c3                   mov    %eax,%ebx
 804844b:       e8 90 fe ff ff          call   80482e0 <puts@plt>
 8048450:       83 c4 10                add    $0x10,%esp
 8048453:       90                      nop
 8048454:       8d 65 f8                lea    -0x8(%ebp),%esp
 8048457:       59                      pop    %ecx
 8048458:       5b                      pop    %ebx
 8048459:       5d                      pop    %ebp
 804845a:       8d 61 fc                lea    -0x4(%ecx),%esp
 804845d:       c3                      ret
0804845e <__x86.get_pc_thunk.ax>:
 804845e:       8b 04 24                mov    (%esp),%eax
 8048461:       c3                      ret
 8048462:       66 90                   xchg   %ax,%ax
 8048464:       66 90                   xchg   %ax,%ax
 8048466:       66 90                   xchg   %ax,%ax
 8048468:       66 90                   xchg   %ax,%ax
 804846a:       66 90                   xchg   %ax,%ax
 804846c:       66 90                   xchg   %ax,%ax
 804846e:       66 90                   xchg   %ax,%ax
08048470 <__libc_csu_init>:
 8048470:       55                      push   %ebp
 8048471:       57                      push   %edi
 8048472:       56                      push   %esi
 8048473:       53                      push   %ebx
 8048474:       e8 e7 fe ff ff          call   8048360 <__x86.get_pc_thunk.bx>
 8048479:       81 c3 87 1b 00 00       add    $0x1b87,%ebx
 804847f:       83 ec 0c                sub    $0xc,%esp
 8048482:       8b 6c 24 28             mov    0x28(%esp),%ebp
 8048486:       8d b3 10 ff ff ff       lea    -0xf0(%ebx),%esi
 804848c:       e8 17 fe ff ff          call   80482a8 <_init>
 8048491:       8d 83 0c ff ff ff       lea    -0xf4(%ebx),%eax
 8048497:       29 c6                   sub    %eax,%esi
 8048499:       c1 fe 02                sar    $0x2,%esi
 804849c:       85 f6                   test   %esi,%esi
 804849e:       74 25                   je     80484c5 <__libc_csu_init+0x55>
 80484a0:       31 ff                   xor    %edi,%edi
 80484a2:       8d b6 00 00 00 00       lea    0x0(%esi),%esi
 80484a8:       83 ec 04                sub    $0x4,%esp
 80484ab:       55                      push   %ebp
 80484ac:       ff 74 24 2c             pushl  0x2c(%esp)
 80484b0:       ff 74 24 2c             pushl  0x2c(%esp)
 80484b4:       ff 94 bb 0c ff ff ff    call   *-0xf4(%ebx,%edi,4)
 80484bb:       83 c7 01                add    $0x1,%edi
 80484be:       83 c4 10                add    $0x10,%esp
 80484c1:       39 fe                   cmp    %edi,%esi
 80484c3:       75 e3                   jne    80484a8 <__libc_csu_init+0x38>
 80484c5:       83 c4 0c                add    $0xc,%esp
 80484c8:       5b                      pop    %ebx
 80484c9:       5e                      pop    %esi
 80484ca:       5f                      pop    %edi
 80484cb:       5d                      pop    %ebp
 80484cc:       c3                      ret
 80484cd:       8d 76 00                lea    0x0(%esi),%esi
080484d0 <__libc_csu_fini>:
 80484d0:       f3 c3                   repz ret
Disassembly of section .fini:
080484d4 <_fini>:
 80484d4:       53                      push   %ebx
 80484d5:       83 ec 08                sub    $0x8,%esp
 80484d8:       e8 83 fe ff ff          call   8048360 <__x86.get_pc_thunk.bx>
 80484dd:       81 c3 23 1b 00 00       add    $0x1b23,%ebx
 80484e3:       83 c4 08                add    $0x8,%esp
 80484e6:       5b                      pop    %ebx
 80484e7:       c3                      ret