| доки | ||
| тесты | ||
| .gitignore | ||
| AGENTS.md | ||
| disassembler_skip_zero.py | ||
| elfreader.py | ||
| kvs_build.py | ||
| kvs_builder.py | ||
| kvs_data.py | ||
| kvs_lexer.py | ||
| kvs_parser.py | ||
| kvs_pass1.py | ||
| kvs_pass2.py | ||
| kvs_pass2_encoder.py | ||
| kvs_pass2_encoder_fixsize.py | ||
| kvs_pass2_encoder_mutsize.py | ||
| kvs_verify.py | ||
| README.html | ||
| README.md | ||
| todo.txt | ||
# КВС — Ассемблер с русским синтаксисом для x86-64
**КВС** — это экспериментальный ассемблер для архитектуры x86-64, полностью использующий **русскую лексику** для мнемоник инструкций, имён регистров и директив. Проект носит образовательный характер и демонстрирует принципы работы ассемблера, построения ELF-файлов и трансляции высокоуровневых концепций в машинный код.
## 📋 Оглавление
- [Особенности](#-особенности)
- [Архитектура](#-архитектура)
- [Установка](#-установка)
- [Быстрый старт](#-быстрый-старт)
- [Синтаксис](#-синтаксис)
- [Система команд](#-система-команд)
- [Регистры](#-регистры-процессора)
- [Директивы](#-директивы-ассемблера)
- [Примеры программ](#-примеры-программ)
- [Отладка](#-отладка-и-проверка)
- [Ограничения](#-ограничения)
- [План развития](#-план-развития)
- [Лицензия](#-лицензия)
## ✨ Особенности
- **Полностью русский синтаксис** — все инструкции, регистры и директивы на кириллице
- **Генерация исполняемых ELF-файлов** — 64-битные ELF для Linux, готовые к запуску
- **Двухпроходная сборка** — традиционная схема с разрешением меток
- **Поддержка секций** — разделение на `.текст` (код), `.данные` (данные) и `.бсс` (неинициализированные данные)
- **Гибкая адресация памяти**:
- абсолютная адресация по меткам `[переменная]`
- абсолютная адресация по числовому адресу `[0x402000]`
- косвенная адресация через регистр `[раикс]`
- всё с RIP-relative кодированием для 64-битных перемещений
- **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/artradeskz/kvs.git
cd kvs
# Установка прав на выполнение (при необходимости)
chmod +x kvs_build.py
# Проверка работы
python3 kvs_build.py --help
🚀 Быстрый старт
1. Создайте файл hello.квс:
.текст
.глобал _start
_start:
; write(1, msg, 13)
переместить_имм раикс,1
переместить_имм рдиай,1
переместить_имм рсиай, msg
переместить_имм рдикс,13
вызов_системы
; exit(0)
переместить_имм раикс,60
переместить_имм рдиай,0
вызов_системы
.данные
msg: .строка_нуль "Hello, World!"
2. Скомпилируйте:
python3 kvs_build.py hello.квс
3. Запустите:
./hello.elf
Вывод:
Hello, World!
📝 Синтаксис
Структура программы
.текст ; секция кода (обязательна)
; ... инструкции ...
.данные ; секция данных (опциональна)
; ... инициализированные данные ...
.бсс ; секция неинициализированных данных (опциональна)
; ... переменные без начального значения ...
Метки
Метка — это имя, за которым следует двоеточие:
_start: ; метка _start
переместить_имм раикс,1
переход _start ; переход на метку
Комментарии
Однострочные комментарии начинаются с ;:
; Это комментарий
переместить_имм раикс,42 ; комментарий после инструкции
Работа с памятью
; Запись значения в память по метке
переместить_имм раикс,42
сохранить [переменная], раикс
; Чтение значения из памяти
загрузить рбикс,[переменная]
; Запись по абсолютному адресу
сохранить [0x402000], раикс
; Косвенная адресация через регистр
переместить_имм рбикс, переменная
загрузить раикс, [рбикс]
; Работа с BSS-секцией
.бсс
счётчик: .байт 0
📖 Система команд
Загрузка констант
| Инструкция | Синтаксис | Описание |
|---|---|---|
переместить_имм |
переместить_имм рег, значение |
Загрузить константу в регистр |
переместить_имм раикс,42 ; RAX = 42
переместить_имм еаикс,0x7FFF ; EAX = 32767
переместить_имм ал,0xFF ; AL = 255
Работа с памятью
| Инструкция | Синтаксис | Описание |
|---|---|---|
загрузить |
загрузить рег, [метка/адрес/регистр] |
Загрузить значение из памяти |
сохранить |
сохранить [метка/адрес/регистр], рег |
Сохранить значение в память |
загрузить раикс,[переменная] ; RAX = *переменная
сохранить [результат], раикс ; *результат = RAX
загрузить рбикс,[0x402000] ; загрузка по абсолютному адресу
загрузить раикс,[рбикс] ; косвенная загрузка через регистр
Арифметика и логика
| Инструкция | Синтаксис | Описание |
|---|---|---|
прибавить |
прибавить рег1, рег2 |
рег1 += рег2 |
вычесть |
вычесть рег1, рег2 |
рег1 -= рег2 |
увеличить |
увеличить рег |
рег++ |
уменьшить |
уменьшить рег |
рег-- |
сравнить |
сравнить рег1, рег2 |
Сравнить регистры |
сравнить_с |
сравнить_с рег, значение |
Сравнить с константой |
проверить |
проверить рег1, рег2 |
TEST (логическое AND) |
прибавить раикс, рбикс ; 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) |
; Пример: завершение программы
переместить_имм раикс,60 ; syscall 60 = exit
переместить_имм рдиай,0 ; код возврата 0
вызов_системы
💾 Регистры процессора
КВС поддерживает все основные 64-битные регистры x86-64:
| 64-бит | 32-бит | 16-бит | 8-бит (мл.) |
|---|---|---|---|
раикс |
еаикс |
аикс |
ал |
рбикс |
ебикс |
бикс |
бл |
рсикс |
есикс |
сикс |
кл |
рдикс |
едикс |
дикс |
дл |
рсипи |
есипи |
эсп |
спл |
рбипи |
ебипи |
бипи |
бпл |
рсиай |
есиай |
эс |
сил |
рдиай |
едиай |
ди |
дил |
🔧 Директивы ассемблера
| Директива | Назначение | Пример |
|---|---|---|
.текст |
Начало секции кода | .текст |
.данные |
Начало секции инициализированных данных | .данные |
.бсс |
Начало секции неинициализированных данных | .бсс |
.глобал |
Объявление глобальной метки | .глобал _start |
.строка |
Строка без завершающего нуля | .строка "Hello" |
.строка_нуль |
Строка с завершающим нулём | .строка_нуль "Hello" |
.байт |
Последовательность байтов | .байт 0x48, 0x65, 108 |
.константа |
Определение константы | .константа LEN = 10 |
📝 Примеры программ
Работа с памятью (переменные)
.текст
.глобал _start
_start:
; Запись значения в переменную
переместить_имм раикс,42
сохранить [переменная], раикс
; Чтение значения из переменной
загрузить рбикс,[переменная]
; Завершение с кодом возврата
переместить_имм раикс,60
загрузить рдиай,[переменная]
вызов_системы
.данные
переменная: .байт 0
Цикл и условный переход
.текст
.глобал _start
_start:
переместить_имм рсикс,10 ; счетчик = 10
loop:
переместить_имм раикс,1
переместить_имм рдиай,1
переместить_имм рсиай, msg
переместить_имм рдикс,10
вызов_системы
уменьшить рсикс ; счетчик--
сравнить_с рсикс,0
переход_если_больше loop ; если > 0, продолжаем
переместить_имм раикс,60
переместить_имм рдиай,0
вызов_системы
.данные
msg: .строка "Iteration\n"
Вычисление суммы чисел от 1 до 10
.текст
.глобал _start
_start:
переместить_имм р8,0 ; сумма
переместить_имм р9,10 ; счётчик
loop:
прибавить р8, р9
уменьшить р9
сравнить_с р9,0
переход_если_больше loop
; exit(сумма в r8)
переместить_имм раикс,60
переместить рдикс, р8
вызов_системы
Использование BSS-секции
.текст
.глобал _start
_start:
; инициализация счётчика в BSS
переместить_имм раикс,0
сохранить [счётчик], раикс
; цикл: увеличить счётчик 10 раз
переместить_имм рсикс,10
loop:
загрузить раикс,[счётчик]
увеличить раикс
сохранить [счётчик], раикс
уменьшить рсикс
сравнить_с рсикс,0
переход_если_больше loop
; выход с кодом = значение счётчика
загрузить рдиай,[счётчик]
переместить_имм раикс,60
вызов_системы
.бсс
счётчик: .байт 0
Косвенная адресация
.текст
.глобал _start
_start:
; загружаем адрес переменной в регистр
переместить_имм рбикс, переменная
; косвенная запись
переместить_имм раикс,99
сохранить [рбикс], раикс
; косвенное чтение
загрузить раикс,[рбикс]
; выход
переместить_имм рдиай, раикс
переместить_имм раикс,60
вызов_системы
.данные
переменная: .байт 0
🐛 Отладка и проверка
Просмотр сгенерированного кода
# Дизассемблирование
objdump -d программа.elf
# Просмотр секций
objdump -h программа.elf
# Просмотр заголовков программы
readelf -l программа.elf
# Извлечение строк из ELF
strings программа.elf
CSV-лог
После компиляции создаётся файл программа.csv со структурой:
| адрес | байт | целевой_адрес | исходная_команда |
|---|---|---|---|
| 0x401000 | 48 | переместить_имм раикс, 1 | |
| 0x401001 | B8 | ||
| 0x401002 | 01 | ||
| ... | ... | ... | ... |
Трассировка системных вызовов
strace ./программа.elf
Отладка с GDB
gdb ./программа.elf
(gdb) break _start ; установить точку останова
(gdb) run ; запустить
(gdb) info registers ; показать регистры
(gdb) x/10i $rip ; показать 10 инструкций
(gdb) stepi ; выполнить одну инструкцию
⚠️ Ограничения
Поддерживается
- ✅ 64-битные, 32-битные, 16-битные и 8-битные регистры (AL, BL, CL, DL)
- ✅ Непосредственная загрузка констант (imm) в регистры
- ✅ Сравнение регистров и регистров с константами
- ✅ Условные и безусловные переходы (длинные и короткие)
- ✅ Арифметические операции (ADD, SUB, INC, DEC)
- ✅ Логическая операция TEST
- ✅ Системные вызовы Linux (syscall)
- ✅ Секции
.текст,.данныеи.бсс - ✅ Строковые литералы с escape-последовательностями (
\n,\t,\\,\") - ✅ Директива
.байтдля raw-данных - ✅ Директива
.константадля имён констант - ✅ Абсолютная адресация по меткам и числовым адресам
[метка]/[0x402000] - ✅ Косвенная адресация через регистр
[раикс] - ✅ RIP-relative кодирование для всех видов адресации
Не поддерживается (в разработке)
- ❌ Адресация со смещением
[reg + disp] - ❌ Сложная адресация с индексом
[reg + reg*scale]и полная SIB-адресация - ❌ Инструкции для работы со стеком (PUSH, POP, CALL, RET)
- ❌ Старшие 8-битные регистры (AH, BH, CH, DH) и расширенные младшие (SPL, BPL, SIL, DIL)
- ❌ Регистры R8–R15 и их байтовые/словные версии
- ❌ Поддержка плавающей запятой (FPU/SSE)
- ❌ Многомодульная компиляция
- ❌ Макросы
📈 План развития
Реализовано (v2.0)
- Лексер с токенами
[,],NUMBER - Парсер с поддержкой операндов в квадратных скобках
- Первый проход с корректным расчётом размера инструкций с памятью
- Второй проход с кодированием абсолютной адресации через RIP-relative
- Поддержка меток в операндах памяти
[переменная] - Поддержка числовых адресов
[0x402000] - Поддержка косвенной адресации
[регистр] - Секция
.бссдля неинициализированных данных - Рефакторинг: выделение кодировщика в отдельный модуль
В планах (v3.0)
- Адресация со смещением
[reg + disp] - Сложная адресация с индексом
[reg + reg*scale] - Полная SIB-адресация
[reg + reg*scale + disp] - Поддержка инструкций PUSH/POP/CALL/RET для стековых операций
- Стандартная библиотека (
libkvs.квс): malloc, free, strlen, strcmp, print
📄 Лицензия
Только для образовательных целей. Используйте на свой страх и риск.
КВС Ассемблер | Экспериментальный проект | 2026 Только для образовательных целей. Используйте на свой страх и риск.