x86128: (Default)
[personal profile] x86128
Продолжаю эксперименты со строительством компилятора.
Реализовал преобразование кода виртуальной машины в код виртуальной целочисленной БЭСМ-6 методом “курильщика” так же известного как Poor Man’s codegen 😅️.

В качестве программы для тестирования возьмем вычисление выражения:

var
    a : integer;

begin
    a := 5  - 3 * 8 div 6;
    writeint(a);
    writeln


В обратной польской записи получается так:

5 3 8 * 6 / - >a


Преобразуется в такой код “первой” виртуальной машины:

 ('CLOAD', 0),
 ('CLOAD', 1),
 ('CLOAD', 2),
 ('BINOP', '*'),
 ('CLOAD', 3),
 ('BINOP', 'DIV'),
 ('BINOP', '-'),
 ('VSTOR', -1, 'a'),
 ('VLOAD', -1, 'a'),
 ('SYSCALL', 'writeint'),
 ('DEALLOC', 1),
 ('SYSCALL', 'writeln'),
 ('STOP', '12345'),

Таблица констант:
 ('LABEL', 'const_table'),
 ('WORD', 5),
 ('WORD', 3),
 ('WORD', 8),
 ('WORD', 6),
 ('WORD', 0),
 ('LABEL', 'locals_base'),
 ('LABEL', 'stack_base')]

Место для локальной переменной a:
 ('WORD', 0),
 ('LABEL', 'locals_base'),
 ('LABEL', 'stack_base')]


Метод курильщика заключается в том, что каждую команду первой машины мы преобразуем буквально в код БЭСМ без каких либо оптимизаций, будто выполняется условный эмулятор первой ВМ на процессоре БЭСМ.

Пусть у нас регистр M1 указывает на последнюю локальную переменную текущего кадра + 1, регистр M2 - на начало блока констант, а М15 - на первый пустой элемент стека, который растет в сторону увеличения адресов.

Работать метод будет тоже со стеком, но пока без учета архитектуры БЭСМ, где аккумулятор является вершиной стека, поэтому код генерируется такой:

00005:           XTA      0         ,M2
00006:           ATX      0         ,M15
00007:           XTA      1         ,M2
00008:           ATX      0         ,M15
00009:           XTA      2         ,M2
00010:           ATX      0         ,M15
00011:           XTA      -2        ,M15
00012:           A*X      -1        ,M15
00013:           ATX      -2        ,M15
00014:           UTM      -1        ,M15
00015:           XTA      3         ,M2
00016:           ATX      0         ,M15
00017:           XTA      -2        ,M15
00018:           A/X      -1        ,M15
00019:           ATX      -2        ,M15
00020:           UTM      -1        ,M15
00021:           XTA      -2        ,M15
00022:           A-X      -1        ,M15
00023:           ATX      -2        ,M15
00024:           UTM      -1        ,M15
00025:           XTA      0         ,M15
Сохранение результата
00026:           ATX      -1        ,M1
Печать числа
00027:           XTA      -1        ,M1
00028:           ATX      0         ,M15
00029:           *77      0         
00030:           UTM      -1        ,M15
Печать перевода строки
00031:           *77      2         
00032:           STOP     12345     


Вот такой вот глупый код, но при этом рабочий.

Рассмотрим как это можно записать с учетом того что аккумулятор является вершиной стека:

5 3 8 * 6 / - >a

XTA =5
XTS =3
A*X =8
A/X =6
X-A ,M15
ATX =a


Как говорится, разница на лицо. Есть над чем поработать.
This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

Profile

x86128: (Default)
x86128

April 2023

S M T W T F S
      1
2345678
9101112131415
16171819202122
232425 26272829
30      

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 22nd, 2025 05:37 am
Powered by Dreamwidth Studios