Генератор асемблерного коду (FASM) для EnotVM32
GenBP4.7z -
http://forumstatic.ru/files/001c/77/27/56695.7z
Вихідний код для https://chat.deepseek.com/
Generator.txt
https://forumstatic.ru/files/001c/77/27/49421.txt
EnotVM |
Привет, Гость! Войдите или зарегистрируйтесь.
Генератор асемблерного коду (FASM) для EnotVM32
GenBP4.7z -
http://forumstatic.ru/files/001c/77/27/56695.7z
Вихідний код для https://chat.deepseek.com/
Generator.txt
https://forumstatic.ru/files/001c/77/27/49421.txt
Документація користувача EnotVM32 від https://chat.deepseek.com/
Документація генератора коду для EnotVM32
(на базі Turbo Pascal 4.0, ціль – FASM + Macros.asm)
# 1. Загальна архітектура генератора
Генератор складається з кількох модулів, що реалізують рівневу модель:
- "Рівень даних" – типи та константи регістрів (`uGenTR`).
- "Базовий рівень" – робота з файлом, допоміжні функції (`uGen0`).
- "Рівень команд із числовими операндами" – мнемоніки, які приймають
числа (`uGenV`).
- "Рівень команд із мітками" – ті самі мнемоніки, але з адресами-рядками
(`uGenL`).
- "Рівень програми" – конкретна логіка генерації (ваша програма) знаходиться
в `uGen` і викликається з `uMain`.
Генератор не виконує жодної інтелектуальної роботи (адресації, підрахунку переходів) – він просто створює текстовий файл із макросами FASM, які потім обробляються самим FASM. Тобто це "генератор вихідного коду асемблера", а не прямого бінарного коду.
# 2. Опис модулів
2.1. `uGenTR.pas` – регістри та їхні імена
- Оголошує тип `TReg = record id: Byte; Name: string[4]; end;`
- Містить константи для всіх 256 регістрів (довгі назви:
`AA`..`JV`, короткі назви: `A`..`Z`).
- Спеціальні регістри `YA..YH` (232..239), `ZA..ZH` (240..247),
`CMP1`, `CMP2`.
- Використовується всіма іншими модулями для звертання до регістрів
за іменем (наприклад, `A`, `YA`, `CMP1`).
"Приклад оголошення констант:"
```pascal
A : TReg = (id:0; Name:'A');
YA: TReg = (id:232; Name:'YA');
```
2.2. `uGen0.pas` – базові операції з вихідним файлом
- "`InitGen`", "`FinalGen`" – відкривають/закривають текстовий
файл `BOOT.asm`.
- "`AddStr(s)`" – записує рядок у файл.
- "`REM(s)`" – додає коментар (`; ...`).
- "`VK`" – порожній рядок.
- "`Label_(L)`" – записує мітку (`L:`).
- "`format_binary_as_bin`" – вставляє директиву `format binary as 'bin'`.
- "`include_Macros_asm`" – вставляє `include 'Macros.asm'`.
- Допоміжні функції "`IntToStr`", "`IntToHex`"
(не використовуються в ядрі, але доступні для налагодження).
Всі наступні рівні викликають тільки процедури з цього модуля для
формування вихідного тексту.
2.3. `uGenV.pas` – команди з числовими операндами
Містить процедури, які генерують рядки з макросами FASM, що приймають
"числові значення" (константи, адреси) або не мають параметрів.
"Категорії процедур:"
- "Пересилання": `MOVrv(Rg, Value)`, `MOVrr(Rg1, Rg2)`, `MOVrm(Rg, Addr)`,
`MOVrmr`, `MOVmr`, `MOVmrr`, `MOV2rm`, `MOV2mr`, `MOV2rmr`, `MOV2mrr`,
`MOV1rm`, `MOV1mr`, `MOV1rmr`, `MOV1mrr`.
- "Арифметика/логіка": `ADDrr`, `SUBrr`, `MULrr`, `DIVrr`, `MODrr`, `INCr`,
`DECr`, `ANDrr`, `ORrr`, `XORrr`, `NOTr`, `SHLrr`, `SHRrr`, `CMPrr`.
- "Переходи": `CALLa(Addr)`, `CALLr(Rg)`, `RET_`, `GOTOa(Addr)`,
`GOTOr(Rg)`, умовні знакові (`GOTOsaIs`, `GOTOsaNotIs`, ...) та
беззнакові (`GOTOuaMoreIs`, `GOTOuaLess`).
- "Стек": `PUSHr`, `POPr`, `PUSHrsvr`, `POPrsvr`.
- "Системні виклики EXTR": `EXTR(Value)`, а також окремі
процедури-обгортки (`WritelnStr`, `EndProgram`, `Readln0` і т.д.).
- "Рядкові макроси": `VarStrB(MaxSize, Text)`, `VarStrW`, `VarStr3B`,
`VarStrDW`, `ContStrB`, `ContStrW`, `ContStr3B`, `ContStrDW`.
- "Копіювання пам’яті": `CopyMainToMain`, `CopyMainToExt`,
`CopyExtToMain`, `CopyExtToExt`.
Усі вони просто формують відповідний текст, наприклад:
```pascal
procedure MOVrv(Rg: TReg; Value: Longint);
begin AddStr(' MOVrv ' + Rg.Name + ', ' + IntToStr(Value)); end;
```
2.4. `uGenL.pas` – команди з мітками
Аналогічний `uGenV`, але операндами виступають "імена міток"
(тип `string255`). Це дозволяє писати:
```pascal
MOVrl(YA, 'hello1'); // MOVrv YA, hello1
GOTOslMoreIs('loop'); // GOTOsaMoreIs loop
```
Список процедур:
`MOVrl`, `MOVrml`, `MOVmlr`, `MOVmlrr`, `MOV2rml`, `MOV2mlr`,
`MOV1rml`, `MOV1mlr`, `CALLl`, `GOTOl`, `GOTOslIs`, `GOTOslNotIs`, `GOTOslMoreIs`, `GOTOslLess`, `GOTOulMoreIs`, `GOTOulLess`.
2.5. `uGen.pas` – сама програма генерації
Це "єдине місце", яке потрібно редагувати для створення нової програми.
Містить процедуру `StartGenerator`, де послідовно викликаються потрібні
команди.
"Приклад з Hello World:"
```pascal
procedure StartGenerator;
begin
InitGen;
REM('Програма від ...');
format_binary_as_bin;
include_Macros_asm;
MOVrl(YA, 'hello1');
WritelnStr;
MOVrl(YA, 'hello2');
WritelnStr;
Readln0;
EndProgram;
Label_('hello1');
AddStr('db 1,13,13,''Hello, World!''');
Label_('hello2');
ConstStrB('Hello, World!');
FinalGen;
end;
```
2.6. `uMain.pas` та `ProjectP.pas`
- `uMain` містить `StartProgram`, яка викликає `StartGenerator`.
- `ProjectP` – головна програма, яка виконує `InitProgram;
StartProgram; FinalProgram;`.
# 3. Робота з рядками (макроси VarStr/ContStr)
У вихідному коді рядки зберігаються в одному з чотирьох форматів
(тип 1, 2, 3, 4), що відрізняються розрядністю полів довжини.
Генератор пропонує дві групи процедур:
- "VarStrB / VarStrW / VarStr3B / VarStrDW" – примусово задається максимальний
розмір буфера. Використовуйте, коли розмір відомий заздалегідь.
- "ContStrB / ContStrW / ContStr3B / ContStrDW" – розмір обчислюється
автоматично (за фактичною довжиною рядка). Простіше, але менш гнучко, якщо треба резервувати місце.
У згенерованому `.asm`-файлі це виглядає як виклик відповідного макросу,
наприклад:
```asm
hello2: ContStrB 'Hello, World!'
```
# 4. Як створити нову програму за допомогою генератора
1. Відредагуйте процедуру `StartGenerator` в модулі `uGen.pas`.
2. Використовуйте процедури з `uGenV` та `uGenL`, щоб описати алгоритм.
3. Для рядкових констант застосовуйте `ContStr...` або `VarStr...`.
4. Позначайте мітки через `Label_('ім'я')`.
5. Скомпілюйте проект `ProjectP.pas` – отримаєте `ProjectP.exe`.
6. Запустіть `ProjectP.exe` – у поточній папці з’явиться `BOOT.asm`.
7. Відкомпілюйте `BOOT.asm` за допомогою FASM (наприклад, `fasm BOOT.asm
BOOT.bin`).
8. Запустіть `EnotVM32.exe` (попередньо скопіювавши `BOOT.bin`
у папку з емулятором).
# 5. Обмеження та примітки
- Генератор не перевіряє семантику (наприклад, чи існує мітка `hello1`).
Це робота FASM.
- Усі адреси та числа задаються безпосередньо користувачем.
Жодних обчислень адрес чи підрахунку довжин команд генератор не
виконує – він покладається на FASM.
- Модулі `uGenV` та `uGenL` навмисно розділені, щоб підкреслити різницю
між «числовим» та «мітковим» інтерфейсом. У майбутньому це спростить
перехід до прямого генератора бінарного коду.
# 6. Перехід до наступного етапу (Delphi, прямий бінарний генератор)
Коли ви будете готові повернутися до прямого генератора `BOOT.bin`
(рівні 0, 1, …), цей генератор залишиться як засіб налагодження
та прототипування. Новий генератор використовуватиме `uTSSB` як
буфер та будуватиме бінарний файл напряму, вирішуючи адреси
міток самостійно.