swed@DESKTOP-K5N5PON:~$ objdump -d -x hello_world_nasm.elf
hello_world_nasm.elf:     file format elf32-i386
hello_world_nasm.elf
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08049000
Program Header:
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x00000094 memsz 0x00000094 flags r--
    LOAD off    0x00001000 vaddr 0x08049000 paddr 0x08049000 align 2**12
         filesz 0x00000022 memsz 0x00000022 flags r-x
    LOAD off    0x00002000 vaddr 0x0804a000 paddr 0x0804a000 align 2**12
         filesz 0x0000000e memsz 0x0000000e flags rw-
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000022  08049000  08049000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         0000000e  0804a000  0804a000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000 l    df *ABS*  00000000 hello.asm
0804a000 l       .data  00000000 message
0000000e l       *ABS*  00000000 msg_len
08049000 g       .text  00000000 _start
0804a00e g       .data  00000000 __bss_start
0804a00e g       .data  00000000 _edata
0804a010 g       .data  00000000 _end
Disassembly of section .text:
08049000 <_start>:
 8049000:       b8 04 00 00 00          mov    $0x4,%eax
 8049005:       bb 01 00 00 00          mov    $0x1,%ebx
 804900a:       b9 00 a0 04 08          mov    $0x804a000,%ecx
 804900f:       ba 0e 00 00 00          mov    $0xe,%edx
 8049014:       cd 80                   int    $0x80
 8049016:       b8 01 00 00 00          mov    $0x1,%eax
 804901b:       bb 00 00 00 00          mov    $0x0,%ebx
 8049020:       cd 80                   int    $0x80
// elf_loader.cpp
#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));
    }
    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;
}
// Emulator.cpp
#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) {
        memory.resize(required_memory_size, 0);
        Logger::get_instance().log(LogLevel::INFO, "Memory resized to " + std::to_string(required_memory_size) + " bytes to accommodate the stack.");
    }
    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: 0x" + 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 за пределами памяти. Адрес: 0x" + 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: 0x" + 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) const {
    static const std::string reg_names[8] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
    if (code < 8) {
        return reg_names[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: 0x" + 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 {
    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.");
            return physical_address;
        }
    }
    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, rm = modrm & 0x07;
    uint32_t virtual_address = 0;
    if (rm == 4) {
        uint8_t sib = fetch_byte();
        int32_t displacement = (mod == 0 && (sib & 0x07) == 5) ? static_cast<int32_t>(fetch_dword()) : (mod == 1) ? static_cast<int32_t>(static_cast<int8_t>(fetch_byte())) : (mod == 2) ? static_cast<int32_t>(fetch_dword()) : 0;
        virtual_address = calculate_sib_address(mod, sib, displacement);
    }
    else {
        int32_t displacement = (mod == 0 && rm == 5) ? static_cast<int32_t>(fetch_dword()) : (mod == 1) ? static_cast<int32_t>(static_cast<int8_t>(fetch_byte())) : (mod == 2) ? static_cast<int32_t>(fetch_dword()) : 0;
        virtual_address = (mod == 0 && rm == 5) ? displacement : *get_register_by_code(rm) + displacement;
    }
    Logger::get_instance().log(LogLevel::DEBUG, "Calculated address: 0x" + 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, rm = modrm & 0x07;
    if (mod == 3) { operand.is_memory = false; operand.register_code = rm; }
    else { operand.is_memory = true; operand.address = calculate_address(modrm); }
    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[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[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[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[0x84] = &Emulator::instr_JE_rel32;
    extended_instruction_set[0x85] = &Emulator::instr_JNE_rel32;
    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.");
}
// file_utils.cpp
#include "file_utils.h"
#include <fstream>
#include <iostream>
#include "Logger.h"
bool save_program_to_file(const std::vector<uint8_t>& program, const std::string& filename) {
    std::ofstream outfile(filename, std::ios::binary);
    if (!outfile) {
        Logger::get_instance().log(LogLevel::ERROR, "Unable to open file for writing: " + filename);
        return false;
    }
    outfile.write(reinterpret_cast<const char*>(program.data()), program.size());
    if (!outfile) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to write data to file: " + filename);
        return false;
    }
    outfile.close();
    return true;
}
std::vector<uint8_t> load_program_from_file(const std::string& filename) {
    std::ifstream infile(filename, std::ios::binary | std::ios::ate);
    if (!infile) {
        Logger::get_instance().log(LogLevel::ERROR, "Unable to open file for reading: " + filename);
        return {};
    }
    std::streamsize size = infile.tellg();
    infile.seekg(0, std::ios::beg);
    if (size <= 0) {
        Logger::get_instance().log(LogLevel::ERROR, "File is empty or inaccessible: " + filename);
        return {};
    }
    std::vector<uint8_t> buffer(static_cast<size_t>(size));
    if (!infile.read(reinterpret_cast<char*>(buffer.data()), size)) {
        Logger::get_instance().log(LogLevel::ERROR, "Failed to read data from file: " + filename);
        return {};
    }
    infile.close();
    return buffer;
}
// Instructions.cpp
#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();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07;
    uint8_t rm = modrm & 0x07;
    uint32_t operand1 = 0;
    uint32_t operand2 = 0;
    uint32_t* reg_operand2 = get_register_by_code(reg);
    if (!reg_operand2) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown register in TEST r/m32, r32.");
        error_flag = true;
        running = false;
        return;
    }
    operand2 = *reg_operand2;
    if (mod == 3) {
        uint32_t* reg_operand1 = get_register_by_code(rm);
        if (!reg_operand1) {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in TEST r/m32, r32.");
            error_flag = true;
            running = false;
            return;
        }
        operand1 = *reg_operand1;
    }
    else {
        uint32_t address = calculate_address(modrm);
        operand1 = read_memory_dword(address);
    }
    uint32_t result = operand1 & operand2;
    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(static_cast<uint8_t>(result & 0xFF));
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: TEST rm32, 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 rel32 = fetch_dword();
    if (regs.EFLAGS & ZF_FLAG) {
        regs.EIP += rel32;
    }
    Logger::get_instance().log(LogLevel::INFO, "Executed instruction: JE 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: 0x" + 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 0x" + 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() {
    Logger::get_instance().log(LogLevel::INFO, "Executing instruction: SUB r/m8, imm8.");
    uint8_t modrm = fetch_byte();
    uint8_t opcode = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;
    if (opcode != 5) {
        Logger::get_instance().log(LogLevel::ERROR, "Unsupported opcode in SUB r/m8, imm8.");
        error_flag = true;
        running = false;
        return;
    }
    uint8_t imm8 = fetch_byte();
    uint8_t* dest = get_register8_by_code(rm_code);
    if (!dest) {
        Logger::get_instance().log(LogLevel::ERROR, "Unknown register in SUB r/m8, imm8.");
        error_flag = true;
        running = false;
        return;
    }
    *dest -= imm8;
    update_ZF_FLAG(*dest);
}
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,
        "Moved value 0x" + byte_to_hex(*src_reg) +
        " from register " + register_name(reg_code) +
        " to register " + register_name(rm_code) + "."
    );
}
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: 0x" + 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;
    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;
            update_ZF_FLAG(*dest_reg);
            Logger::get_instance().log(
                LogLevel::DEBUG,
                "XORed value 0x" + addr_to_hex(*src_reg) +
                " from register " + register_name(reg) +
                " with register " + register_name(rm) +
                ", result: 0x" + addr_to_hex(*dest_reg) + "."
            );
        }
        else {
            Logger::get_instance().log(LogLevel::ERROR, "Unknown register in XOR r/m32, r32.");
            error_flag = true;
            running = false;
        }
    }
}
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: 0x" + 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: // ADD
        *dest_reg += imm32;
        update_ZF_FLAG(*dest_reg);
        Logger::get_instance().log(LogLevel::DEBUG, "Added 0x" + addr_to_hex(imm32) + " to register " + register_name(rm) + ".");
        break;
    case 1: // OR
        *dest_reg |= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 4: // AND
        *dest_reg &= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 5: // SUB
        *dest_reg -= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 6: // XOR
        *dest_reg ^= imm32;
        update_ZF_FLAG(*dest_reg);
        break;
    case 7: // CMP
    {
        uint32_t result = *dest_reg - imm32;
        update_ZF_FLAG(result);
        Logger::get_instance().log(LogLevel::DEBUG, "Compared register " + register_name(rm) + " with 0x" + 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;
    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 0x83.");
        error_flag = true;
        running = false;
        return;
    }
    int8_t imm8 = static_cast<int8_t>(fetch_byte());
    int32_t sign_extended_imm = static_cast<int32_t>(imm8);
    switch (reg_opcode) {
    case 0: // ADD
        *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) + ".");
        break;
    case 1: // OR
        *dest_reg |= sign_extended_imm;
        update_ZF_FLAG(*dest_reg);
        break;
    case 4: // AND
        *dest_reg &= sign_extended_imm;
        update_ZF_FLAG(*dest_reg);
        break;
    case 5: // SUB
        *dest_reg -= sign_extended_imm;
        update_ZF_FLAG(*dest_reg);
        break;
    case 6: // XOR
        *dest_reg ^= sign_extended_imm;
        update_ZF_FLAG(*dest_reg);
        break;
    case 7: // CMP
    {
        uint32_t result = *dest_reg - sign_extended_imm;
        update_ZF_FLAG(result);
        Logger::get_instance().log(LogLevel::DEBUG, "Compared register " + register_name(rm) + " 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;
        break;
    }
}
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: 0x" + 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: 0x" + addr_to_hex(regs.ESI) + ", EDI: 0x" + 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::update_PF(uint8_t result) {
    // Count the number of set bits
    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);
    // Обновите флаги CF и OF
}
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 "Logger.h"
Logger& Logger::get_instance() {
    static Logger instance;
    return instance;
}
Logger::Logger()
    : current_level(LogLevel::DEBUG), file_logging_enabled(false) {}
Logger::~Logger() {
    if (log_file.is_open()) {
        log_file.close();
    }
}
void Logger::set_log_level(LogLevel level) {
    current_level = level;
}
void Logger::enable_file_logging(const std::string& filename) {
    std::lock_guard<std::mutex> lock(log_mutex);
    if (log_file.is_open()) {
        log_file.close();
    }
    log_file.open(filename, std::ios::out | std::ios::app);
    if (log_file.is_open()) {
        file_logging_enabled = true;
    }
    else {
        std::cerr << "Failed to open log file: " << filename << "\n";
    }
}
void Logger::disable_file_logging() {
    std::lock_guard<std::mutex> lock(log_mutex);
    if (log_file.is_open()) {
        log_file.close();
    }
    file_logging_enabled = false;
}
std::string get_current_timestamp() {
    auto now = std::chrono::system_clock::now();
    auto now_time_t = std::chrono::system_clock::to_time_t(now);
    std::tm tm;
    bool success = false;
#if defined(_WIN32) || defined(_WIN64)
    errno_t err = localtime_s(&tm, &now_time_t); // WINDOWS
    success = (err == 0);
#else
    success = (localtime_r(&now_time_t, &tm) != nullptr); // POSIX
#endif
    if (!success) {
        return "1970-01-01 00:00:00.000";
    }
    auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        now.time_since_epoch()) % 1000;
    std::ostringstream ss;
    ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << '.'
        << std::setw(3) << std::setfill('0') << now_ms.count();
    return ss.str();
}
void Logger::log(LogLevel level, const std::string& message) {
    if (static_cast<int>(level) < static_cast<int>(current_level)) {
        return;
    }
    std::lock_guard<std::mutex> lock(log_mutex);
    std::string timestamp = get_current_timestamp();
    std::string level_str;
    switch (level) {
    case LogLevel::DEBUG:   level_str = "[DEBUG] "; break;
    case LogLevel::INFO:    level_str = "[INFO] "; break;
    case LogLevel::WARNING: level_str = "[WARNING] "; break;
    case LogLevel::ERROR:   level_str = "[ERROR] "; break;
    }
    std::string formatted_message = timestamp + " " + level_str + message;
    //std::cout << formatted_message << std::endl;
    if (file_logging_enabled && log_file.is_open()) {
        log_file << formatted_message << std::endl;
    }
}// main.cpp
#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;
}// elf_loader.h
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
#include "Emulator.h"
#include "elf_structs.h"
#include <string>
#include <vector>
// Функция для загрузки ELF-файла в эмулятор
bool load_elf(const std::string& filename, Emulator& emulator);
#endif // ELF_LOADER_H
// elf_structs.h
#ifndef ELF_STRUCTS_H
#define ELF_STRUCTS_H
#include <cstdint>
// Упаковка структур без отступов
#pragma pack(push, 1)
// ELF Header для 32-битных x86
struct Elf32_Ehdr {
    unsigned char e_ident[16]; // Идентификационная информация
    uint16_t e_type;           // Тип файла
    uint16_t e_machine;        // Архитектура
    uint32_t e_version;        // Версия ELF
    uint32_t e_entry;          // Точка входа
    uint32_t e_phoff;          // Смещение к таблице заголовков сегментов
    uint32_t e_shoff;          // Смещение к таблице заголовков секций
    uint32_t e_flags;          // Флаги
    uint16_t e_ehsize;         // Размер заголовка ELF
    uint16_t e_phentsize;      // Размер одного заголовка сегмента
    uint16_t e_phnum;          // Количество заголовков сегментов
    uint16_t e_shentsize;      // Размер одного заголовка секции
    uint16_t e_shnum;          // Количество заголовков секций
    uint16_t e_shstrndx;       // Индекс секции строк заголовков
};
// Program Header для 32-битных x86
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)
// Константы для p_type
#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 // ELF_STRUCTS_H
// Emulator.h
#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; // Базовый адрес ELF
    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);
    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;          // Размер стека (8 КБ)
    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;
    };
    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;    // Carry Flag
    const uint32_t PF_FLAG = 1 << 2;    // Parity Flag
    const uint32_t AF_FLAG = 1 << 4;    // Auxiliary Carry Flag
    const uint32_t ZF_FLAG = 1 << 6;    // Zero Flag
    const uint32_t SF_FLAG = 1 << 7;    // Sign Flag
    const uint32_t OF_FLAG = 1 << 11;   // Overflow Flag
    const uint32_t DF_FLAG = 1 << 10;   // Direction Flag
    const uint32_t IF_FLAG = 1 << 9;    // Interrupt Enable Flag
    // Текущие сегментные указатели
    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_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);
    // Методы для группы инструкций F6
    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) 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);
    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 push(uint32_t value);
    uint32_t translate_virtual_address(uint32_t virtual_addr) const;
    Operand decode_operand(uint8_t modrm);
    void sys_read();
};
#endif // EMULATOR_H