commit 930cd451a9bed6140e5fe612a1f2c5fb3ce9951c Author: pablusha Date: Sat Jun 7 18:45:05 2025 +0300 это ужас diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d9cae5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +emulator +pizda \ No newline at end of file diff --git a/emulator.h b/emulator.h new file mode 100644 index 0000000..e50e107 --- /dev/null +++ b/emulator.h @@ -0,0 +1,117 @@ +#include +#include +#include + +#define MEMORY_SIZE 1048576 + +union reg16 { + struct { + uint8_t low; + uint8_t high; + }; + uint16_t value; +}; + +struct ModRM { + uint8_t mod; // addressing mode + uint8_t reg; // source + uint8_t rm; // dest +}; + +reg16 AX, BX, CX, DX; // general regs +uint16_t SI, DI; // source index, dest index +uint16_t BP, SP; // base ptr, stack ptr +uint16_t IP; // instruction ptr +uint16_t CS, DS, ES, SS; // code segmets reg, data segment reg, extra segment reg, stack segment reg + +bool CF; // carry +bool PF; // parity +bool AF; // auxiliary carry +bool ZF; // zero +bool SF; // sign +bool TF; // trap +bool IF; // interrupt +bool DF; // direction +bool OF; // overflow + +uint8_t ram[MEMORY_SIZE]; + +uint32_t physical_addr(uint16_t seg, uint16_t offset); +bool load_binary(char* filename, size_t addr); +ModRM parse_modrm(uint8_t byte); + +uint8_t get_reg_byte(uint8_t code); +uint8_t set_reg_byte(uint8_t code, uint8_t value); + +uint32_t physical_addr(uint16_t seg, uint16_t offset) { + return ((uint32_t) seg << 4) + offset; +} + +bool load_binary(char* filename, size_t addr) { + std::ifstream file(filename, std::ios::binary); + if (!file) { + std::cerr << "failed to open file " << filename << "\n"; + return false; + } + + file.seekg(0, std::ios::end); + size_t file_size = file.tellg(); + file.seekg(0, std::ios::beg); + + if (file_size > MEMORY_SIZE - addr) { + std::cerr << "file is too big"; + return false; + } + + file.read(reinterpret_cast(ram + addr), file_size); + + if (!file) { + std::cerr << "failed to read entire file"; + return false; + } + + std::cout << "file " << filename << " loaded to ram\n"; + return true; +} + +ModRM parse_modrm(uint8_t byte) { + ModRM modrm; + modrm.mod = (byte >> 6) & 0x3; + modrm.reg = (byte >> 3) & 0x7; + modrm.rm = byte & 0x7; + return modrm; +} + +uint8_t get_reg_byte(uint8_t code, uint8_t value) { + switch (code) + { + case 0: AX.low = value; break; + case 1: CX.low = value; break; + case 2: DX.low = value; break; + case 3: BX.low = value; break; + case 4: AX.high = value; break; + case 5: AX.high = value; break; + case 6: AX.high = value; break; + case 7: AX.high = value; break; + default: + std::cerr << "invalid reg code for 8-bit reg"; + return 0; + } +} + +uint8_t set_reg_byte(uint8_t code) { + switch (code) + { + case 0: return AX.low; + case 1: return CX.low; + case 2: return DX.low; + case 3: return BX.low; + case 4: return AX.high; + case 5: return CX.high; + case 6: return DX.high; + case 7: return BX.high; + default: + std::cerr << "invalid reg code for 8-bit reg"; + return 0; + } +} \ No newline at end of file diff --git a/instructions.h b/instructions.h new file mode 100644 index 0000000..6d14fe7 --- /dev/null +++ b/instructions.h @@ -0,0 +1,10 @@ +#include "emulator.h" + +void add_eb_gb() { + uint32_t addr = physical_addr(CS, IP); + uint8_t modrm_byte = ram[addr]; + IP++; + + ModRM modrm = parse_modrm(modrm_byte); + uint8_t gb_value = get_reg_byte(modrm.reg); +} \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..622c837 --- /dev/null +++ b/main.cpp @@ -0,0 +1,28 @@ +#include "instructions.h" + +void emulate() { + while (1) { + uint32_t addr = physical_addr(CS, IP); + uint8_t opcode = ram[addr]; + + IP++; + } +} + +int main(int argc, char* argv[]) { + CS = 0x0000; + IP = 0x0100; + + if (argc < 2) { + std::cerr << "usage: " << argv[0] << "\n"; + return 1; + } + + char* filename = argv[1]; + if (!load_binary(filename, 0x0100)) { + return 1; + } + + emulate(); + return 0; +} \ No newline at end of file