// Instructions.cpp
#include "Emulator.h"
#include <iostream>
#include <stdint.h>
#include <string>
// Реализация обработчиков инструкций

// MOV EAX, imm32
void Emulator::instr_MOV_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX = imm;
}

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() {
    // Clear the Direction Flag (DF), which is bit 10 in EFLAGS
    regs.EFLAGS &= ~DF;

    // Optionally, print debug information
    std::cout << "Выполнена инструкция CLD (Direction Flag сброшен).\n";
}
void Emulator::instr_PUSH_imm8() {
    int8_t imm8 = static_cast<int8_t>(fetch_byte()); // Получаем 8-битное значение
    push(static_cast<uint32_t>(imm8)); // Преобразуем в 32-битное знаковое значение и помещаем в стек
}
void Emulator::push(uint32_t value) {
    if (regs.ESP < 4) {
        std::cerr << "Stack overflow при попытке записать в стек.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.ESP -= 4;  // Уменьшаем указатель стека
    write_memory_dword(regs.ESP, value);  // Записываем значение в стек
}
void Emulator::instr_NOP_EAX() {
    // Эта инструкция ничего не делает, можно просто вывести сообщение
    std::cout << "Выполнен NOP [EAX]\n";
}
void Emulator::instr_STI() {
    // Устанавливаем флаг прерываний (IF)
    regs.EFLAGS |= IF_FLAG;
    std::cout << "Выполнен STI: Установлен флаг прерываний (IF).\n";
}
void Emulator::instr_POP_ESP() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP ESP.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.ESP = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
void Emulator::instr_POP_EBX() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP EBX.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.EBX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
void Emulator::instr_POP_EDX() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP EDX.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.EDX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
void Emulator::instr_POP_ECX() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP ECX.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.ECX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
void Emulator::instr_POP_EAX() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP EAX.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.EAX = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
void Emulator::instr_POP_ESI() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP ESI.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Считываем значение со стека и сохраняем его в регистр ESI
    regs.ESI = read_memory_dword(regs.ESP);
    regs.ESP += 4;  // Увеличиваем указатель стека

    std::cout << "Выполнен POP ESI. Значение в регистре ESI: " << std::hex << regs.ESI << "\n";
}
void Emulator::instr_POP_EDI() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP EDI.\n";
        error_flag = true;
        running = false;
        return;
    }
    regs.EDI = read_memory_dword(regs.ESP);
    regs.ESP += 4;
}
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) {
            std::cout << "Unknown register in MOV Ev, Iv.\n";
            error_flag = true;
            running = false;
            return;
        }
        *reg = immediate;
    }
}
// Реализация инструкции INC r/m32
void Emulator::instr_INC_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    if (operand.is_memory) {
        uint32_t 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)++;
    }
    update_ZF(operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code));
}

// Реализация инструкции DEC r/m32
void Emulator::instr_DEC_rm32(uint8_t modrm) {
    Operand operand = decode_operand(modrm);
    if (operand.is_memory) {
        uint32_t 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)--;
    }
    update_ZF(operand.is_memory ? read_memory_dword(operand.address) : *get_register_by_code(operand.register_code));
}
void Emulator::instr_LEAVE() {
    // Set ESP to EBP
    regs.ESP = regs.EBP;

    // POP EBP
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on LEAVE.\n";
        error_flag = true;
        running = false;
        return;
    }

    regs.EBP = read_memory_dword(regs.ESP);
    regs.ESP += 4;

    std::cout << "Выполнена инструкция LEAVE. ESP: 0x" << std::hex << regs.ESP
        << ", EBP: 0x" << regs.EBP << "\n";
}
// Реализация инструкции CALL r/m32
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;
}

// Реализация инструкции JMP r/m32
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;
}

// Реализация инструкции PUSH r/m32
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);
}
void Emulator::instr_PUSH_imm32() {
    uint32_t imm32 = fetch_dword();  // Чтение 32-битного непосредственного значения
    push(imm32);  // Помещение значения в стек
}
void Emulator::instr_GROUP5() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07;  // Поле reg в ModR/M указывает на операцию
    uint8_t rm = modrm & 0x07;

    switch (reg) {
    case 0: // INC r/m32
        instr_INC_rm32(modrm);
        break;
    case 1: // DEC r/m32
        instr_DEC_rm32(modrm);
        break;
    case 2: // CALL r/m32
        instr_CALL_rm32(modrm);
        break;
    case 3: // CALL far
        std::cout << "CALL far не поддерживается.\n";
        error_flag = true;
        running = false;
        break;
    case 4: // JMP r/m32
        instr_JMP_rm32(modrm);
        break;
    case 5: // JMP far
        std::cout << "JMP far не поддерживается.\n";
        error_flag = true;
        running = false;
        break;
    case 6: // PUSH r/m32
        instr_PUSH_rm32(modrm);
        break;
    default:
        std::cout << "Неизвестный подтип команды 0xFF: " << (int)reg << "\n";
        error_flag = true;
        running = false;
        break;
    }
}
void Emulator::instr_ENDBR32() {
    // Мы уже обработали префикс 0xF3 и прочитали опкод 0x0F
    // Теперь нужно убедиться, что следующий байт 0x1E, уже считан
    // Считываем последний байт инструкции
    uint8_t modrm = fetch_byte();
    if (modrm != 0xFB) {
        std::cout << "Ожидаемый байт 0xFB не найден после opcode 0x1E для ENDBR32.\n";
        error_flag = true;
        running = false;
        return;
    }
    // Инструкция корректно распознана, выполняем NOP
    std::cout << "Выполнена инструкция ENDBR32 (пропущена).\n";
}
void Emulator::instr_STD() {
    // Set the Direction Flag (DF), which is bit 10 in EFLAGS
    regs.EFLAGS |= DF;
    std::cout << "Выполнена инструкция STD (Direction Flag установлен).\n";
}
void Emulator::instr_NOP() {
    // NOP does nothing
    std::cout << "Выполнена инструкция NOP.\n";
}
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);     // Original value of ESP
    push(regs.EBP);
    push(regs.ESI);
    push(regs.EDI);
    std::cout << "Выполнена инструкция PUSHAD.\n";
}
void Emulator::instr_REP_MOVSB() {
    while (regs.ECX != 0) {
        uint8_t byte = read_memory_byte(regs.ESI);
        write_memory_byte(regs.EDI, byte);

        // Update ESI and EDI based on the Direction Flag
        if (regs.EFLAGS & DF) {
            regs.ESI -= 1;
            regs.EDI -= 1;
        }
        else {
            regs.ESI += 1;
            regs.EDI += 1;
        }

        regs.ECX -= 1;
    }
    std::cout << "Выполнена инструкция REP MOVSB.\n";
}
void Emulator::instr_NOP_m16_m32() {
    // Инструкция NOP m16/32 имеет модификатор размера операнда
    // Если установлен префикс 0x66, то размер операнда 16 бит, иначе 32 бита
    bool operand_size = regs.operand_size_override;

    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;

    if (mod == 3) {
        // Mod == 3 означает, что операнд — регистр
        // В этом случае NOP не делает ничего
        uint8_t rm = modrm & 0x07;
        // Можно просто считать регистр для эмуляции чтения
        uint32_t* reg = get_register_by_code(rm);
        if (reg) {
            uint32_t temp = *reg;
            // NOP ничего не делает, поэтому не изменяем значение
        }
        else {
            std::cout << "Неизвестный регистр в NOP r/m32.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        // Если Mod != 3, то вычисляем адрес и читаем операнд из памяти
        uint32_t address = calculate_address(modrm);

        if (operand_size) {
            // Чтение 16-битного операнда для NOP m16
            uint16_t temp = read_memory_byte(address) | (read_memory_byte(address + 1) << 8);
            // NOP не изменяет ничего, просто читаем для эмуляции
        }
        else {
            // Чтение 32-битного операнда для NOP m32
            uint32_t temp = read_memory_dword(address);
            // NOP не изменяет ничего, просто читаем для эмуляции
        }
    }

    // NOP ничего не делает, поэтому ничего не изменяем
}
// MOV EBX, imm32
void Emulator::instr_MOV_EBX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EBX = imm;
}

// MOV ECX, imm32
void Emulator::instr_MOV_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX = imm;
}

// MOV EDX, imm32
void Emulator::instr_MOV_EDX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EDX = imm;
}

// ADD EAX, imm32
void Emulator::instr_ADD_EAX_imm32() {
    if (regs.rep_prefix || regs.repne_prefix) {
        std::cout << "Warning: REP prefix is ignored for ADD EAX, imm32.\n";
        reset_prefixes();
    }
    uint32_t imm = fetch_dword();
    std::cout << "Executing ADD EAX, " << imm << " (Before EAX: " << regs.EAX << ")\n";
    regs.EAX += imm;
    std::cout << "After EAX: " << regs.EAX << "\n";
    update_ZF(regs.EAX);
}



// SUB EAX, imm32
void Emulator::instr_SUB_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX -= imm;
    update_ZF(regs.EAX);
}

// INC EAX
void Emulator::instr_INC_EAX() {
    regs.EAX += 1;
    update_ZF(regs.EAX);
}

// DEC EAX
void Emulator::instr_DEC_EAX() {
    regs.EAX -= 1;
    update_ZF(regs.EAX);
}

// MUL EAX
void Emulator::instr_MUL_EAX() {
    uint8_t modrm = fetch_byte();
    // Для простоты реализуем только MUL EAX
    if ((modrm & 0x38) == 0x20) { // Проверяем, что это MUL r/m32
        regs.EAX *= regs.EAX;
        update_ZF(regs.EAX);
    }
    else {
        std::cout << "MUL instruction with unsupported operand.\n";
        // Можно установить флаг ошибки или завершить выполнение
    }
}

// JMP rel32
void Emulator::instr_JMP_rel32() {
    int32_t rel = fetch_dword();
    regs.EIP += rel;
}

// CMP регистр, imm8
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;

        // Zero Flag
        if (result == 0)
            regs.EFLAGS |= ZF;
        else
            regs.EFLAGS &= ~ZF;

        // Carry Flag
        if (*reg_ptr < imm8)
            regs.EFLAGS |= CF;
        else
            regs.EFLAGS &= ~CF;

        // Sign Flag (SF)
        if (result & (1 << 31))
            regs.EFLAGS |= (1 << 7); // Предполагаем, что SF находится в бит 7
        else
            regs.EFLAGS &= ~(1 << 7);

        // Overflow Flag (OF) - необходимо корректно реализовать
        // Здесь может быть упрощение, для точной реализации требуется дополнительная логика
    }
    else {
        std::cout << "CMP instruction with unsupported register.\n";
        // Можно установить флаг ошибки или завершить выполнение
    }
}

// JE rel8
void Emulator::instr_JE_rel8() {
    int8_t rel = fetch_byte();
    if (regs.EFLAGS & ZF) {
        regs.EIP += rel;
    }
}

// JNE rel8
void Emulator::instr_JNE_rel8() {
    int8_t rel = fetch_byte();
    if (!(regs.EFLAGS & ZF)) {
        regs.EIP += rel;
    }
}

// AND EAX, imm32
void Emulator::instr_AND_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX &= imm;
    update_ZF(regs.EAX);
}

// AND ECX, imm32
void Emulator::instr_AND_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX &= imm;
    update_ZF(regs.ECX);
}

// OR EAX, imm32
void Emulator::instr_OR_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX |= imm;
    update_ZF(regs.EAX);
}

// OR ECX, imm32
void Emulator::instr_OR_ECX_imm32() {
    uint32_t imm = fetch_dword();
    regs.ECX |= imm;
    update_ZF(regs.ECX);
}

// XOR EAX, imm32
void Emulator::instr_XOR_EAX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EAX ^= imm;
    update_ZF(regs.EAX);
}

// SUB EBX, imm32
void Emulator::instr_SUB_EBX_imm32() {
    uint32_t imm = fetch_dword();
    regs.EBX -= imm;
    update_ZF(regs.EBX);
}

// CMP EAX, 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;
    else
        regs.EFLAGS &= ~ZF;
    // Дополнительно можно установить другие флаги (CF, OF и т.д.)
}

// Обработчик инструкции RET
void Emulator::instr_RET() {
    if (regs.ESP + 4 > memory.size()) {
        std::cout << "Stack underflow on RET.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Pop the return address from the stack
    uint32_t return_address = read_memory_dword(regs.ESP);
    regs.ESP += 4;

    // Jump to the return address
    regs.EIP = return_address;
}

// Обработчик инструкции SUB r32, imm32
void Emulator::instr_SUB_r32_imm32() {
    uint8_t modrm = fetch_byte();
    uint8_t reg_opcode = (modrm >> 3) & 0x07; // Извлекаем поле reg из ModRM

    if (reg_opcode != 5) { // Для инструкции SUB reg, imm32, reg_opcode должен быть 5
        std::cout << "Unsupported SUB instruction with reg opcode: " << (int)reg_opcode << "\n";
        return;
    }

    uint32_t imm32 = fetch_dword(); // Извлекаем непосредственное значение
    uint8_t rm = regm_rm(modrm); // Извлекаем регистр назначения из ModRM
    uint32_t* reg_ptr = get_register_by_code(rm);

    if (reg_ptr) {
        *reg_ptr -= imm32;
        update_ZF(*reg_ptr);
    }
    else {
        std::cout << "SUB instruction with unsupported register.\n";
    }
}
void Emulator::instr_CMP_r32_rm32() {
    uint8_t modrm = fetch_byte();

    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07; // Источник: r32
    uint8_t rm_code = modrm & 0x07;         // Назначение: r/m32

    uint32_t* reg = get_register_by_code(reg_code); // Источник
    uint32_t* rm;

    if (mod == 3) {
        rm = get_register_by_code(rm_code);

        if (!rm) {
            std::cout << "Неизвестный регистр в CMP r/m32, r32.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        // Для простоты реализуем только регистровый режим
        std::cout << "Поддерживается только регистровый режим для CMP r/m32, r32.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Выполняем сравнение
    uint32_t result = *rm - *reg;

    // Обновляем флаги
    // Zero Flag (ZF)
    if (result == 0)
        regs.EFLAGS |= ZF;
    else
        regs.EFLAGS &= ~ZF;

    // Sign Flag (SF)
    if (result & 0x80000000)
        regs.EFLAGS |= SF;
    else
        regs.EFLAGS &= ~SF;

    // Carry Flag (CF)
    if (*rm < *reg)
        regs.EFLAGS |= CF;
    else
        regs.EFLAGS &= ~CF;

    // Overflow Flag (OF)
    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;
    else
        regs.EFLAGS &= ~OF;
}
// Обработчик инструкции JE rel32 (0x0F 0x84)
void Emulator::instr_JE_rel32() {
    int32_t rel32 = fetch_dword(); // Читаем относительное смещение
    if (regs.EFLAGS & ZF) { // Проверка флага равенства
        regs.EIP += rel32;
    }
}

// Обработчик инструкции JNE rel32 (0x0F 0x85)
void Emulator::instr_JNE_rel32() {
    int32_t rel32 = fetch_dword(); // Читаем относительное смещение
    if (!(regs.EFLAGS & ZF)) { // Проверка флага неравенства
        regs.EIP += rel32;
    }
}

// Обработчик инструкции JG rel32 (0x0F 0x8F)
void Emulator::instr_JG_rel32() {
    int32_t rel32 = fetch_dword(); // Читаем относительное смещение
    bool zf = (regs.EFLAGS & ZF) != 0;
    bool sf = (regs.EFLAGS & SF) != 0;
    bool of = (regs.EFLAGS & OF) != 0;
    if (!zf && (sf == of)) {
        regs.EIP += rel32;
    }
}
void Emulator::instr_MOV_rm8_imm8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm & 0xC0) >> 6;
    // uint8_t reg = (modrm & 0x38) >> 3; // Не используется для MOV r/m8, imm8
    uint8_t rm = (modrm & 0x07);       // Назначение: r/m8

    uint8_t imm8 = fetch_byte();

    if (mod == 3) { // Регистр
        uint32_t* dest_reg = get_register_by_code(rm);
        if (dest_reg) {
            // Только младший байт регистра
            uint8_t* dest_reg_byte = reinterpret_cast<uint8_t*>(dest_reg);
            dest_reg_byte[0] = imm8;
        }
        else {
            std::cout << "Неизвестный регистр в MOV r/m8, imm8.\n";
            error_flag = true;
            running = false;
        }
    }
    else { // Память
        uint32_t address = calculate_address(modrm);
        if (error_flag) {
            return; // Ошибка уже установлена в calculate_address
        }

        if (address >= memory.size()) {
            std::cout << "Memory access out of bounds in MOV r/m8, imm8.\n";
            error_flag = true;
            running = false;
            return;
        }

        memory[address] = imm8;
    }
}

// Обработчик инструкции MUL r/m32
void Emulator::instr_MUL_rm32(uint8_t modrm) {
    uint8_t mod = (modrm & 0xC0) >> 6;
    // uint8_t reg = (modrm & 0x38) >> 3; // Не используется для MUL r/m32
    uint8_t rm = (modrm & 0x07);       // Источник: r/m32

    uint32_t operand = 0;

    if (mod == 3) { // Регистр
        uint32_t* src_reg = get_register_by_code(rm);
        if (src_reg) {
            operand = *src_reg;
        }
        else {
            std::cout << "Неизвестный регистр в MUL r/m32.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        operand = read_memory_dword(address);
    }

    // Выполнение умножения: EDX:EAX = EAX * operand
    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);

    update_ZF(regs.EAX);
}

// Реализация обработчика для DIV r/m32
void Emulator::instr_DIV_rm32(uint8_t modrm) {
    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 {
            std::cout << "Неизвестный регистр в DIV r/m32.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else { // Операнд из памяти
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        operand = read_memory_dword(address); // Чтение операнда из памяти
    }

    if (operand == 0) {
        std::cout << "Деление на ноль.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Выполнение деления: EDX:EAX = EAX / operand
    uint64_t dividend = (static_cast<uint64_t>(regs.EDX) << 32) | regs.EAX;
    regs.EAX = static_cast<uint32_t>(dividend / operand);
    regs.EDX = static_cast<uint32_t>(dividend % operand);

    //std::cout << "DIV instruction: Dividend = " << dividend << ", Operand = " << operand
        //<< ", EAX = " << regs.EAX << ", EDX = " << regs.EDX << "\n";

    update_ZF(regs.EAX);
}
void Emulator::instr_LEA_r32_m() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg = (modrm >> 3) & 0x07; // Destination register code
    uint8_t rm = modrm & 0x07;         // Source operand

    // LEA is invalid with mod == 3 (register-direct mode)
    if (mod == 3) {
        std::cout << "Invalid LEA instruction with mod == 3.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Calculate the effective address
    uint32_t address = calculate_address(modrm);
    if (error_flag)
        return;

    // Get the destination register
    uint32_t* dest_reg = get_register_by_code(reg);
    if (!dest_reg) {
        std::cout << "Unknown destination register in LEA.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Store the effective address into the destination register
    *dest_reg = address;
}
void Emulator::instr_IDIV_rm32(uint8_t modrm) {
    uint8_t mod = (modrm & 0xC0) >> 6;
    uint8_t rm = (modrm & 0x07);       // Источник: r/m32

    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 {
            std::cout << "Неизвестный регистр в IDIV r/m32.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else { // Операнд из памяти
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;
        operand = read_memory_dword(address); // Чтение операнда из памяти
    }

    if (operand == 0) {
        std::cout << "Деление на ноль.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Выполнение деления: EDX:EAX = EAX / operand
    int64_t dividend = (static_cast<int64_t>(regs.EDX) << 32) | regs.EAX;
    regs.EAX = static_cast<uint32_t>(dividend / operand);
    regs.EDX = static_cast<uint32_t>(dividend % operand);

    update_ZF(regs.EAX);
}

// Общий обработчик для opcode 0xF7
void Emulator::instr_F7() {
    uint8_t modrm = fetch_byte();
    uint8_t reg = (modrm >> 3) & 0x07; // /digit

    switch (reg) {
    case 4: // MUL r/m32
        instr_MUL_rm32(modrm);
        break;
    case 6: // DIV r/m32
        instr_DIV_rm32(modrm);
        break;
    case 7: // IDIV r/m32
        instr_IDIV_rm32(modrm);
        break;
    default:
        std::cout << "F7 instruction with unsupported /digit: " << static_cast<int>(reg) << "\n";
        error_flag = true;
        running = false;
        break;
    }
}

void Emulator::instr_MOV_rm8_r8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t rm = modrm & 0x07;
    uint8_t reg = (modrm >> 3) & 0x07;

    uint8_t* src_reg = get_register8_by_code(reg);
    if (!src_reg) {
        std::cout << "Unknown source register in MOV r/m8, r8.\n";
        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) {
            std::cout << "Unknown destination register in MOV r/m8, r8.\n";
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg = value;
    }

    else {
        // Режим регистр-память
        uint32_t address = 0;
        if (rm == 4) {
            // SIB байт
            uint8_t sib = fetch_byte();
            int32_t displacement = 0;
            if (mod == 1) {
                displacement = static_cast<int8_t>(fetch_byte());
            }
            else if (mod == 2) {
                displacement = static_cast<int32_t>(fetch_dword());
            }
            address = calculate_sib_address(mod, sib, displacement);
        }
        else {
            int32_t displacement = 0;
            if (mod == 1) {
                displacement = static_cast<int8_t>(fetch_byte());
            }
            else if (mod == 2) {
                displacement = static_cast<int32_t>(fetch_dword());
            }
            address = *get_register_by_code(rm) + displacement;
        }
        if (address >= memory.size()) {
            std::cout << "Memory access out of bounds in MOV r/m8, r8.\n";
            error_flag = true;
            running = false;
            return;
        }
        memory[address] = value;
    }
    
}

void Emulator::instr_ADD_AL_imm8() {
    uint8_t imm8 = fetch_byte();
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    *al += imm8;
    update_ZF(*al); // Обновляем флаг ZF на основе 8-битного результата
}
void Emulator::instr_POP_EBP() {
    if (regs.ESP + 4 > memory.size()) {
        std::cerr << "Stack underflow on POP EBP.\n";
        error_flag = true;
        running = false;
        return;
    }
    // Pop the value from the stack into EBP
    regs.EBP = read_memory_dword(regs.ESP);
    regs.ESP += 4;

    std::cout << "Выполнен POP EBP. Значение в регистре EBP: 0x" << std::hex << regs.EBP << "\n";
}
void Emulator::instr_MOV_ESI_imm32() {
    regs.ESI = fetch_dword();
}

// INT n (0xCD)
void Emulator::instr_INT() {
    uint8_t int_number = fetch_byte();
    if (int_number == 0x80) {
        // Обработка системного вызова Linux
        uint32_t syscall_number = regs.EAX;
        switch (syscall_number) {
        case 1: // sys_exit
            running = false;
            break;
        case 3: { // sys_read
            uint32_t fd = regs.EBX;
            uint32_t buf = regs.ECX;
            uint32_t count = regs.EDX;

            if (fd == 0) { // stdin
                std::string input;
                std::getline(std::cin, input);

                // Читаем не более count байтов
                input = input.substr(0, count);

                // Записываем введённые данные в память
                for (size_t i = 0; i < input.size(); ++i) {
                    memory[buf + i] = static_cast<uint8_t>(input[i]);
                }

                // Если введённых данных меньше, чем запрошено, заполняем оставшиеся нулями
                for (size_t i = input.size(); i < count; ++i) {
                    memory[buf + i] = 0;
                }

                // Возвращаем количество прочитанных байтов в EAX
                regs.EAX = input.size();
            }
            else {
                std::cout << "Unsupported file descriptor in sys_read: " << fd << "\n";
                regs.EAX = -1; // Возвращаем -1 в случае ошибки
            }
        }
        case 4: { // sys_write
            uint32_t fd = regs.EBX;
            uint32_t buf = regs.ECX;
            uint32_t count = regs.EDX;
            // Debug output
            std::cout << "sys_write called with fd=" << fd
                << ", buf=0x" << std::hex << buf
                << ", count=" << std::dec << count << "\n";
            if (fd == 1) { // stdout
                // Ensure the buffer address is within memory bounds
                if (buf + count > memory.size()) {
                    std::cout << "Buffer out of bounds in sys_write.\n";
                    regs.EAX = -1; // Return -1 on error
                    break;
                }
                std::string output;
                for (uint32_t i = 0; i < count; ++i) {
                    output += static_cast<char>(memory[buf + i]);
                }
                std::cout << output; // Output the string

                // Return the number of bytes written
                regs.EAX = count;
            }

            else {
                std::cout << "Unsupported file descriptor in sys_write: " << fd << "\n";
                regs.EAX = -1; // Return -1 on error
            }
            break;
        }
        case 45: { // sys_brk
            uint32_t addr = regs.EBX;
            if (addr == 0) {
                // Возвращаем текущий адрес brk
                regs.EAX = current_brk;
            }
            else {
                // Устанавливаем новый адрес brk
                if (addr >= data_segment_start && addr < memory.size()) {
                    current_brk = addr;
                    regs.EAX = current_brk;
                }
                else {
                    // Ошибка: попытка установить brk за пределами памяти
                    regs.EAX = 0; // Ошибка
                }
            }
            break;
        }
        case 90: // sys_mmap
            // Реализация sys_mmap
            break;
        case 91: { // sys_munmap
            uint32_t addr = regs.EBX;
            uint32_t length = regs.ECX;
            // Для простоты, можно игнорировать освобождение памяти
            regs.EAX = 0;
            break;
        }
        case 5: { // sys_open
            const char* filename = reinterpret_cast<const char*>(&memory[regs.EBX]); // Путь к файлу
            uint32_t flags = regs.ECX;
            uint32_t mode = regs.EDX;
            // Для простоты, возвращаем фиктивный файловый дескриптор, например 3
            regs.EAX = 3;
            break;
        }
        case 6: { // sys_close
            uint32_t fd = regs.EBX;
            // Ничего не делаем, возвращаем успех
            regs.EAX = 0;
            break;
        }
        case 192: { // sys_mmap2
            uint32_t addr = regs.EBX;
            uint32_t length = regs.ECX;
            uint32_t prot = regs.EDX;
            uint32_t flags = regs.ESI;
            uint32_t fd = regs.EDI;
            uint32_t pgoffset = regs.EBP;

            // Если addr равен 0, выбираем свободный адрес
            if (addr == 0) {
                addr = allocate_memory(0, length);
            }
            else {
                // Проверяем, можем ли мы выделить память по запрошенному адресу
                addr = allocate_memory(addr, length);
            }

            if (addr == 0) {
                // Ошибка при выделении памяти
                regs.EAX = -1;
            }
            else {
                // Успешное выделение памяти
                regs.EAX = addr;
            }
            break;
        }
        case 195: // sys_fstat
            // Реализация sys_fstat
            break;
        case 197: { // sys_fstat64
            uint32_t fd = regs.EBX;
            uint32_t buf = regs.ECX;
            // Возвращаем фиктивные данные
            // В структуре struct stat64 около 104 байт
            memset(&memory[buf], 0, 104);
            regs.EAX = 0;
            break;
        }
        default:
            std::cout << "Неизвестный системный вызов: " << syscall_number << "\n";
            running = false;
            break;
        }
    }
    else {
        std::cout << "Неизвестное прерывание: INT " << (int)int_number << "\n";
        error_flag = true;
        running = false;
    }
}

void Emulator::instr_MOV_MEM_EAX() {
    uint32_t address = fetch_dword();
    if (address + 4 > memory.size()) {
        throw std::runtime_error("Выход за пределы памяти при MOV [address], EAX");
    }
    memory[address] = regs.EAX & 0xFF;
    memory[address + 1] = (regs.EAX >> 8) & 0xFF;
    memory[address + 2] = (regs.EAX >> 16) & 0xFF;
    memory[address + 3] = (regs.EAX >> 24) & 0xFF;
}

void Emulator::instr_MOV_EAX_MEM() {
    uint32_t address = fetch_dword();
    if (address + 4 > memory.size()) {
        throw std::runtime_error("Выход за пределы памяти при MOV EAX, [address]");
    }
    regs.EAX = memory[address] |
        (memory[address + 1] << 8) |
        (memory[address + 2] << 16) |
        (memory[address + 3] << 24);
}
// CMP EAX, EBX
void Emulator::instr_CMP_EAX_EBX() {
    uint8_t modrm = fetch_byte(); // Получаем ModRM байт
    uint8_t reg = (modrm >> 3) & 0x07; // Извлекаем регистры
    uint8_t rm = modrm & 0x07;

    // Проверяем, что регистры соответствуют EAX и EBX
    if (reg == 0 && rm == 3) { // 0 для EAX и 3 для EBX
        uint32_t result = regs.EAX - regs.EBX;

        // Zero Flag (ZF)
        if (result == 0)
            regs.EFLAGS |= ZF;
        else
            regs.EFLAGS &= ~ZF;

        // Sign Flag (SF)
        if (result & (1 << 31))
            regs.EFLAGS |= SF;
        else
            regs.EFLAGS &= ~SF;

        // Остальная обработка флагов
    }
    else {
        std::cout << "CMP instruction with unsupported register combination.\n";
        error_flag = true;
        running = false;
    }
}

void Emulator::instr_JG_rel8() {
    int8_t rel = fetch_byte();

    bool zf = (regs.EFLAGS & ZF) != 0;
    bool sf = (regs.EFLAGS & SF) != 0;
    bool of = (regs.EFLAGS & OF) != 0;

    // JG переходит, если ZF = 0 и SF = OF
    if (!zf && (sf == of)) {
        regs.EIP += rel;
    }
}
// Реализация инструкции IMUL reg, r/m32, imm32
void Emulator::instr_IMUL_reg_rm32_imm32() {
    // Before reading ModRM byte, EIP points to it
    std::cout << "EIP before fetch_byte (ModRM): 0x" << std::hex << regs.EIP << "\n";

    uint8_t modrm = fetch_byte(); // Read ModRM byte
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07; // Destination register
    uint8_t rm_code = modrm & 0x07;         // Source operand

    // Debug output
    std::cout << "Executing IMUL with modrm: 0x" << std::hex << (int)modrm << "\n";
    std::cout << "Destination reg code: " << (int)reg_code << ", Source rm code: " << (int)rm_code << "\n";
    std::cout << "EIP after fetch_byte (ModRM): 0x" << std::hex << regs.EIP << "\n";

    uint32_t* dest_reg = get_register_by_code(reg_code);
    uint32_t* src_reg = nullptr;

    if (mod == 3) { // Register-register mode
        src_reg = get_register_by_code(rm_code);
        if (!src_reg) {
            std::cout << "Unknown source register in IMUL.\n";
            error_flag = true;
            running = false;
            return;
        }
    }
    else {
        std::cout << "Unsupported addressing mode in IMUL.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Check if dest_reg is valid
    if (!dest_reg) {
        std::cout << "Unknown destination register in IMUL.\n";
        error_flag = true;
        running = false;
        return;
    }

    // Before reading imm32, EIP points to it
    std::cout << "EIP before fetch_dword (imm32): 0x" << std::hex << regs.EIP << "\n";

    uint32_t imm32 = fetch_dword(); // Read immediate value imm32

    // After reading imm32, EIP should have been incremented by 4
    std::cout << "EIP after fetch_dword (imm32): 0x" << std::hex << regs.EIP << "\n";
    // Debug output of imm32
    std::cout << "Immediate value: " << std::dec << imm32 << "\n";

    // Perform signed multiplication
    int32_t result = static_cast<int32_t>(*src_reg) * static_cast<int32_t>(imm32);
    *dest_reg = static_cast<uint32_t>(result);

    // Update flags appropriately
    update_ZF(*dest_reg);
    // Update other flags (CF, OF) if necessary
}

void Emulator::instr_SUB_AL_imm8() {
    uint8_t imm8 = fetch_byte();
    uint8_t* al = reinterpret_cast<uint8_t*>(&regs.EAX);
    *al -= imm8;
    update_ZF(*al);
}
void Emulator::instr_JMP_rel8() {
    int8_t rel = fetch_byte();
    regs.EIP += rel;
}
void Emulator::instr_JB_rel8() {
    int8_t rel = fetch_byte();
    if (regs.EFLAGS & CF) {
        regs.EIP += rel;
    }
}

void Emulator::instr_JA_rel8() {
    int8_t rel = fetch_byte();
    bool cf = (regs.EFLAGS & CF) != 0;
    bool zf = (regs.EFLAGS & ZF) != 0;
    if (!cf && !zf) {
        regs.EIP += rel;
    }
}
void Emulator::instr_INC_ECX() {
    regs.ECX += 1;
    update_ZF(regs.ECX);
}
void Emulator::instr_MOV_r8_imm8() {
    uint8_t opcode = memory[regs.EIP - 1]; // Последний прочитанный опкод
    uint8_t reg_code = opcode - 0xB0; // Регистры AL, CL, DL, BL, AH, CH, DH, BH идут от 0xB0 до 0xB7

    uint8_t imm8 = fetch_byte();
    uint8_t* reg = get_register8_by_code(reg_code);

    if (!reg) {
        std::cout << "Unknown register in MOV r8, imm8.\n";
        error_flag = true;
        running = false;
        return;
    }

    *reg = imm8;
}
void Emulator::instr_SUB_rm8_imm8() {
    uint8_t modrm = fetch_byte();
    uint8_t opcode = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;

    if (opcode != 5) {
        std::cout << "Unsupported opcode in SUB rm8, imm8.\n";
        error_flag = true;
        running = false;
        return;
    }

    uint8_t imm8 = fetch_byte();
    uint8_t* dest = get_register8_by_code(rm_code);

    if (!dest) {
        std::cout << "Unknown register in SUB rm8, imm8.\n";
        error_flag = true;
        running = false;
        return;
    }

    *dest -= imm8;

    update_ZF(*dest);
}
void Emulator::instr_MOV_r8_rm8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = modrm >> 6;
    uint8_t reg_code = (modrm >> 3) & 0x07; // Назначение: r8
    uint8_t rm = modrm & 0x07;              // Источник: r/m8

    uint8_t* reg = get_register8_by_code(reg_code);
    if (!reg) {
        std::cout << "Unknown register in MOV r8, rm8.\n";
        error_flag = true;
        running = false;
        return;
    }

    uint32_t address = 0;

    if (mod == 0) {
        if (rm == 4) {
            // Обработка SIB байта
            uint8_t sib = fetch_byte();
            address = calculate_sib_address(mod, sib, 0);
        }
        else if (rm == 5) {
            // [disp32]
            address = fetch_dword();
        }
        else {
            // [reg]
            uint32_t* rm_reg = get_register_by_code(rm);
            if (rm_reg) {
                address = *rm_reg;
            }
            else {
                std::cout << "Unknown base register in MOV r8, rm8.\n";
                error_flag = true;
                running = false;
                return;
            }
        }
    }
    else if (mod == 1) {
        int8_t disp8 = static_cast<int8_t>(fetch_byte());
        if (rm == 4) {
            // Обработка SIB байта
            uint8_t sib = fetch_byte();
            address = calculate_sib_address(mod, sib, disp8);
        }
        else {
            // [reg + disp8]
            uint32_t* rm_reg = get_register_by_code(rm);
            if (rm_reg) {
                address = *rm_reg + disp8;
            }
            else {
                std::cout << "Unknown base register in MOV r8, rm8.\n";
                error_flag = true;
                running = false;
                return;
            }
        }
    }
    else if (mod == 2) {
        int32_t disp32 = static_cast<int32_t>(fetch_dword());
        if (rm == 4) {
            // Обработка SIB байта
            uint8_t sib = fetch_byte();
            address = calculate_sib_address(mod, sib, disp32);
        }
        else {
            // [reg + disp32]
            uint32_t* rm_reg = get_register_by_code(rm);
            if (rm_reg) {
                address = *rm_reg + disp32;
            }
            else {
                std::cout << "Unknown base register in MOV r8, rm8.\n";
                error_flag = true;
                running = false;
                return;
            }
        }
    }
    else if (mod == 3) {
        // MOV r8, r8
        uint8_t* rm_reg = get_register8_by_code(rm);
        if (rm_reg) {
            *reg = *rm_reg;
        }
        else {
            std::cout << "Unknown register in MOV r8, rm8.\n";
            error_flag = true;
            running = false;
        }
        return;
    }
    else {
        std::cout << "Unsupported mod in MOV r8, rm8.\n";
        error_flag = true;
        running = false;
        return;
    }

    if (address >= memory.size()) {
        std::cout << "Memory access out of bounds in MOV r8, [address].\n";
        error_flag = true;
        running = false;
        return;
    }

    *reg = memory[address];
}
// MOV EBP, imm32
void Emulator::instr_MOV_EBP_imm32() {
    uint32_t imm = fetch_dword();
    regs.EBP = imm;
}
// MOV ESP, imm32
void Emulator::instr_MOV_ESP_imm32() {
    uint32_t imm = fetch_dword();
    regs.ESP = imm;
}

// MOV EDI, imm32
void Emulator::instr_MOV_EDI_imm32() {
    uint32_t imm = fetch_dword();
    regs.EDI = imm;
}
void Emulator::instr_MOV_r32_r_m32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07; // Destination register (r32)
    uint8_t rm = modrm & 0x07;         // Source (r/m32)

    uint32_t* dest_reg = get_register_by_code(reg);

    if (mod == 3) { // Register-register mode
        uint32_t* src_reg = get_register_by_code(rm);
        if (dest_reg && src_reg) {
            *dest_reg = *src_reg;
        }
        else {
            std::cout << "Unknown register in MOV r32, r/m32.\n";
            error_flag = true;
            running = false;
        }
    }
    else { // Memory to register
        uint32_t address = calculate_address(modrm);
        if (error_flag) return;

        uint32_t value = read_memory_dword(address);
        if (dest_reg) {
            *dest_reg = value;
        }
        else {
            std::cout << "Unknown destination register in MOV r32, r/m32.\n";
            error_flag = true;
            running = false;
        }
    }
}
void Emulator::instr_ADD_r32_rm32() {
    uint8_t modrm = fetch_byte();
    Operand operand = decode_operand(modrm); // Предполагается, что вы реализовали структуру Operand

    uint8_t reg_code = (modrm >> 3) & 0x07;
    uint8_t rm_code = modrm & 0x07;

    uint32_t* reg = get_register_by_code(reg_code);

    if (!reg) {
        std::cout << "Unknown destination register in ADD r32, r/m32.\n";
        error_flag = true;
        running = false;
        return;
    }

    if (operand.is_memory) {
        uint32_t value = read_memory_dword(operand.address);
        *reg += value;
    }
    else {
        uint32_t* src_reg = get_register_by_code(rm_code);
        if (!src_reg) {
            std::cout << "Unknown source register in ADD r32, r/m32.\n";
            error_flag = true;
            running = false;
            return;
        }
        *reg += *src_reg;
    }

    update_ZF(*reg);
    // Обновите другие флаги при необходимости
}

void Emulator::instr_ADD_rm32_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; // Source register (r32)
    uint8_t rm_code = modrm & 0x07;         // Destination (r/m32)

    uint32_t* src_reg = get_register_by_code(reg_code);

    if (mod == 3) { // Register-register mode
        uint32_t* dest_reg = get_register_by_code(rm_code);
        if (src_reg && dest_reg) {
            if (is_locked) {
                std::cout << "LOCK prefix applied to ADD r32, r/m32.\n";
            }
            *dest_reg += *src_reg;
            update_ZF(*dest_reg);
            // Update other flags as needed
        }
        else {
            std::cout << "Unknown register in ADD r/m32, r32.\n";
            error_flag = true;
            running = false;
        }
    }
    else { // Memory operand
        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(value);
        // Update other flags as needed
    }
    reset_prefixes();
}
void Emulator::instr_CMP_AL_imm8() {
    uint8_t imm8 = fetch_byte();
    uint8_t al = regs.EAX & 0xFF;
    uint8_t result = al - imm8;

    // Update Zero Flag (ZF)
    if (result == 0)
        regs.EFLAGS |= ZF;
    else
        regs.EFLAGS &= ~ZF;

    // Update Sign Flag (SF)
    if (result & 0x80)
        regs.EFLAGS |= SF;
    else
        regs.EFLAGS &= ~SF;

    // Update Carry Flag (CF)
    if (al < imm8)
        regs.EFLAGS |= CF;
    else
        regs.EFLAGS &= ~CF;

    // Update Overflow Flag (OF)
    bool overflow = ((al ^ imm8) & (al ^ result) & 0x80) != 0;
    if (overflow)
        regs.EFLAGS |= OF;
    else
        regs.EFLAGS &= ~OF;
}
void Emulator::instr_JL_rel8() {
    int8_t rel = fetch_byte();

    bool sf = (regs.EFLAGS & SF) != 0;
    bool of = (regs.EFLAGS & OF) != 0;

    // JL переходит, если SF != OF
    if (sf != of) {
        regs.EIP += rel;
    }
}

void Emulator::instr_XOR_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07; // Source register (r32)
    uint8_t rm = modrm & 0x07;         // Destination (r/m32)

    if (mod == 3) { // Register-register mode
        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(*dest_reg);
        }
        else {
            std::cout << "Unknown register in XOR r/m32, r32.\n";
            error_flag = true;
            running = false;
        }
    }
    // ...
}
void Emulator::instr_CALL_rel32() {
    int32_t rel32 = fetch_dword();
    // Push the next instruction address onto the stack
    push(regs.EIP);
    // Jump to the target address
    regs.EIP += rel32;
}
// Обработчик для opcode 0x81 (32-битное непосредственное значение)
void Emulator::instr_GROUP1_Ev_Iz_81() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_opcode = (modrm >> 3) & 0x07; // Поле reg в ModRM
    uint8_t rm = modrm & 0x07;

    uint32_t* dest_reg = nullptr;
    if (mod == 3) { // Режим регистр-регистр
        dest_reg = get_register_by_code(rm);
    }
    else {
        // Обработка памяти (не реализовано)
        std::cout << "Memory operands not implemented for opcode 0x81.\n";
        error_flag = true;
        running = false;
        return;
    }

    uint32_t imm32 = fetch_dword(); // Чтение 32-битного непосредственного значения

    switch (reg_opcode) {
    case 0: // ADD
        *dest_reg += imm32;
        update_ZF(*dest_reg);
        break;
    case 1: // OR
        *dest_reg |= imm32;
        update_ZF(*dest_reg);
        break;
    case 2: // ADC
        // Реализуйте ADC при необходимости
        break;
    case 3: // SBB
        // Реализуйте SBB при необходимости
        break;
    case 4: // AND
        *dest_reg &= imm32;
        update_ZF(*dest_reg);
        break;
    case 5: // SUB
        *dest_reg -= imm32;
        update_ZF(*dest_reg);
        break;
    case 6: // XOR
        *dest_reg ^= imm32;
        update_ZF(*dest_reg);
        break;
    case 7: // CMP
    {
        uint32_t result = *dest_reg - imm32;
        update_ZF(result);
        // Обновите другие флаги при необходимости
    }
    break;
    default:
        std::cout << "Unsupported reg opcode in opcode 0x81: " << (int)reg_opcode << "\n";
        error_flag = true;
        running = false;
        break;
    }
}

// Обработчик для opcode 0x83 (8-битное непосредственное значение)
void Emulator::instr_GROUP1_Ev_Iz_83() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_opcode = (modrm >> 3) & 0x07; // Поле reg в ModRM
    uint8_t rm = modrm & 0x07;

    uint32_t* dest_reg = nullptr;
    if (mod == 3) { // Режим регистр-регистр
        dest_reg = get_register_by_code(rm);
    }
    else {
        // Обработка памяти (не реализовано)
        std::cout << "Memory operands not implemented for opcode 0x83.\n";
        error_flag = true;
        running = false;
        return;
    }

    int8_t imm8 = static_cast<int8_t>(fetch_byte()); // Чтение 8-битного непосредственного значения

    // Знаковое расширение до 32 бит
    int32_t sign_extended_imm = static_cast<int32_t>(imm8);

    switch (reg_opcode) {
    case 0: // ADD
        *dest_reg += sign_extended_imm;
        update_ZF(*dest_reg);
        break;
    case 1: // OR
        *dest_reg |= sign_extended_imm;
        update_ZF(*dest_reg);
        break;
    case 2: // ADC
        // Реализуйте ADC при необходимости
        break;
    case 3: // SBB
        // Реализуйте SBB при необходимости
        break;
    case 4: // AND
        *dest_reg &= sign_extended_imm;
        update_ZF(*dest_reg);
        break;
    case 5: // SUB
        *dest_reg -= sign_extended_imm;
        update_ZF(*dest_reg);
        break;
    case 6: // XOR
        *dest_reg ^= sign_extended_imm;
        update_ZF(*dest_reg);
        break;
    case 7: // CMP
    {
        uint32_t result = *dest_reg - sign_extended_imm;
        update_ZF(result);
        // Обновите другие флаги при необходимости
    }
    break;
    default:
        std::cout << "Unsupported reg opcode in opcode 0x83: " << (int)reg_opcode << "\n";
        error_flag = true;
        running = false;
        break;
    }
}
void Emulator::instr_JL_rel32() {
    int32_t rel32 = fetch_dword(); // Читаем относительное смещение
    bool sf = (regs.EFLAGS & SF) != 0;
    bool of = (regs.EFLAGS & OF) != 0;
    if (sf != of) {
        regs.EIP += rel32;
    }
}
void Emulator::instr_MOVSB() {
    // Обработка префиксов REP/REPE/REPNE
    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(byte);

            // Для `REPNE` можно добавить условия выхода
            if (is_repne && (regs.EFLAGS & ZF)) {
                break;
            }

            if (is_rep && regs.ECX == 0) {
                break;
            }
        }

        // Сброс префиксов после выполнения
        reset_prefixes();
    }
    else {
        // Обычное выполнение MOVSB без повторения
        uint8_t byte = read_memory_byte(regs.ESI);
        write_memory_byte(regs.EDI, byte);
        regs.ESI += 1;
        regs.EDI += 1;

        // Обновление флагов по необходимости
        update_ZF(byte);
    }
}
void Emulator::instr_ADD_rm8_r8() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg_code = (modrm >> 3) & 0x07; // Source register (r8)
    uint8_t rm = modrm & 0x07;              // Destination (r/m8)

    uint8_t* src_reg = get_register8_by_code(reg_code);
    if (!src_reg) {
        std::cout << "Unknown source register in ADD r/m8, r8.\n";
        error_flag = true;
        running = false;
        return;
    }

    if (mod == 3) { // Register to register
        uint8_t* dest_reg = get_register8_by_code(rm);
        if (!dest_reg) {
            std::cout << "Unknown destination register in ADD r/m8, r8.\n";
            error_flag = true;
            running = false;
            return;
        }
        *dest_reg += *src_reg;
        update_ZF(*dest_reg);
    }
    else {
        // Memory operand
        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(value);
    }
    // Update other flags (CF, OF, etc.) as necessary
}
void Emulator::instr_MOV_r32_rm32() {
    uint8_t modrm = fetch_byte();
    uint8_t mod = (modrm >> 6) & 0x03;
    uint8_t reg = (modrm >> 3) & 0x07; // Source register (r32)
    uint8_t rm = modrm & 0x07;         // Destination (r/m32)

    if (mod == 3) { // Register-register mode
        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 {
            std::cout << "Unknown register in MOV r/m32, r32.\n";
            error_flag = true;
            running = false;
        }
    }
    // ...
}

C:\Users\Swed\source\repos\x86_Emulator\x64\Debug>x86_Emulator.exe main2.elf

Запуск программы из файла: main2.elf...
Объем выделенной памяти эмулятора: 1024 MB
ELF-файл успешно загружен. Точка входа: 0x80495b0
EIP: 0x80495b0
ESP: 3fffffec, Значение на вершине стека: 0
Обнаружен префикс: 0xf3
Выполнена инструкция ENDBR32 (пропущена).
EIP: 0x80495b4
ESP: 3fffffec, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffec
EBP: 0x0
EIP: 0x80495b6
EFLAGS: 0x40
EFLAGS: 0x40
EIP: 0x80495b6
ESP: 3fffffec, Значение на вершине стека: 0
Выполнен POP ESI. Значение в регистре ESI: 0
EAX: 0x0
EBX: 0x0
ECX: 0x0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3ffffff0
EBP: 0x0
EIP: 0x80495b7
EFLAGS: 0x40
EFLAGS: 0x40
EIP: 0x80495b7
ESP: 3ffffff0, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3ffffff0
EBP: 0x0
EIP: 0x80495b9
EFLAGS: 0x40
EFLAGS: 0x40
EIP: 0x80495b9
ESP: 3ffffff0, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3ffffff0
EBP: 0x0
EIP: 0x80495bc
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495bc
ESP: 3ffffff0, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffec
EBP: 0x0
EIP: 0x80495bd
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495bd
ESP: 3fffffec, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe8
EBP: 0x0
EIP: 0x80495be
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495be
ESP: 3fffffe8, Значение на вершине стека: 3fffffec
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe4
EBP: 0x0
EIP: 0x80495bf
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495bf
ESP: 3fffffe4, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x0
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe0
EBP: 0x0
EIP: 0x80495dd
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495dd
ESP: 3fffffe0, Значение на вершине стека: 80495c4
EAX: 0x0
EBX: 0x80495c4
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe0
EBP: 0x0
EIP: 0x80495e0
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495e0
ESP: 3fffffe0, Значение на вершине стека: 80495c4
EAX: 0x0
EBX: 0x80495c4
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe4
EBP: 0x0
EIP: 0x80495c4
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495c4
ESP: 3fffffe4, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe4
EBP: 0x0
EIP: 0x80495ca
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495ca
ESP: 3fffffe4, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffe0
EBP: 0x0
EIP: 0x80495cc
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495cc
ESP: 3fffffe0, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffdc
EBP: 0x0
EIP: 0x80495ce
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495ce
ESP: 3fffffdc, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffd8
EBP: 0x0
EIP: 0x80495cf
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495cf
ESP: 3fffffd8, Значение на вершине стека: 3ffffff0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffd4
EBP: 0x0
EIP: 0x80495d0
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495d0
ESP: 3fffffd4, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffd4
EBP: 0x0
EIP: 0x80495d6
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495d6
ESP: 3fffffd4, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffd0
EBP: 0x0
EIP: 0x80495d7
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x80495d7
ESP: 3fffffd0, Значение на вершине стека: 8049725
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffcc
EBP: 0x0
EIP: 0x804a980
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a980
ESP: 3fffffcc, Значение на вершине стека: 80495dc
Обнаружен префикс: 0xf3
Выполнена инструкция ENDBR32 (пропущена).
EIP: 0x804a984
ESP: 3fffffcc, Значение на вершине стека: 80495dc
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffc8
EBP: 0x0
EIP: 0x804a985
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a985
ESP: 3fffffc8, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffc4
EBP: 0x0
EIP: 0x804a986
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a986
ESP: 3fffffc4, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffc0
EBP: 0x0
EIP: 0x804a987
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a987
ESP: 3fffffc0, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x0
EDI: 0x0
ESP: 0x3fffffbc
EBP: 0x0
EIP: 0x804ba87
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804ba87
ESP: 3fffffbc, Значение на вершине стека: 804a98c
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x804a98c
EDI: 0x0
ESP: 0x3fffffbc
EBP: 0x0
EIP: 0x804ba8a
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804ba8a
ESP: 3fffffbc, Значение на вершине стека: 804a98c
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x804a98c
EDI: 0x0
ESP: 0x3fffffc0
EBP: 0x0
EIP: 0x804a98c
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a98c
ESP: 3fffffc0, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffffc0
EBP: 0x0
EIP: 0x804a992
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a992
ESP: 3fffffc0, Значение на вершине стека: 0
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffffbc
EBP: 0x0
EIP: 0x804a993
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a993
ESP: 3fffffbc, Значение на вершине стека: 80ed000
EAX: 0x8049725
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a999
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a999
ESP: 3fffff30, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x3ffffff0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9a0
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a9a0
ESP: 3fffff30, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9a7
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a9a7
ESP: 3fffff30, Значение на вершине стека: 0
EAX: 0x0
EBX: 0x80ed000
ECX: 0x0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9ae
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a9ae
ESP: 3fffff30, Значение на вершине стека: 0
EAX: 0x3ffffeb8
EBX: 0x80ed000
ECX: 0x0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9b2
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a9b2
ESP: 3fffff30, Значение на вершине стека: 0
EAX: 0x3ffffeb8
EBX: 0x80ed000
ECX: 0x0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9b4
EFLAGS: 0x0
EFLAGS: 0x0
EIP: 0x804a9b4
ESP: 3fffff30, Значение на вершине стека: 0
Неизвестный opcode: 0x34
EAX: 0x3ffffeb8
EBX: 0x80ed000
ECX: 0x0
EDX: 0x0
ESI: 0x80ed000
EDI: 0x0
ESP: 0x3fffff30
EBP: 0x0
EIP: 0x804a9b5
EFLAGS: 0x0
EFLAGS: 0x0

Программа из ELF-файла не выполнена.