ассемблер для архитектуры x86-64, полностью использующий русскую лексику
Find a file
2026-06-07 22:59:34 +03:00
доки пересборка 2026-05-02 23:04:46 +03:00
инструменты адресация в bss 2026-05-25 20:36:43 +03:00
тесты вывод аргумента 2026-06-07 22:59:34 +03:00
.gitignore обновить todo 2026-05-17 12:52:29 +03:00
AGENTS.md обновить ридми 2026-05-23 16:30:12 +03:00
kvs_build.py добавить сортировщик для таблицы 2026-06-07 16:26:54 +03:00
kvs_builder.py убрать харкод в 4м проходе 2026-05-23 21:14:49 +03:00
kvs_data.py рефакторинг общих данных 2026-05-23 20:30:15 +03:00
kvs_encoder.py однотабличная сборка_ 2026-05-23 08:58:10 +03:00
kvs_encoder_fixsize.py однотабличная сборка 2026-05-23 08:52:52 +03:00
kvs_encoder_mutsize.py однотабличная сборка 2026-05-23 08:52:52 +03:00
kvs_lexer.py кодировщик инструкций фиксированного размера 2026-05-17 12:21:28 +03:00
kvs_parser.py косвенная адресация 2026-05-17 15:18:35 +03:00
kvs_pass1.py починить бнд и учесть длину коментария 2026-06-07 15:55:19 +03:00
kvs_pass2.py упростить рассчет смещений 2026-05-23 18:56:43 +03:00
kvs_pass3.py однотабличная сборка 2026-05-23 08:52:52 +03:00
kvs_pass4.py маркеры секций 2026-05-25 18:19:13 +03:00
kvs_pass5.py починить бнд и учесть длину коментария 2026-06-07 15:55:19 +03:00
kvs_pass6.py добавить сортировщик для таблицы 2026-06-07 16:26:54 +03:00
README.md упростить рассчет смещений 2026-05-23 18:56:43 +03:00
todo.txt вывод аргумента 2026-06-07 22:59:34 +03:00
особенности вывод аргумента 2026-06-07 22:59:34 +03:00
черновик.txt вывод аргумента 2026-06-07 22:59:34 +03:00

# КВС — Ассемблер с русским синтаксисом для x86-64

**КВС** — это экспериментальный ассемблер для архитектуры x86-64, полностью использующий **русскую лексику** для мнемоник инструкций, имён регистров и директив. Проект носит образовательный характер и демонстрирует принципы работы ассемблера, построения ELF-файлов и трансляции высокоуровневых концепций в машинный код.

## 📋 Оглавление

- [Особенности](#-особенности)
- [Архитектура](#-архитектура)
- [Установка](#-установка)
- [Быстрый старт](#-быстрый-старт)
- [Синтаксис](#-синтаксис)
- [Система команд](#-система-команд)
- [Регистры](#-регистры-процессора)
- [Директивы](#-директивы-ассемблера)
- [Примеры программ](#-примеры-программ)
- [Отладка](#-отладка-и-проверка)
- [Ограничения](#-ограничения)
- [План развития](#-план-развития)
- [Лицензия](#-лицензия)

## ✨ Особенности

- **Полностью русский синтаксис** — все инструкции, регистры и директивы на кириллице
- **Генерация исполняемых ELF-файлов** — 64-битные ELF для Linux, готовые к запуску
- **Четырёхпроходная сборка** — традиционная схема с разрешением меток, подстановкой констант и перекодированием
- **Поддержка секций** — разделение на `.текст` (код), `.данные` (данные) и `.бнд` (неинициализированные данные)
- **Гибкая адресация памяти**:
  - абсолютная адресация по меткам `[переменная]`
  - абсолютная адресация по числовому адресу `[0x402000]`
  - косвенная адресация через регистр `[раикс]`
  - всё с RIP-relative кодированием для 64-битных перемещений
- **CSV-логирование** — детальный файл с соответствием адресов, байтов, меток и исходных команд
- **Более 50 инструкций** — полный набор основных команд x86-64
- **Минимализм зависимостей** — только стандартная библиотека Python

## 🏗 Архитектура

Процесс трансляции исходного кода `.квс` в исполняемый файл `.elf` проходит через **6 этапов** (4 прохода + сборка):

Исходный файл (.квс) │ ▼ (kvs_lexer.py) ← лексический анализ Файл токенов (.токены) │ ▼ (kvs_parser.py) ← синтаксический анализ AST-представление (.аст) │ ▼ (kvs_pass1.py) ← ПРОХОД 1: генерация CSV с заглушками (0xCC) CSV-файл (.csv) ← содержит все байты программы, метки, виртуальные адреса │ ▼ (kvs_pass2.py) ← ПРОХОД 2: разрешение меток │ ▼ (kvs_pass3.py) ← ПРОХОД 3: подстановка констант (.константа) │ ▼ (kvs_pass4.py) ← ПРОХОД 4: перекодирование инструкций │ ▼ (kvs_builder.py) ← сборка ELF из CSV ELF-файл (.elf) │ ▼ Исполняемый файл!


### Модули компилятора

| Файл | Назначение |
|------|-------------|
| `kvs_build.py` | Главный сборочный скрипт (запускает все этапы по порядку) |
| `kvs_lexer.py` | Лексический анализ, разбор на токены (поддерживает `[]`, `+`, `-`, `*`) |
| `kvs_parser.py` | Синтаксический анализ, построение AST (директивы, метки, инструкции) |
| `kvs_data.py` | Общие данные: регистры, таблица инструкций, вспомогательные функции |
| `kvs_encoder.py` | Фасад кодировщика (объединяет fixsize и mutsize) |
| `kvs_encoder_fixsize.py` | Кодировщик инструкций фиксированного размера |
| `kvs_encoder_mutsize.py` | Кодировщик инструкций переменного размера + диспетчер |
| `kvs_pass1.py` | Первый проход — генерация CSV с заглушками для неизвестных меток |
| `kvs_pass2.py` | Второй проход — разрешение меток (замена заглушек на реальные адреса) |
| `kvs_pass3.py` | Третий проход — подстановка констант из директив `.константа` |
| `kvs_pass4.py` | Четвёртый проход — перекодирование инструкций с подставленными значениями |
| `kvs_builder.py` | Сборка ELF: чтение CSV, заполнение байтов по адресам, установка прав на исполнение |

### Почему 4 прохода?

1. **Первый проход** — неизвестно, какие адреса будут у меток (метка может использоваться до определения). Вместо остановки ставим заглушки `0xCC` и продолжаем.
2. **Второй проход** — после того как все адреса меток известны, заменяем заглушки на реальные значения.
3. **Третий проход** — константы могут ссылаться друг на друга и на метки, поэтому их подстановка делается отдельно.
4. **Четвёртый проход** — после подстановки чисел (адресов/констант) нужно перегенерировать машинный код, так как разные операнды могут менять длину инструкции.

### Структура CSV-файла

| Колонка | Назначение |
|---------|-------------|
| `сегмент` | Имя секции (`.header`, `.text`, `.data`, `.bss`) |
| `адрес` | Файловое смещение байта |
| `виртуальный_адрес` | Виртуальный адрес байта в памяти (для вычисления смещений) |
| `байт` | Исходное значение байта (из pass1) |
| `приводящая_метка` | Имена меток, находящихся на этом адресе (через запятую) |
| `уводящий_адрес` | Строка `ЗАГЛУШКА имя` для неразрешённых меток |
| `исходная_команда` | Исходная инструкция (например, `переход метка`) |
| `команда_со_значениями` | Инструкция с подставленными адресами/константами (pass2/pass3) |
| `рассчитанный_уводящий_адрес` | Реальный адрес метки (файловое смещение) после разрешения |
| `рассчитанный_байт` | Итоговый байт после перекодирования (pass4) |

## 🔧 Установка

```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], раикс

; Косвенная адресация через регистр
переместить_имм рбикс, переменная
загрузить раикс, [рбикс]

; Работа с BND-секцией
.бнд
счётчик: .байт 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
.резб Резервирование байтов в BND .резб 100
.резс Резервирование слов в BND .резс 50
.рездс Резервирование двойных слов в BND .рездс 25
.резкс Резервирование квадрослов в BND .резкс 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
    вызов_системы

Использование BND-секции

.текст
.глобал _start

_start:
    ; инициализация счётчика в BND
    переместить_имм раикс,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 со структурой:

адрес виртуальный_адрес байт приводящая_метка исходная_команда
0x1000 0x401000 48 _start переместить_имм раикс, 10
0x1001 0x401001 B8
... ... ... ... ...

Трассировка системных вызовов

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-адресация
  • Поддержка плавающей запятой (FPU/SSE)
  • Многомодульная компиляция
  • Макросы

📈 План развития

Реализовано (v2.0)

  • Лексер с токенами [, ], NUMBER, +, -, *
  • Парсер с поддержкой операндов в квадратных скобках
  • Четырёхпроходная схема сборки
  • Первый проход с корректным расчётом размера инструкций с памятью
  • Второй проход с разрешением меток
  • Третий проход с подстановкой констант
  • Четвёртый проход с перекодированием инструкций
  • Поддержка меток в операндах памяти [переменная]
  • Поддержка числовых адресов [0x402000]
  • Поддержка косвенной адресации [регистр]
  • Секция .бнд для неинициализированных данных
  • Вынесение кодировщика в отдельный модуль
  • Колонка виртуальный_адрес в CSV для точного вычисления смещений

В планах (v3.0)

  • Адресация со смещением [reg + disp]
  • Сложная адресация с индексом [reg + reg*scale]
  • Полная SIB-адресация [reg + reg*scale + disp]
  • Стандартная библиотека (libkvs.квс): malloc, free, strlen, strcmp, print

📄 Лицензия

Только для образовательных целей. Используйте на свой страх и риск.


КВС Ассемблер | Экспериментальный проект | 2026 Только для образовательных целей. Используйте на свой страх и риск.