```markdown # КВС Ассемблер с русским синтаксисом для x86-64 **КВС** — это экспериментальный ассемблер для архитектуры x86-64, полностью использующий **русскую лексику** для мнемоник инструкций, имён регистров и директив. Проект носит образовательный характер и демонстрирует принципы работы ассемблера, построения ELF-файлов и трансляции высокоуровневых концепций в машинный код. ## 📋 Оглавление - [Особенности](#-особенности) - [Архитектура](#-архитектура) - [Установка](#-установка) - [Быстрый старт](#-быстрый-старт) - [Синтаксис](#-синтаксис) - [Система команд](#-система-команд) - [Регистры](#-регистры-процессора) - [Директивы](#-директивы-ассемблера) - [Примеры программ](#-примеры-программ) - [Отладка](#-отладка-и-проверка) - [Ограничения](#-ограничения) - [План развития](#-план-развития) - [Лицензия](#-лицензия) ## ✨ Особенности - **Полностью русский синтаксис** — все инструкции, регистры и директивы на кириллице - **Генерация исполняемых ELF-файлов** — 64-битные ELF для Linux, готовые к запуску - **Двухпроходная сборка** — традиционная схема с разрешением меток - **Поддержка секций** — разделение на `.текст` (код) и `.данные` (данные) - **Абсолютная адресация памяти** — чтение и запись по меткам `[переменная]` и абсолютным адресам `[0x402000]` с RIP-relative кодированием - **CSV-логирование** — детальный файл с соответствием адресов, байтов и исходных команд - **Более 50 инструкций** — полный набор основных команд x86-64 - **Минимализм зависимостей** — только стандартная библиотека Python - **Рефакторинг** — кодогенерация вынесена в отдельный модуль `kvs_pass2_encoder.py` ## 🏗 Архитектура Процесс трансляции исходного кода `.квс` в исполняемый файл `.elf` проходит через несколько этапов: ``` Исходный файл (.квс) │ ▼ (kvs_lexer.py) Файл токенов (.токены) │ ▼ (kvs_parser.py) AST-представление (.аст) │ ▼ (kvs_pass1.py) Первый проход: размеры, метки (.проход1) │ ▼ (kvs_pass2.py + kvs_pass2_encoder.py) Второй проход: генерация кода (.csv) │ ▼ (kvs_builder.py) ELF-компоновщик (.elf) Исполняемый файл! ``` ### Модули компилятора | Файл | Назначение | |------|------------| | `kvs_build.py` | Главный сборочный скрипт | | `kvs_lexer.py` | Лексический анализ, разбор на токены | | `kvs_parser.py` | Синтаксический анализ, построение AST | | `kvs_pass1.py` | Первый проход: вычисление размеров и адресов меток | | `kvs_pass2.py` | Второй проход: обход AST, генерация CSV | | `kvs_pass2_encoder.py` | Кодировщик инструкций (все encode_* функции) | | `kvs_builder.py` | Сборка ELF-файла из CSV | | `kvs_data.py` | Общие данные (регистры, инструкции) | ## 🔧 Установка ```bash # Клонирование репозитория git clone https://github.com/username/kvs.git cd kvs # Установка прав на выполнение (при необходимости) chmod +x kvs_build.py # Проверка работы python3 kvs_build.py --help ``` ## 🚀 Быстрый старт ### 1. Создайте файл `hello.квс`: ```asm .текст .глобал _start _start: ; write(1, msg, 13) переместить_имм раикс, 1 переместить_имм рдиай, 1 переместить_имм рсиай, msg переместить_имм рдикс, 13 вызов_системы ; exit(0) переместить_имм раикс, 60 переместить_имм рдиай, 0 вызов_системы .данные msg: .строка_нуль "Hello, World!" ``` ### 2. Скомпилируйте: ```bash python3 kvs_build.py hello.квс ``` ### 3. Запустите: ```bash ./hello.elf ``` **Вывод:** ``` Hello, World! ``` ## 📝 Синтаксис ### Структура программы ``` .текст ; секция кода (обязательна) ; ... инструкции ... .данные ; секция данных (опциональна) ; ... данные ... ``` ### Метки Метка — это имя, за которым следует двоеточие: ```asm _start: ; метка _start переместить_имм раикс, 1 переход _start ; переход на метку ``` ### Комментарии Однострочные комментарии начинаются с `;`: ```asm ; Это комментарий переместить_имм раикс, 42 ; комментарий после инструкции ``` ### Работа с памятью (абсолютная адресация) ```asm ; Запись значения в память по метке переместить_имм раикс, 42 сохранить [переменная], раикс ; Чтение значения из памяти загрузить рбикс, [переменная] ; Запись по абсолютному адресу сохранить [0x402000], раикс ``` ## 📖 Система команд ### Загрузка констант | Инструкция | Синтаксис | Описание | |------------|-----------|----------| | `переместить_имм` | `переместить_имм рег, значение` | Загрузить константу в регистр | ```asm переместить_имм раикс, 42 ; RAX = 42 переместить_имм еаикс, 0x7FFF ; EAX = 32767 переместить_имм ал, 0xFF ; AL = 255 ``` ### Работа с памятью | Инструкция | Синтаксис | Описание | |------------|-----------|----------| | `загрузить` | `загрузить рег, [метка/адрес]` | Загрузить значение из памяти | | `сохранить` | `сохранить [метка/адрес], рег` | Сохранить значение в память | ```asm загрузить раикс, [переменная] ; RAX = *переменная сохранить [результат], раикс ; *результат = RAX загрузить рбикс, [0x402000] ; загрузка по абсолютному адресу ``` ### Арифметика и логика | Инструкция | Синтаксис | Описание | |------------|-----------|----------| | `прибавить` | `прибавить рег1, рег2` | рег1 += рег2 | | `вычесть` | `вычесть рег1, рег2` | рег1 -= рег2 | | `увеличить` | `увеличить рег` | рег++ | | `уменьшить` | `уменьшить рег` | рег-- | | `сравнить` | `сравнить рег1, рег2` | Сравнить регистры | | `сравнить_с` | `сравнить_с рег, значение` | Сравнить с константой | | `проверить` | `проверить рег1, рег2` | TEST (логическое AND) | ```asm прибавить раикс, рбикс ; RAX += RBX увеличить рсикс ; RCX++ сравнить раикс, 10 ; сравнить RAX с 10 ``` ### Переходы | Инструкция | Условие | |------------|---------| | `переход` | Безусловный | | `короткий_переход` | Безусловный (смещение ±127) | | `переход_если_равно` | ZF = 1 | | `переход_если_неравно` | ZF = 0 | | `переход_если_меньше` | SF ≠ OF (signed <) | | `переход_если_больше` | ZF = 0 и SF = OF (signed >) | | `переход_если_меньше_или_равно` | ZF = 1 или SF ≠ OF | | `переход_если_больше_или_равно` | SF = OF | | `переход_если_перенос` | CF = 1 | | `переход_если_нет_переноса` | CF = 0 | **Короткие условные переходы** (префикс `короткий_`): - `короткий_переход_если_равно`, `короткий_переход_если_неравно`, и т.д. - Генерируют 2-байтовые инструкции (смещение ±127 байт) ### Системные вызовы | Инструкция | Описание | |------------|----------| | `вызов_системы` | Вызов ядра Linux (syscall) | ```asm ; Пример: завершение программы переместить_имм раикс, 60 ; syscall 60 = exit переместить_имм рдиай, 0 ; код возврата 0 вызов_системы ``` ## 💾 Регистры процессора КВС поддерживает все основные 64-битные регистры x86-64: | 64-бит | 32-бит | 16-бит | 8-бит (мл.) | 8-бит (ст.) | |--------|--------|--------|-------------|-------------| | `раикс` | `еаикс` | `аикс` | `ал` | `аш` | | `рбикс` | `ебикс` | `бикс` | `бл` | `бш` | | `рсикс` | `есикс` | `сикс` | `кл` | `чш` | | `рдикс` | `едикс` | `дикс` | `дл` | `дш` | | `рсипи` | `есипи` | `эсп` | `спл` | — | | `рбипи` | `ебипи` | `бипи` | `бпл` | — | | `рсиай` | `есиай` | `эс` | `сил` | — | | `рдиай` | `едиай` | `ди` | `дил` | — | | `р8`…`р15` | `р8д`…`р15д` | `р8в`…`р15в` | `р8б`…`р15б` | — | ## 🔧 Директивы ассемблера | Директива | Назначение | Пример | |-----------|------------|--------| | `.текст` | Начало секции кода | `.текст` | | `.данные` | Начало секции данных | `.данные` | | `.глобал` | Объявление глобальной метки | `.глобал _start` | | `.строка` | Строка без завершающего нуля | `.строка "Hello"` | | `.строка_нуль` | Строка с завершающим нулём | `.строка_нуль "Hello"` | | `.байт` | Последовательность байтов | `.байт 0x48, 0x65, 108` | | `.константа` | Определение константы | `.константа LEN = 10` | ## 📝 Примеры программ ### Работа с памятью (переменные) ```asm .текст .глобал _start _start: ; Запись значения в переменную переместить_имм раикс, 42 сохранить [переменная], раикс ; Чтение значения из переменной загрузить рбикс, [переменная] ; Завершение с кодом возврата переместить_имм раикс, 60 загрузить рдиай, [переменная] вызов_системы .данные переменная: .байт 0 ``` ### Цикл и условный переход ```asm .текст .глобал _start _start: переместить_имм рсикс, 10 ; счетчик = 10 loop: переместить_имм раикс, 1 переместить_имм рдиай, 1 переместить_имм рсиай, msg переместить_имм рдикс, 10 вызов_системы уменьшить рсикс ; счетчик-- сравнить_с рсикс, 0 переход_если_больше loop ; если > 0, продолжаем переместить_имм раикс, 60 переместить_имм рдиай, 0 вызов_системы .данные msg: .строка "Iteration\n" ``` ### Вычисление суммы чисел от 1 до 10 ```asm .текст .глобал _start _start: переместить_имм р8, 0 ; сумма переместить_имм р9, 10 ; счётчик loop: прибавить р8, р9 уменьшить р9 сравнить_с р9, 0 переход_если_больше loop ; exit(сумма в r8) переместить_имм раикс, 60 переместить рдикс, р8 вызов_системы ``` ## 🐛 Отладка и проверка ### Просмотр сгенерированного кода ```bash # Дизассемблирование objdump -d программа.elf # Просмотр секций objdump -h программа.elf # Просмотр заголовков программы readelf -l программа.elf # Извлечение строк из ELF strings программа.elf ``` ### CSV-лог После компиляции создаётся файл `программа.csv` со структурой: | адрес | байт | целевой_адрес | исходная_команда | |-------|------|---------------|------------------| | 0x401000 | 48 | | переместить_имм раикс, 1 | | 0x401001 | B8 | | | | 0x401002 | 01 | | | | ... | ... | ... | ... | ### Трассировка системных вызовов ```bash strace ./программа.elf ``` ### Отладка с GDB ```bash gdb ./программа.elf ``` ```gdb (gdb) break _start ; установить точку останова (gdb) run ; запустить (gdb) info registers ; показать регистры (gdb) x/10i $rip ; показать 10 инструкций (gdb) stepi ; выполнить одну инструкцию ``` ## ⚠️ Ограничения ### Поддерживается - ✅ 64-битные, 32-битные, 16-битные и 8-битные регистры - ✅ Непосредственная загрузка констант (imm) в регистры - ✅ Сравнение регистров и регистров с константами - ✅ Условные и безусловные переходы (длинные и короткие) - ✅ Арифметические операции (ADD, SUB, INC, DEC) - ✅ Логическая операция TEST - ✅ Системные вызовы Linux (syscall) - ✅ Секции `.текст` и `.данные` - ✅ Строковые литералы с escape-последовательностями (`\n`, `\t`, `\\`, `\"`) - ✅ Директива `.байт` для raw-данных - ✅ Директива `.константа` для имён констант - ✅ **Абсолютная адресация памяти** `[метка]` и `[число]` (RIP-relative) ### Не поддерживается (в разработке) - ❌ Косвенная адресация `[reg]` — доступ к памяти через регистр - ❌ Адресация со смещением `[reg + disp]` - ❌ Сложная адресация с индексом `[reg + reg*scale]` и полная SIB-адресация - ❌ Инструкции для работы со стеком (PUSH, POP, CALL, RET) — частично - ❌ Поддержка плавающей запятой (FPU/SSE) - ❌ Многомодульная компиляция - ❌ Директива `.bss` для неинициализированных данных - ❌ Макросы ## 📈 План развития ### Реализовано (v2.0) - [x] Лексер с токенами `[`, `]`, `NUMBER` - [x] Парсер с поддержкой операндов в квадратных скобках - [x] Первый проход с корректным расчётом размера инструкций с памятью - [x] Второй проход с кодированием абсолютной адресации через RIP-relative - [x] Поддержка меток в операндах памяти `[переменная]` - [x] Рефакторинг: выделение кодировщика в отдельный модуль ### В планах (v3.0) - [ ] Косвенная адресация `[reg]` - [ ] Адресация со смещением `[reg + disp]` - [ ] Сложная адресация с индексом `[reg + reg*scale]` - [ ] Полная SIB-адресация `[reg + reg*scale + disp]` - [ ] Директива `.bss` для неинициализированных данных - [ ] Поддержка инструкций PUSH/POP/CALL/RET для стековых операций - [ ] Стандартная библиотека (`libkvs.квс`): malloc, free, strlen, strcmp, print ## 📄 Лицензия Только для образовательных целей. Используйте на свой страх и риск. ``` КВС Ассемблер | Экспериментальный проект | 2025 Только для образовательных целей. Используйте на свой страх и риск. ```