15 KiB
КВС (kvs_9_8.py) — Ассемблер с русским синтаксисом для x86-64
📖 Оглавление
- 🎯 Назначение и концепция
- 🚀 Особенности и возможности
- ⚙️ Архитектура и процесс сборки
- 📁 Формат исходных файлов (.квс)
- 🔧 Система команд (инструкции)
- 💾 Регистры процессора
- 📋 Директивы ассемблера
- 📦 Система импорта модулей
- 🔄 Процесс трансляции и выходные файлы
- ⚠️ Ограничения и особенности реализации
🎯 Назначение и концепция
КВС — это ассемблер для архитектуры x86-64, полностью использующий русскую лексику для мнемоник инструкций, имён регистров и директив. Проект носит образовательный и экспериментальный характер и демонстрирует принципы работы ассемблера, построения ELF-файлов и трансляции высокоуровневых концепций в машинный код.
Ключевые философские принципы проекта:
- Самодокументируемый код: Читаемость и ясность важнее краткости.
- Изоляция логики: Разделение парсера, трансформатора и кодогенератора.
- Минимизация зависимостей: Используется только
structдля упаковки данных,reне используется. - Избегание чрезмерного ООП: В контексте возможной будущей самокомпиляции.
🚀 Особенности и возможности
- Полностью русский синтаксис: Все инструкции (
переместить,прибавить,вызвать), регистры (раикс,есипи,ал) и директивы (.текст,.данные) используют кириллицу. - Генерация исполняемых ELF-файлов: На выходе создаются 64-битные ELF-файлы для Linux, готовые к запуску.
- Двухпроходная сборка: Традиционная для ассемблеров схема с разрешением меток.
- Поддержка секций: Явное разделение на секции кода (
.текст) и данных (.данные). - Система импорта модулей: Директива
.импортдля включения других файлов.квсс автоматическим разрешением имён. - Подготовка к сложной адресации: Архитектура заложена для будущей трансформации сложных режимов адресации памяти в последовательности простых инструкций через промежуточное представление.
- Детальное логирование: Генерация
.log.csvфайла с полным соответствием машинных кодов, виртуальных адресов и исходных команд.
⚙️ Архитектура и процесс сборки
Процесс трансляции исходного кода .квс в исполняемый файл .elf проходит через несколько этапов:
Исходный файл (.квс)
│
▼ (Этап 1: Разбор и импорт)
Промежуточный файл (.квс.промежуточный)
│
▼ (Этап 2: Двухпроходное ассемблирование)
Данные секций + Таблица меток
│
▼ (Этап 3: Генерация ELF)
Исполняемый файл (.elf) + Лог (.log.csv)
Подробнее об этапах:
- Построение промежуточного представления: Исходный файл и все импортированные модули объединяются в один текст. Метки и константы переименовываются (получают суффикс имени модуля) для избежания коллизий.
- Первый проход ассемблирования: Анализируется промежуточный файл, вычисляются размеры всех инструкций и данных, строится таблица меток с их смещениями внутри секций.
- Второй проход ассемблирования: Генерируется машинный код. Адреса меток подставляются в инструкции переходов, загрузки адресов и т.д. Формируются бинарные содержимое секций
.textи.data. - Компоновка ELF: Собранные секции упаковываются в формат исполняемого файла ELF 64-bit с корректными заголовками, таблицами секций и сегментов.
📁 Формат исходных файлов (.квс)
Исходные файлы имеют расширение .квс. Их структура следует традициям ассемблера:
; Комментарий начинается с точки с запятой
.данные ; Начало секции данных
приветствие: .строка_нуль "Здравствуй, мир!"
число: .байт 0x2A
.текст ; Начало секции кода
.глобал _start ; Объявление точки входа
_start: ; Метка
переместить_имм раикс, 60 ; Системный вызов exit (60) в rax
переместить_имм рдикс, 42 ; Код возврата (42) в rdi
вызов_системы ; Вызов ядра (syscall)
🔧 Система команд (инструкции)
Ассемблер поддерживает обширный набор инструкций x86-64, сгруппированных по категориям:
| Категория | Примеры инструкций | Соответствие NASM |
|---|---|---|
| Перемещение данных | переместить, загрузить, сохранить, загрузить_адрес |
mov, lea |
| Арифметика | прибавить, вычесть, умножить, разделить, увеличить |
add, sub, mul, div, inc |
| Логические операции | и, или, инвертировать, проверить |
and, or, not, test |
| Управление потоком | переход, переход_если_равно, вызвать, вернуться |
jmp, je, call, ret |
| Работа со стеком | втолкнуть, вытолкнуть |
push, pop |
| Сдвиги и вращения | сдвиг_влево, вращать_вправо |
shl, ror |
| Строковые операции | переместить_байт, сравнить_байты |
movsb, cmpsb |
| Системные вызовы | вызов_системы, прервать |
syscall, int |
Особенности кодирования: Проект корректно генерирует префиксы REX, учитывает размеры операндов (8/16/32/64 бита) и поддерживает базовые режимы адресации памяти (например, [раикс]).
💾 Регистры процессора
Поддерживаются регистры x86-64 во всех их размерах:
| 64-битные | 32-битные | 16-битные | 8-битные (младшие) | 8-битные (старшие) |
|---|---|---|---|---|
раикс |
еаикс |
аикс |
ал |
аш |
рбикс |
ебикс |
бикс |
бл |
бш |
рсикс |
есикс |
сикс |
кл |
чш |
рдикс |
едикс |
дикс |
дл |
дш |
рсипи |
есипи |
эсп |
спл |
— |
рбипи |
ебипи |
бипи |
бпл |
— |
рсиай |
есиай |
эс |
сил |
— |
рдиай |
едиай |
ди |
дил |
— |
р8 ... р15 |
р8д ... р15д |
р8в ... р15в |
р8б ... р15б |
— |
📋 Директивы ассемблера
Директивы управляют процессом ассемблирования, не превращаясь в машинный код напрямую.
| Директива | Описание | Пример |
|---|---|---|
.текст |
Переключает ассемблер на запись в секцию кода. | .текст |
.данные |
Переключает ассемблер на запись в секцию данных. | .данные |
.глобал |
Объявляет метку глобальной (точку входа программы). | .глобал _start |
.строка / .строка_нуль |
Резервирует место в секции данных для строки (без нуля / с нулевым завершителем). | .строка_нуль "Текст" |
.байт |
Резервирует один или несколько байт с заданными значениями. | .байт 1, 0xFE, 255 |
.константа |
Определяет символьную константу, которую можно использовать как число. | .константа ВЫХОД = 60 |
.импорт |
Включает содержимое другого файла .квс в текущую сборку. |
.импорт библиотека.квс |
📦 Система импорта модулей
Директива .импорт позволяет разбивать проект на несколько файлов.
Принцип работы:
- Рекурсивный поиск: Ассемблер ищет указанный файл в той же директории, что и импортирующий файл.
- Переименование: Чтобы избежать конфликтов имён, все метки и константы импортированного модуля автоматически получают суффикс, основанный на имени файла (например, метка
циклизмодуль.квсстанетцикл_модуль). - Объединение: Содержимое всех секций
.данныеиз импортированных файлов сливается в общую секцию.данныепромежуточного файла. Аналогично для.текст.
Это упрощает создание библиотек и организацию больших проектов.
🔄 Процесс трансляции и выходные файлы
Запуск ассемблера:
python3 kvs_9_8.py программа.квс
В результате создаются три файла:
программа.квс.промежуточный: Текстовый файл, содержащий объединённый и переименованный код всех модулей. Используется для отладки процесса импорта.программа.elf: Исполняемый 64-битный ELF-файл. Для запуска может потребоваться установить флаг исполнения:chmod +x программа.elf.программа.log.csv: Детальный лог в формате CSV, где для каждого байта машинного кода указан его виртуальный адрес, шестнадцатеричное значение, целевой адрес (для инструкций переходов) и исходная команда на русском языке. Неоценим для обучения и отладки.
⚠️ Ограничения и особенности реализации
- Экспериментальный статус: Проект в активной разработке, некоторые углы архитектуры x86-64 могут быть реализованы не полностью.
- Базовая адресация памяти: На данный момент поддерживаются преимущественно простые формы адресации (например,
[регистр]). Режимы со сдвигом и несколькими регистрами ([база + индекс*масштаб + смещение]) предназначены для реализации через трансформацию в промежуточном представлении (задел на будущее). - Отсутствие макросов и условной компиляции: В текущей версии эти конструкции не поддерживаются.
- Лексический анализатор (лексер): Написан "вручную", без использования регулярных выражений (
re), в соответствии с философией проекта. - Генерация ELF: Реализация фокусируется на создании рабочих исполняемых файлов для Linux. Некоторые необязательные или специфичные поля заголовков ELF могут быть заполнены упрощённо.