ридми .bss

This commit is contained in:
mzhoot 2026-05-17 17:18:35 +03:00
parent e54fb6a479
commit 353ecb363d
3 changed files with 325 additions and 220 deletions

View file

@ -363,8 +363,8 @@
╚══════════════════════════════════╝
</pre>
</div>
<p>Версия 2.0 | Экспериментальный проект | 2025</p>
<p><span style="color: #00ff00;">✓ Абсолютная адресация реализована</span> | <span style="color: #ffff00;">⟳ Косвенная адресация в разработке</span></p>
<p>Версия 2.0 | Экспериментальный проект | 2026</p>
<p><span style="color: #00ff00;">✓ Абсолютная адресация реализована</span> | <span style="color: #00ff00;">✓ Косвенная адресация реализована</span> | <span style="color: #00ff00;">✓ Секция .bss реализована</span></p>
</div>
<h2>┌──[ ОГЛАВЛЕНИЕ ]────────────────────────────────────────────┐</h2>
@ -401,11 +401,18 @@
<h2 id="особенности">ОСОБЕННОСТИ И ВОЗМОЖНОСТИ</h2>
<ul>
<li><strong>Полностью русский синтаксис</strong><code>переместить</code>, <code>прибавить</code>, <code>вызвать</code>, регистры <code>раикс</code>, <code>есипи</code>, <code>ал</code>, директивы <code>.текст</code>, <code>.данные</code></li>
<li><strong>Полностью русский синтаксис</strong><code>переместить</code>, <code>прибавить</code>, <code>вызвать</code>, регистры <code>раикс</code>, <code>есипи</code>, <code>ал</code>, директивы <code>.текст</code>, <code>.данные</code>, <code>.бсс</code></li>
<li><strong>Генерация исполняемых ELF-файлов</strong> — 64-битные ELF для Linux, готовые к запуску</li>
<li><strong>Двухпроходная сборка</strong> — традиционная схема с разрешением меток</li>
<li><strong>Поддержка секций</strong> — разделение на <code>.текст</code> (код) и <code>.данные</code> (данные)</li>
<li><strong>Абсолютная адресация памяти</strong> — чтение и запись по меткам <code>[переменная]</code> и абсолютным адресам <code>[0x402000]</code> с RIP-relative кодированием</li>
<li><strong>Поддержка секций</strong> — разделение на <code>.текст</code> (код), <code>.данные</code> (инициализированные данные) и <code>.бсс</code> (неинициализированные данные)</li>
<li><strong>Полная адресация памяти</strong>:
<ul>
<li>Абсолютная адресация по меткам <code>[переменная]</code></li>
<li>Абсолютная адресация по числовому адресу <code>[0x402000]</code></li>
<li>Косвенная адресация через регистр <code>[раикс]</code></li>
<li>Всё с RIP-relative кодированием для 64-битных перемещений</li>
</ul>
</li>
<li><strong>CSV-логирование</strong> — детальный файл <code>.csv</code> с соответствием адресов, байтов и исходных команд</li>
<li><strong>Более 50 инструкций</strong> — полный набор основных команд x86-64</li>
<li><strong>Рефакторинг</strong> — кодогенерация вынесена в отдельный модуль <code>kvs_pass2_encoder.py</code></li>
@ -448,7 +455,7 @@ ELF-компоновщик (.elf)
<h2 id="установка">УСТАНОВКА И ЗАПУСК</h2>
<pre># Клонирование репозитория
git clone https://github.com/username/kvs.git
git clone https://github.com/artradeskz/kvs.git
cd kvs
# Установка прав на выполнение (при необходимости)
@ -463,29 +470,36 @@ python3 kvs_build.py программа.квс
<h2 id="синтаксис">СИНТАКСИС ИСХОДНЫХ ФАЙЛОВ (.квс)</h2>
<pre>; Комментарий начинается с точки с запятой
.данные ; Начало секции данных
переменная: .байт 0 ; Переменная в памяти
.бсс ; Начало секции неинициализированных данных
счётчик: .байт 0 ; Переменная без начального значения
.данные ; Начало секции инициализированных данных
message: .строкауль "Привет, мир!"
.текст ; Начало секции кода
.глобал _start ; Точка входа
_start:
; Работа с памятью
; Абсолютная адресация через метку
переместить_имм раикс, 42
сохранить [переменная], раикс ; запись в память
сохранить [счётчик], раикс ; запись в BSS-переменную
загрузить рбикс, [переменная] ; чтение из памяти
; Абсолютная адресация через число
сохранить [0x402000], раикс ; запись по абсолютному адресу
; Косвенная адресация через регистр
переместить_имм рбикс, message
загрузить раикс, [рбикс] ; чтение через регистр
; Системный вызов write
переместить_имм раикс, 1
загрузить_адрес рсиай, message
переместить_имм рсиай, message
переместить_имм рдикс, 13
вызов_системы
; Выход с кодом из переменной
; Выход с кодом из счётчика
загрузить рдиай, [счётчик]
переместить_имм раикс, 60
загрузить рдиай, [переменная]
вызов_системы</pre>
<h2 id="команды">СИСТЕМА КОМАНД</h2>
@ -493,68 +507,81 @@ _start:
<tr><th>Категория</th><th>Примеры инструкций</th><th>Соответствие NASM</th></tr>
<tr><td>Перемещение данных</td><td><code>переместить</code>, <code>переместить_имм</code></td><td><code>mov</code>, <code>mov reg, imm</code></td></tr>
<tr><td>Работа с памятью</td><td><code>загрузить</code>, <code>сохранить</code>, <code>загрузить_адрес</code></td><td><code>mov reg, mem</code>, <code>mov mem, reg</code>, <code>lea</code></td></tr>
<tr><td>Арифметика</td><td><code>прибавить</code>, <code>вычесть</code>, <code>умножить</code>, <code>разделить</code>, <code>увеличить</code>, <code>уменьшить</code></td><td><code>add</code>, <code>sub</code>, <code>mul</code>, <code>div</code>, <code>inc</code>, <code>dec</code></td></tr>
<tr><td>Логические</td><td><code>и</code>, <code>или</code>, <code>исключающее_или</code>, <code>инвертировать</code>, <code>отрицать</code></td><td><code>and</code>, <code>or</code>, <code>xor</code>, <code>not</code>, <code>neg</code></td></tr>
<tr><td>Сравнение</td><td><code>сравнить</code>, <code>сравнить_с</code>, <code>проверить</code></td><td><code>cmp</code>, <code>test</code></td></tr>
<tr><td>Условные переходы</td><td><code>переход_если_равно</code>, <code>переход_если_больше</code>, <code>короткий_переход_если_равно</code></td><td><code>je</code>, <code>jg</code>, <code>je short</code></td><tr>
<tr><td>Безусловные переходы</td><td><code>переход</code>, <code>короткий_переход</code>, <code>вызвать</code>, <code>вернуться</code></td><td><code>jmp</code>, <code>jmp short</code>, <code>call</code>, <code>ret</code></td></tr>
<tr><td>Системные</td><td><code>вызов_системы</code>, <code>остановить</code></td><td><code>syscall</code>, <code>hlt</code></td></tr>
<tr><td>Арифметика</td><td><code>прибавить</code>, <code>вычесть</code>, <code>увеличить</code>, <code>уменьшить</code></td><td><code>add</code>, <code>sub</code>, <code>inc</code>, <code>dec</code></td></tr>
<tr><td>Логические</td><td><code>сравнить</code>, <code>сравнить_с</code>, <code>проверить</code></td><td><code>cmp</code>, <code>test</code></td></tr>
<tr><td>Условные переходы</td><td><code>переход_если_равно</code>, <code>переход_если_больше</code>, <code>короткий_переход</code></td><td><code>je</code>, <code>jg</code>, <code>jmp short</code></td></tr>
<tr><td>Безусловные переходы</td><td><code>переход</code>, <code>короткий_переход</code></td><td><code>jmp</code>, <code>jmp short</code></td></tr>
<tr><td>Системные</td><td><code>вызов_системы</code></td><td><code>syscall</code></td></tr>
</table>
<h2 id="память">РАБОТА С ПАМЯТЬЮ</h2>
<div class="success">
<strong>✓ РЕАЛИЗОВАНО (v2.0):</strong> Абсолютная адресация через метки и числа
<strong>✓ РЕАЛИЗОВАНО (v2.0):</strong> Абсолютная адресация (метки и числа), косвенная адресация через регистры
</div>
<h3>Поддерживаемые формы:</h3>
<table>
<tr><th>Синтаксис</th><th>Описание</th><th>Пример</th></tr>
<tr><td><code>[метка]</code></td><td>Адрес метки (из .данные)</td><td><code>загрузить раикс, [переменная]</code></td></tr>
<tr><td><code>[метка]</code></td><td>Адрес метки (из .данные или .бсс)</td><td><code>загрузить раикс, [переменная]</code></td></tr>
<tr><td><code>[число]</code></td><td>Абсолютный адрес</td><td><code>сохранить [0x402000], раикс</code></td></tr>
<tr><td><code>[регистр]</code></td><td>Косвенная адресация через регистр</td><td><code>загрузить раикс, [рбикс]</code></td></tr>
</table>
<h3>Пример использования:</h3>
<pre>.данные
переменная: .байт 0
результат: .байт 0
<pre>.бсс
счётчик: .байт 0
указатель: .байт 0
.данные
переменная: .байт 42
message: .строкауль "Hello"
.текст
_start:
; Запись значения
переместить_имм раикс, 42
сохранить [переменная], раикс
; Абсолютная адресация через метку
загрузить раикс, [переменная]
; Чтение значения
загрузить рбикс, [переменная]
; Абсолютная адресация через число
сохранить [0x402000], раикс
; Завершение с кодом 42
; Косвенная адресация
переместить_имм рбикс, переменная
загрузить раикс, [рбикс]
; Работа с BSS
сохранить [счётчик], раикс
; Завершение
переместить_имм раикс, 60
загрузить рдиай, [переменная]
загрузить рдиай, [счётчик]
вызов_системы</pre>
<div class="warning">
<strong>⚠️ ВАЖНО:</strong> Порядок объявления в секции <code>.данные</code> имеет значение! Переменные, объявленные перед строковыми константами, могут затереть первые байты строк. Рекомендуется объявлять строки первыми, а изменяемые переменные — после.
<div class="note">
<strong>📌 ВАЖНО:</strong> Все тесты из папки <code>тесты/</code> успешно собираются и запускаются, включая тест, воспроизводящий баг с BSS-секцией. Адресация работает корректно во всех формах.
</div>
<h2 id="регистры">РЕГИСТРЫ ПРОЦЕССОРА</h2>
<table>
<tr><th>64-битные</th><th>32-битные</th><th>16-битные</th><th>8-битные (мл.)</th><th>8-битные (ст.)</th></tr>
<tr><td><code>раикс</code></td><td><code>еаикс</code></td><td><code>аикс</code></td><td><code>ал</code></td><td><code>аш</code></td></tr>
<tr><td><code>рбикс</code></td><td><code>ебикс</code></td><td><code>бикс</code></td><td><code>бл</code></td><td><code>бш</code></td></tr>
<tr><td><code>рсикс</code></td><td><code>есикс</code></td><td><code>сикс</code></td><td><code>кл</code></td><td><code>чш</code></td></tr>
<tr><td><code>рдикс</code></td><td><code>едикс</code></td><td><code>дикс</code></td><td><code>дл</code></td><td><code>дш</code></td></tr>
<tr><td><code>рсипи</code></td><td><code>есипи</code></td><td><code>эсп</code></td><td><code>спл</code></td><td></td></tr>
<tr><td><code>рбипи</code></td><td><code>ебипи</code></td><td><code>бипи</code></td><td><code>бпл</code></td><td></td></tr>
<tr><td><code>рсиай</code></td><td><code>есиай</code></td><td><code>эс</code></td><td><code>сил</code></td><td></td></tr>
<tr><td><code>рдиай</code></td><td><code>едиай</code></td><td><code>ди</code></td><td><code>дил</code></td><td></td></tr>
<tr><td><code>р8</code><code>р15</code></td><td><code>р</code><code>р15д</code></td><td><code>р</code><code>р15в</code></td><td><code>р8б</code><code>р15б</code></td><td></td></tr>
<tr><th>64-битные</th><th>32-битные</th><th>16-битные</th><th>8-битные (мл.)</th></tr>
<tr><td><code>раикс</code></td><td><code>еаикс</code></td><td><code>аикс</code></td><td><code>ал</code></td></tr>
<tr><td><code>рбикс</code></td><td><code>ебикс</code></td><td><code>бикс</code></td><td><code>бл</code></td></tr>
<tr><td><code>рсикс</code></td><td><code>есикс</code></td><td><code>сикс</code></td><td><code>кл</code></td></tr>
<tr><td><code>рдикс</code></td><td><code>едикс</code></td><td><code>дикс</code></td><td><code>дл</code></td></tr>
<tr><td><code>рсипи</code></td><td><code>есипи</code></td><td><code>эсп</code></td><td><code>спл</code></td></tr>
<tr><td><code>рбипи</code></td><td><code>ебипи</code></td><td><code>бипи</code></td><td><code>бпл</code></td></tr>
<tr><td><code>рсиай</code></td><td><code>есиай</code></td><td><code>эс</code></td><td><code>сил</code></td></tr>
<tr><td><code>рдиай</code></td><td><code>едиай</code></td><td><code>ди</code></td><td><code>дил</code></td></tr>
</table>
<div class="warning">
<strong>⚠️ ПРИМЕЧАНИЕ:</strong> Старшие 8-битные регистры (AH, BH, CH, DH) и расширенные младшие (SPL, BPL, SIL, DIL) не поддерживаются. Регистры R8R15 также отсутствуют.
</div>
<h2 id="директивы">ДИРЕКТИВЫ АССЕМБЛЕРА</h2>
<table>
<tr><th>Директива</th><th>Назначение</th><th>Пример</th></tr>
<tr><td><code>.текст</code></td><td>Начало секции кода</td><td><code>.текст</code></td></tr>
<tr><td><code>.данные</code></td><td>Начало секции данных</td><td><code>.данные</code></td></tr>
<tr><td><code>.данные</code></td><td>Начало секции инициализированных данных</td><td><code>.данные</code></td></tr>
<tr><td><code>.бсс</code></td><td>Начало секции неинициализированных данных</td><td><code>.бсс</code></td></tr>
<tr><td><code>.глобал</code></td><td>Объявление глобальной метки</td><td><code>.глобал _start</code></td></tr>
<tr><td><code>.строка</code></td><td>Строка без нулевого терминатора</td><td><code>.строка "Hello"</code></td></tr>
<tr><td><code>.строкауль</code></td><td>Строка с нулевым терминатором</td><td><code>.строкауль "Hello"</code></td></tr>
@ -584,40 +611,71 @@ _start:
.данные
msg: .строкауль "Hello, World!"</pre>
<h3>Пример 2: Работа с переменными в памяти</h3>
<h3>Пример 2: Работа с BSS-секцией</h3>
<pre>.глобал _start
.текст
_start:
; Запись 42 в переменную
переместить_имм раикс, 42
сохранить [переменная], раикс
; Инициализация счётчика
переместить_имм раикс, 0
сохранить [счётчик], раикс
; Завершение с кодом 42
; Цикл: увеличить счётчик 10 раз
переместить_имм рсикс, 10
loop:
загрузить раикс, [счётчик]
увеличить раикс
сохранить [счётчик], раикс
уменьшить рсикс
сравнить_с рсикс, 0
переход_если_больше loop
; Выход с кодом = значение счётчика
загрузить рдиай, [счётчик]
переместить_имм раикс, 60
вызов_системы
.бсс
счётчик: .байт 0</pre>
<h3>Пример 3: Косвенная адресация</h3>
<pre>.глобал _start
.текст
_start:
; Загружаем адрес переменной в регистр
переместить_имм рбикс, переменная
; Косвенная запись
переместить_имм раикс, 99
сохранить [рбикс], раикс
; Косвенное чтение
загрузить раикс, [рбикс]
; Выход
переместить_имм рдиай, раикс
переместить_имм раикс, 60
загрузить рдиай, [переменная]
вызов_системы
.данные
переменная: .байт 0</pre>
<h3>Пример 3: Цикл для вычисления суммы</h3>
<h3>Пример 4: Абсолютный адрес</h3>
<pre>.глобал _start
.текст
_start:
переместить_имм р8, 0 ; сумма
переместить_имм р9, 10 ; счётчик
loop:
прибавить р8, р9
уменьшить р9
сравнить_с р9, 0
переход_если_больше loop
; exit(сумма в r8)
; Запись по абсолютному адресу 0x402000
переместить_имм раикс, 0x2A
сохранить [0x402000], раикс
; Чтение по абсолютному адресу
загрузить рбикс, [0x402000]
; Выход с кодом 42
переместить_имм раикс, 60
переместить рдикс, р8
переместить_имм рдиай, 0x2A
вызов_системы</pre>
<h2 id="трансляция">ПРОЦЕСС ТРАНСЛЯЦИИ И ВЫХОДНЫЕ ФАЙЛЫ</h2>
@ -640,50 +698,44 @@ loop:
<li>Лексер с токенами <code>[</code>, <code>]</code>, <code>NUMBER</code></li>
<li>Парсер с поддержкой операндов в квадратных скобках</li>
<li>Первый проход с корректным расчётом размера инструкций с памятью</li>
<li>Второй проход с кодированием абсолютной адресации через RIP-relative</li>
<li>Поддержка меток в операндах памяти <code>[переменная]</code></li>
<li>Рефакторинг: выделение кодировщика в отдельный модуль <code>kvs_pass2_encoder.py</code></li>
<li>Второй проход с кодированием адресации через RIP-relative</li>
<li>Абсолютная адресация по меткам <code>[переменная]</code></li>
<li>Абсолютная адресация по числовым адресам <code>[0x402000]</code></li>
<li>Косвенная адресация через регистры <code>[раикс]</code></li>
<li>Секция <code>.бсс</code> для неинициализированных данных</li>
<li>Рефакторинг: выделение кодировщика в отдельный модуль</li>
<li>Более 50 инструкций x86-64</li>
<li>CSV-логирование</li>
</ul>
<h3>⚠️ Частично реализовано</h3>
<h3>⚠️ Частично реализовано / ограничено</h3>
<ul>
<li><code>загрузить_адрес</code> (LEA) — только для чисел, не для меток</li>
<li>Сложные выражения в операндах памяти парсятся, но не кодируются</li>
</ul>
<h3>В разработке (v3.0)</h3>
<ul>
<li>Косвенная адресация <code>[reg]</code></li>
<li>Адресация со смещением <code>[reg + disp]</code></li>
<li>Сложная адресация с индексом <code>[reg + reg*scale]</code></li>
<li>Полная SIB-адресация <code>[reg + reg*scale + disp]</code></li>
<li>Директива <code>.bss</code> для неинициализированных данных</li>
<li>LEA для меток (<code>загрузить_адрес reg, [метка]</code>)</li>
<li>Стандартная библиотека</li>
<li>Старшие 8-битные регистры (AH, BH, CH, DH) не поддерживаются</li>
<li>Регистры R8R15 не поддерживаются</li>
</ul>
<h2 id="план">ПЛАН РАЗВИТИЯ</h2>
<h3>v2.0 (текущая) — Абсолютная адресация</h3>
<h3>v2.0 (текущая) — Адресация и BSS</h3>
<ul>
<li>✅ Лексер: <code>[</code>, <code>]</code>, <code>NUMBER</code></li>
<li>✅ Парсер: <code>[метка]</code> и <code>[число]</code></li>
<li>✅ Pass1: размер = 7 байт</li>
<li>✅ Парсер: <code>[метка]</code>, <code>[число]</code>, <code>[регистр]</code></li>
<li>✅ Pass1: корректный расчёт размера инструкций</li>
<li>✅ Pass2: RIP-relative кодирование</li>
<li>✅ Поддержка меток в памяти</li>
<li>✅ Абсолютная адресация (метки и числа)</li>
<li>✅ Косвенная адресация (<code>[reg]</code>)</li>
<li>✅ Секция <code>.бсс</code></li>
<li>✅ Рефакторинг энкодера</li>
</ul>
<h3>v3.0 (планируется) — Косвенная и относительная адресация</h3>
<h3>v3.0 (планируется) — Расширенная адресация</h3>
<ul>
<li><code>[reg]</code> — косвенная адресация через регистр</li>
<li><code>[reg + disp]</code>со смещением (disp8/disp32)</li>
<li><code>[reg + disp]</code> — адресация со смещением</li>
<li><code>[reg + reg*scale]</code>с индексным регистром</li>
<li><code>[reg + reg*scale + disp]</code> — полная SIB-адресация</li>
<li><code>.bss</code> — секция неинициализированных данных</li>
<li>❌ LEA для меток</li>
<li>❌ PUSH/POP/CALL/RET</li>
</ul>
<h3>v4.0 (отложено) — Стандартная библиотека</h3>
@ -691,40 +743,18 @@ loop:
<li><code>malloc</code>, <code>free</code></li>
<li><code>strlen</code>, <code>strcmp</code>, <code>memcpy</code></li>
<li><code>putchar</code>, <code>getchar</code></li>
<li><code>printf</code> (упрощённый вариант)</li>
</ul>
<div class="process-diagram">
Зависимости между подзадачами:
Лексер (шаг 1) ✅
Парсер (шаг 2) ✅
Данные инструкций (шаг 3) ⚠️
Pass1 (шаг 4) ✅
Pass2 (шаг 5): ⚠️ ЧАСТИЧНО
5.1 → 5.2 → 5.3 → 5.4 → 5.5
5.6 (генераторы инструкций)
5.7 (диспетчер) ✅
Тестирование (шаг 6) ⚠️ ЧАСТИЧНО
Библиотека (шаг 7) ❌ ОТЛОЖЕНО
</div>
<h2 id="ограничения">ОГРАНИЧЕНИЯ</h2>
<div class="warning">
<ul>
<li><strong>Косвенная адресация памяти</strong> — поддерживается только абсолютная форма <code>[метка]</code>; адресация через регистры <code>[reg]</code> в разработке</li>
<li><strong>Сложная адресация</strong> — формы <code>[reg+disp]</code>, <code>[reg+reg*scale]</code>, <code>[reg+reg*scale+disp]</code> не реализованы</li>
<li><strong>Адресация со смещением</strong> — формы <code>[reg+disp]</code>, <code>[reg+reg*scale]</code>, <code>[reg+reg*scale+disp]</code> не реализованы</li>
<li><strong>LEA для меток</strong><code>загрузить_адрес reg, [метка]</code> не работает, используйте <code>переместить_имм reg, метка</code></li>
<li><strong>Отсутствие .bss</strong> — все переменные инициализируются и попадают в <code>.data</code> (занимают место в файле)</li>
<li><strong>Нет динамической памяти</strong> — нет встроенных malloc/free (можно реализовать через syscall brk)</li>
<li><strong>Старшие 8-битные регистры</strong> — AH, BH, CH, DH не поддерживаются</li>
<li><strong>Расширенные регистры</strong> — SPL, BPL, SIL, DIL, а также R8R15 не поддерживаются</li>
<li><strong>Нет умножения и деления</strong> — инструкции MUL/DIV не реализованы</li>
<li><strong>Нет операций со стеком</strong> — PUSH/POP/CALL/RET отсутствуют</li>
<li><strong>Нет динамической памяти</strong> — нет встроенных malloc/free</li>
<li><strong>Нет макросов и условной компиляции</strong></li>
<li><strong>Экспериментальный статус</strong> — некоторые инструкции могут быть реализованы не полностью</li>
</ul>
@ -732,7 +762,7 @@ Pass2 (шаг 5): ⚠️ ЧАСТИЧНО
<footer>
<p>───────────────────────────────────────────────────────────────────────</p>
<p>КВС Ассемблер v2.0 | Экспериментальный проект | 2025</p>
<p>КВС Ассемблер v2.0 | Экспериментальный проект | 2026</p>
<p>Только для образовательных целей. Используйте на свой страх и риск.</p>
<p style="margin-top: 10px; font-size: 10px; color: #005500;">
> Система готова. Введите команду...

281
README.md
View file

@ -1,5 +1,5 @@
```markdown
# КВС Ассемблер с русским синтаксисом для x86-64
# КВС Ассемблер с русским синтаксисом для x86-64
**КВС** — это экспериментальный ассемблер для архитектуры x86-64, полностью использующий **русскую лексику** для мнемоник инструкций, имён регистров и директив. Проект носит образовательный характер и демонстрирует принципы работы ассемблера, построения ELF-файлов и трансляции высокоуровневых концепций в машинный код.
@ -24,8 +24,12 @@
- **Полностью русский синтаксис** — все инструкции, регистры и директивы на кириллице
- **Генерация исполняемых ELF-файлов** — 64-битные ELF для Linux, готовые к запуску
- **Двухпроходная сборка** — традиционная схема с разрешением меток
- **Поддержка секций** — разделение на `.текст` (код) и `.данные` (данные)
- **Абсолютная адресация памяти** — чтение и запись по меткам `[переменная]` и абсолютным адресам `[0x402000]` с RIP-relative кодированием
- **Поддержка секций** — разделение на `.текст` (код), `.данные` (данные) и `.бсс` (неинициализированные данные)
- **Гибкая адресация памяти**:
- абсолютная адресация по меткам `[переменная]`
- абсолютная адресация по числовому адресу `[0x402000]`
- косвенная адресация через регистр `[раикс]`
- всё с RIP-relative кодированием для 64-битных перемещений
- **CSV-логирование** — детальный файл с соответствием адресов, байтов и исходных команд
- **Более 50 инструкций** — полный набор основных команд x86-64
- **Минимализм зависимостей** — только стандартная библиотека Python
@ -37,29 +41,30 @@
```
Исходный файл (.квс)
▼ (kvs_lexer.py)
▼ (kvs_lexer.py)
Файл токенов (.токены)
▼ (kvs_parser.py)
▼ (kvs_parser.py)
AST-представление (.аст)
▼ (kvs_pass1.py)
▼ (kvs_pass1.py)
Первый проход: размеры, метки (.проход1)
▼ (kvs_pass2.py + kvs_pass2_encoder.py)
▼ (kvs_pass2.py + kvs_pass2_encoder.py)
Второй проход: генерация кода (.csv)
▼ (kvs_builder.py)
▼ (kvs_builder.py)
ELF-компоновщик (.elf)
Исполняемый файл!
```
### Модули компилятора
| Файл | Назначение |
|------|------------|
|------|-------------|
| `kvs_build.py` | Главный сборочный скрипт |
| `kvs_lexer.py` | Лексический анализ, разбор на токены |
| `kvs_parser.py` | Синтаксический анализ, построение AST |
@ -73,7 +78,7 @@ ELF-компоновщик (.elf)
```bash
# Клонирование репозитория
git clone https://github.com/username/kvs.git
git clone https://github.com/artradeskz/kvs.git
cd kvs
# Установка прав на выполнение (при необходимости)
@ -87,21 +92,21 @@ python3 kvs_build.py --help
### 1. Создайте файл `hello.квс`:
```asm
```assembly
.текст
.глобал _start
_start:
; write(1, msg, 13)
переместить_имм раикс, 1
переместить_имм рдиай, 1
переместить_имм раикс,1
переместить_имм рдиай,1
переместить_имм рсиай, msg
переместить_имм рдикс, 13
переместить_имм рдикс,13
вызов_системы
; exit(0)
переместить_имм раикс, 60
переместить_имм рдиай, 0
переместить_имм раикс,60
переместить_имм рдиай,0
вызов_системы
.данные
@ -121,6 +126,7 @@ python3 kvs_build.py hello.квс
```
**Вывод:**
```
Hello, World!
```
@ -129,21 +135,24 @@ Hello, World!
### Структура программы
```
```assembly
.текст ; секция кода (обязательна)
; ... инструкции ...
.данные ; секция данных (опциональна)
; ... данные ...
; ... инициализированные данные ...
.бсс ; секция неинициализированных данных (опциональна)
; ... переменные без начального значения ...
```
### Метки
Метка — это имя, за которым следует двоеточие:
```asm
```assembly
_start: ; метка _start
переместить_имм раикс, 1
переместить_имм раикс,1
переход _start ; переход на метку
```
@ -151,23 +160,31 @@ _start: ; метка _start
Однострочные комментарии начинаются с `;`:
```asm
```assembly
; Это комментарий
переместить_имм раикс, 42 ; комментарий после инструкции
переместить_имм раикс,42 ; комментарий после инструкции
```
### Работа с памятью (абсолютная адресация)
### Работа с памятью
```asm
```assembly
; Запись значения в память по метке
переместить_имм раикс, 42
переместить_имм раикс,42
сохранить [переменная], раикс
; Чтение значения из памяти
загрузить рбикс, [переменная]
загрузить рбикс,[переменная]
; Запись по абсолютному адресу
сохранить [0x402000], раикс
; Косвенная адресация через регистр
переместить_имм рбикс, переменная
загрузить раикс, [рбикс]
; Работа с BSS-секцией
.бсс
счётчик: .байт 0
```
## 📖 Система команд
@ -178,23 +195,24 @@ _start: ; метка _start
|------------|-----------|----------|
| `переместить_имм` | `переместить_имм рег, значение` | Загрузить константу в регистр |
```asm
переместить_имм раикс, 42 ; RAX = 42
переместить_имм еаикс, 0x7FFF ; EAX = 32767
переместить_имм ал, 0xFF ; AL = 255
```assembly
переместить_имм раикс,42 ; RAX = 42
переместить_имм еаикс,0x7FFF ; EAX = 32767
переместить_имм ал,0xFF ; AL = 255
```
### Работа с памятью
| Инструкция | Синтаксис | Описание |
|------------|-----------|----------|
| `загрузить` | `загрузить рег, [метка/адрес]` | Загрузить значение из памяти |
| `сохранить` | `сохранить [метка/адрес], рег` | Сохранить значение в память |
| `загрузить` | `загрузить рег, [метка/адрес/регистр]` | Загрузить значение из памяти |
| `сохранить` | `сохранить [метка/адрес/регистр], рег` | Сохранить значение в память |
```asm
загрузить раикс, [переменная] ; RAX = *переменная
```assembly
загрузить раикс,[переменная] ; RAX = *переменная
сохранить [результат], раикс ; *результат = RAX
загрузить рбикс, [0x402000] ; загрузка по абсолютному адресу
загрузить рбикс,[0x402000] ; загрузка по абсолютному адресу
загрузить раикс,[рбикс] ; косвенная загрузка через регистр
```
### Арифметика и логика
@ -209,10 +227,10 @@ _start: ; метка _start
| `сравнить_с` | `сравнить_с рег, значение` | Сравнить с константой |
| `проверить` | `проверить рег1, рег2` | TEST (логическое AND) |
```asm
```assembly
прибавить раикс, рбикс ; RAX += RBX
увеличить рсикс ; RCX++
сравнить раикс, 10 ; сравнить RAX с 10
сравнить раикс,10 ; сравнить RAX с 10
```
### Переходы
@ -240,10 +258,10 @@ _start: ; метка _start
|------------|----------|
| `вызов_системы` | Вызов ядра Linux (syscall) |
```asm
```assembly
; Пример: завершение программы
переместить_имм раикс, 60 ; syscall 60 = exit
переместить_имм рдиай, 0 ; код возврата 0
переместить_имм раикс,60 ; syscall 60 = exit
переместить_имм рдиай,0 ; код возврата 0
вызов_системы
```
@ -251,24 +269,24 @@ _start: ; метка _start
КВС поддерживает все основные 64-битные регистры x86-64:
| 64-бит | 32-бит | 16-бит | 8-бит (мл.) | 8-бит (ст.) |
|--------|--------|--------|-------------|-------------|
| `раикс` | `еаикс` | `аикс` | `ал` | `аш` |
| `рбикс` | `ебикс` | `бикс` | `бл` | `бш` |
| `рсикс` | `есикс` | `сикс` | `кл` | `чш` |
| `рдикс` | `едикс` | `дикс` | `дл` | `дш` |
| `рсипи` | `есипи` | `эсп` | `спл` | — |
| `рбипи` | `ебипи` | `бипи` | `бпл` | — |
| `рсиай` | `есиай` | `эс` | `сил` | — |
| `рдиай` | `едиай` | `ди` | `дил` | — |
| `р8`…`р15` | `р8д`…`р15д` | `р8в`…`р15в` | `р8б`…`р15б` | — |
| 64-бит | 32-бит | 16-бит | 8-бит (мл.) |
|--------|--------|--------|-------------|
| `раикс` | `еаикс` | `аикс` | `ал` |
| `рбикс` | `ебикс` | `бикс` | `бл` |
| `рсикс` | `есикс` | `сикс` | `кл` |
| `рдикс` | `едикс` | `дикс` | `дл` |
| `рсипи` | `есипи` | `эсп` | `спл` |
| `рбипи` | `ебипи` | `бипи` | `бпл` |
| `рсиай` | `есиай` | `эс` | `сил` |
| `рдиай` | `едиай` | `ди` | `дил` |
## 🔧 Директивы ассемблера
| Директива | Назначение | Пример |
|-----------|------------|--------|
| `.текст` | Начало секции кода | `.текст` |
| `.данные` | Начало секции данных | `.данные` |
| `.данные` | Начало секции инициализированных данных | `.данные` |
| `.бсс` | Начало секции неинициализированных данных | `.бсс` |
| `.глобал` | Объявление глобальной метки | `.глобал _start` |
| `.строка` | Строка без завершающего нуля | `.строка "Hello"` |
| `.строкауль` | Строка с завершающим нулём | `.строкауль "Hello"` |
@ -279,21 +297,19 @@ _start: ; метка _start
### Работа с памятью (переменные)
```asm
```assembly
.текст
.глобал _start
_start:
; Запись значения в переменную
переместить_имм раикс, 42
переместить_имм раикс,42
сохранить [переменная], раикс
; Чтение значения из переменной
загрузить рбикс, [переменная]
загрузить рбикс,[переменная]
; Завершение с кодом возврата
переместить_имм раикс, 60
загрузить рдиай, [переменная]
переместить_имм раикс,60
загрузить рдиай,[переменная]
вызов_системы
.данные
@ -302,26 +318,26 @@ _start:
### Цикл и условный переход
```asm
```assembly
.текст
.глобал _start
_start:
переместить_имм рсикс, 10 ; счетчик = 10
переместить_имм рсикс,10 ; счетчик = 10
loop:
переместить_имм раикс, 1
переместить_имм рдиай, 1
переместить_имм раикс,1
переместить_имм рдиай,1
переместить_имм рсиай, msg
переместить_имм рдикс, 10
переместить_имм рдикс,10
вызов_системы
уменьшить рсикс ; счетчик--
сравнить_с рсикс, 0
сравнить_с рсикс,0
переход_если_больше loop ; если > 0, продолжаем
переместить_имм раикс, 60
переместить_имм рдиай, 0
переместить_имм раикс,60
переместить_имм рдиай,0
вызов_системы
.данные
@ -330,26 +346,82 @@ msg: .строка "Iteration\n"
### Вычисление суммы чисел от 1 до 10
```asm
```assembly
.текст
.глобал _start
_start:
переместить_имм р8, 0 ; сумма
переместить_имм р9, 10 ; счётчик
переместить_имм р8,0 ; сумма
переместить_имм р9,10 ; счётчик
loop:
прибавить р8, р9
уменьшить р9
сравнить_с р9, 0
сравнить_с р9,0
переход_если_больше loop
; exit(сумма в r8)
переместить_имм раикс, 60
переместить_имм раикс,60
переместить рдикс, р8
вызов_системы
```
### Использование BSS-секции
```assembly
.текст
.глобал _start
_start:
; инициализация счётчика в BSS
переместить_имм раикс,0
сохранить [счётчик], раикс
; цикл: увеличить счётчик 10 раз
переместить_имм рсикс,10
loop:
загрузить раикс,[счётчик]
увеличить раикс
сохранить [счётчик], раикс
уменьшить рсикс
сравнить_с рсикс,0
переход_если_больше loop
; выход с кодом = значение счётчика
загрузить рдиай,[счётчик]
переместить_имм раикс,60
вызов_системы
.бсс
счётчик: .байт 0
```
### Косвенная адресация
```assembly
.текст
.глобал _start
_start:
; загружаем адрес переменной в регистр
переместить_имм рбикс, переменная
; косвенная запись
переместить_имм раикс,99
сохранить [рбикс], раикс
; косвенное чтение
загрузить раикс,[рбикс]
; выход
переместить_имм рдиай, раикс
переместить_имм раикс,60
вызов_системы
.данные
переменная: .байт 0
```
## 🐛 Отладка и проверка
### Просмотр сгенерированного кода
@ -389,9 +461,7 @@ strace ./программа.elf
```bash
gdb ./программа.elf
```
```gdb
(gdb) break _start ; установить точку останова
(gdb) run ; запустить
(gdb) info registers ; показать регистры
@ -403,54 +473,59 @@ gdb ./программа.elf
### Поддерживается
- ✅ 64-битные, 32-битные, 16-битные и 8-битные регистры
- ✅ 64-битные, 32-битные, 16-битные и 8-битные регистры (AL, BL, CL, DL)
- ✅ Непосредственная загрузка констант (imm) в регистры
- ✅ Сравнение регистров и регистров с константами
- ✅ Условные и безусловные переходы (длинные и короткие)
- ✅ Арифметические операции (ADD, SUB, INC, DEC)
- ✅ Логическая операция TEST
- ✅ Системные вызовы Linux (syscall)
- ✅ Секции `.текст` и `.данные`
- ✅ Секции `.текст`, `.данные` и `.бсс`
- ✅ Строковые литералы с escape-последовательностями (`\n`, `\t`, `\\`, `\"`)
- ✅ Директива `.байт` для raw-данных
- ✅ Директива `.константа` для имён констант
- ✅ **Абсолютная адресация памяти** `[метка]` и `[число]` (RIP-relative)
- ✅ **Абсолютная адресация** по меткам и числовым адресам `[метка]` / `[0x402000]`
- ✅ **Косвенная адресация через регистр** `[раикс]`
- ✅ RIP-relative кодирование для всех видов адресации
### Не поддерживается (в разработке)
- ❌ Косвенная адресация `[reg]` — доступ к памяти через регистр
- ❌ Адресация со смещением `[reg + disp]`
- ❌ Сложная адресация с индексом `[reg + reg*scale]` и полная SIB-адресация
- ❌ Инструкции для работы со стеком (PUSH, POP, CALL, RET) — частично
- ❌ Инструкции для работы со стеком (PUSH, POP, CALL, RET)
- ❌ Старшие 8-битные регистры (AH, BH, CH, DH) и расширенные младшие (SPL, BPL, SIL, DIL)
- ❌ Регистры R8R15 и их байтовые/словные версии
- ❌ Поддержка плавающей запятой (FPU/SSE)
- ❌ Многомодульная компиляция
- ❌ Директива `.bss` для неинициализированных данных
- ❌ Макросы
## 📈 План развития
### Реализовано (v2.0)
- [x] Лексер с токенами `[`, `]`, `NUMBER`
- [x] Парсер с поддержкой операндов в квадратных скобках
- [x] Первый проход с корректным расчётом размера инструкций с памятью
- [x] Второй проход с кодированием абсолютной адресации через RIP-relative
- [x] Поддержка меток в операндах памяти `[переменная]`
- [x] Рефакторинг: выделение кодировщика в отдельный модуль
- Лексер с токенами `[`, `]`, `NUMBER`
- Парсер с поддержкой операндов в квадратных скобках
- Первый проход с корректным расчётом размера инструкций с памятью
- Второй проход с кодированием абсолютной адресации через RIP-relative
- Поддержка меток в операндах памяти `[переменная]`
- Поддержка числовых адресов `[0x402000]`
- Поддержка косвенной адресации `[регистр]`
- Секция `.бсс` для неинициализированных данных
- Рефакторинг: выделение кодировщика в отдельный модуль
### В планах (v3.0)
- [ ] Косвенная адресация `[reg]`
- [ ] Адресация со смещением `[reg + disp]`
- [ ] Сложная адресация с индексом `[reg + reg*scale]`
- [ ] Полная SIB-адресация `[reg + reg*scale + disp]`
- [ ] Директива `.bss` для неинициализированных данных
- [ ] Поддержка инструкций PUSH/POP/CALL/RET для стековых операций
- [ ] Стандартная библиотека (`libkvs.квс`): malloc, free, strlen, strcmp, print
- Адресация со смещением `[reg + disp]`
- Сложная адресация с индексом `[reg + reg*scale]`
- Полная SIB-адресация `[reg + reg*scale + disp]`
- Поддержка инструкций PUSH/POP/CALL/RET для стековых операций
- Стандартная библиотека (`libkvs.квс`): malloc, free, strlen, strcmp, print
## 📄 Лицензия
Только для образовательных целей. Используйте на свой страх и риск.
```
КВС Ассемблер | Экспериментальный проект | 2026
Только для образовательных целей. Используйте на свой страх и риск.
```
---
*КВС Ассемблер | Экспериментальный проект | 2026*
*Только для образовательных целей. Используйте на свой страх и риск.*
```

View file

@ -246,5 +246,5 @@ Pass2 (шаг 5):
```
тестировать все директивы бнд
изучить работу с кучей