Цей проєкт реалізує програмну емуляцію системи портів введення-виведення (I/O) архітектури x86 у середовищі Windows на мові C++.
Мета — надати безпечний інструмент для навчання та експериментів з низькорівневим введенням-виведенням без прямого доступу до апаратури та без написання драйверів ядра.
Основна ідея: замість справжніх I/O-портів створюється набір віртуальних портів, які поводяться подібно до апаратних, але існують лише в памʼяті програми.
- Емуляція адресного простору портів x86 (0x0000–0xFFFF).
- Створення віртуальних портів з індивідуальною логікою:
- порти введення,
- порти виведення,
- двонаправлені порти.
- OOП-архітектура:
- базовий інтерфейс порту (
Port); - похідні класи для конкретних пристроїв (наприклад, віртуальна клавіатура).
- базовий інтерфейс порту (
- Централізований менеджер портів:
- реєстрація/видалення портів,
- пошук порту за адресою,
- маршрутизація операцій читання/запису.
- Проміжний рівень обробки операцій (
IOHandler):- уніфікований інтерфейс для виконання команд введення-виведення;
- перевірка коректності адреси та значення перед передачею в
PortManager; - спрощення взаємодії між віртуальними пристроями та механізмом портів;
- використовується як у CLI-режимі, так і в окремих пристроях (наприклад, VirtualKeyboard).
- Консольний інтерфейс (CLI) для тестування:
- читання значення порту;
- запис значення в порт;
- вивід списку зареєстрованих портів;
- симуляція натискання клавіш (для віртуальної клавіатури) — якщо реалізовано.
- Можливість розширення новими віртуальними пристроями.
Увага: назви класів/файлів нижче — приклад. Підстав свої реальні назви з коду.
-
Port- абстрактний базовий клас або інтерфейс для всіх віртуальних портів;
- типово містить:
uint16_t address;- віртуальні методи:
virtual uint8_t read() = 0;virtual void write(uint8_t value) = 0;
-
Конкретні порти:
KeyboardPort
Емуляція контролера клавіатури (аналог портів 0x60 / 0x64):- внутрішній буфер скан-кодів;
- методи для "натискання" клавіш із коду (для тестів).
- (за потреби)
GeneralPurposePort,StatusPort, інші класи-емулятори.
-
PortManager/Emulator- відповідає за:
- реєстрацію портів:
registerPort(std::shared_ptr<Port> port); - пошук порту за адресою;
- високорівневі операції:
uint8_t in(uint16_t portAddress);void out(uint16_t portAddress, uint8_t value);
- реєстрацію портів:
- відповідає за:
-
IOHandler- проміжний компонент для виконання операцій введення-виведення;
- забезпечує:
- спрощений інтерфейс роботи з портами через методи
in()таout(); - перевірку наявності порту та коректності параметрів;
- інкапсуляцію роботи
PortManagerпри взаємодії з CLI або віртуальними пристроями; - можливість централізовано керувати помилками та логуванням операцій.
- спрощений інтерфейс роботи з портами через методи
-
main.cpp-
точка входу;
-
ініціалізація
PortManagerта реєстрація необхідних портів; -
реалізація консольного інтерфейсу:
- цикл команд:
in <addr>,out <addr> <value>,list,exitтощо; - демонстраційні сценарії для розділу "Приклади використання".
- цикл команд:
-
для демонстрації роботи віртуальної клавіатури слід використовувати такий варіант
main():int main() { SetConsoleOutputCP(1251); SetConsoleCP(1251); PortManager manager; manager.initialize(256); IOHandler io(manager); VirtualKeyboard keyboard(io); std::cout << "Введіть символ для передачі у порт 0x60: "; char input; std::cin >> input; keyboard.sendKey(input); // записуємо символ у порт keyboard.readKey(); // зчитуємо назад return 0; }
-
для тестування роботи емулятора у режимі CLI використовується наступний варіант
main():int main() { PortManager manager; manager.initialize(256); IOHandler io(manager); std::string command; std::cout << "Емулятор портів x86 запущено.\n"; std::cout << "Команди: OUT <addr> <value>, IN <addr>, STATE, EXIT\n"; while (true) { std::cout << "> "; std::getline(std::cin, command); std::stringstream ss(command); std::string op; ss >> op; if (op == "OUT") { int addr, val; ss >> std::hex >> addr >> std::dec >> val; io.out(addr, val); } else if (op == "IN") { int addr; ss >> std::hex >> addr; std::cout << "Значення: " << (int)io.in(addr) << "\n"; } else if (op == "STATE") { manager.displayState(); } else if (op == "EXIT") { break; } else { std::cout << "Невідома команда.\n"; } } }
-