x86128: (Default)
[personal profile] x86128
Доброго времени!

Продолжаю эксперименты с компиляторо-строением.

Добавил возможность возвращать результаты работы процедуры через VAR-аргументы.

Поэтому подобный код компилируется и работает:

MODULE Samples;
const
    pass = 12345;
    fail = 54321;

var
    t : integer;

procedure gcd(a,b : integer; var res : integer);
begin
    while b > 0 do
        res := b;
        b := a mod b;
        a := res
    end
end gcd;

begin
    gcd(27+25*3-(10 div 5),15, t);
    if t = 5 then
        halt(pass)
    else
        halt(fail)
    end

END Samples.


Передача аргументов осуществляется через стек, на котором формируется рабочая область (фрейм) куда записываются аргументы процедуры и внутренние локальные переменные.

Схема такая:

| old frame | arg0 | arg1 | v0 | v1 | v2 | old_bp | return address | free RAM cells |
|-----------+------+------+----+----+----+--------+----------------+----------------|
|           |      |      |    |    |    | ^ BP   |                | ^ SP           |


Сделал я это для того, чтобы была возможность работы с рекурсией, но боком вышло то, что глобальные переменные по отношению к телу процедуры “дали прикурить” т.к. их адреса во время компиляции программы неизвестны (так же из-за возможности объявлять вложенные процедуры (своего рода замыкания)). Можно было ввести некоторый GP который бы показывал на локальные переменные вышестоящей области видимости, но тогда пришлось бы организовывать какой-то механизм многократной относительной адресации. Понятно, что эта задача решаема, но в книге по Оберону я пока не добрался до соотв. главы. Если запретить рекурсию, то задача размещения и адресации переменных становится тривиальной, т.к. все адреса можно вычислить прямо на этапе компиляции.

Результатом работы компилятора является такой питонячий объект:
{'c_mem': [12345, 54321],
 'consts': {'fail': {'line': 4, 'offset': 1, 'val': 54321},
            'pass': {'line': 3, 'offset': 0, 'val': 12345}},
 'main': 'Samples_main',
 'name': 'Samples',
 'p_text': [('LABEL', 'L0'),
            ('VLOAD', -2, 'b'),
            ('CONST', 0),
            ('RELOP', '>'),
            ('BR_ZERO', 'L1'),
            ('VLOAD', -2, 'b'),
            ('RSTOR', -1, 'res'),
            ('VLOAD', -3, 'a'),
            ('VLOAD', -2, 'b'),
            ('BINOP', 'MOD'),
            ('VSTOR', -2, 'b'),
            ('RLOAD', -1, 'res'),
            ('VSTOR', -3, 'a'),
            ('BR', 'L0'),
            ('LABEL', 'L1'),
            ('RETURN', ''),
            ('ALLOC', 1),
            ('CONST', 27),
            ('CONST', 25),
            ('CONST', 3),
            ('BINOP', '*'),
            ('BINOP', '+'),
            ('CONST', 10),
            ('CONST', 5),
            ('BINOP', 'DIV'),
            ('BINOP', '-'),
            ('CONST', 15),
            ('ADR_LOAD', -1, 't'),
            ('CALL', 0, 'gcd'),
            ('DEALLOC', 3),
            ('VLOAD', -1, 't'),
            ('CONST', 5),
            ('RELOP', '='),
            ('BR_ZERO', 'L3'),
            ('CLOAD', 0, 'pass'),
            ('SYSCALL', 'halt'),
            ('DEALLOC', 1),
            ('BR', 'L3'),
            ('LABEL', 'L2'),
            ('CLOAD', 1, 'fail'),
            ('SYSCALL', 'halt'),
            ('DEALLOC', 1),
            ('LABEL', 'L3'),
            ('STOP', '12345')],
 'proc_tab': {'Samples_main': {'offset': 16},
              'gcd': {'arg_sz': 3,
                      'args': {'a': {'offset': 2,
                                     'typ': 'integer',
                                     'var': False},
                               'b': {'offset': 1,
                                     'typ': 'integer',
                                     'var': False},
                               'res': {'offset': 0,
                                       'typ': 'integer',
                                       'var': True}},
                      'consts': {},
                      'offset': 0,
                      'v_size': 0,
                      'vars': {}}},
 'v_size': 1,
 'vars': {'t': {'offset': 0, 'size': 1, 'typ': 'integer'}}}


Интерес представляет поле p_text, в котором находится текст программы в виде инструкций для абстрактной виртуальной машины. Я выбрал одноадресное промежуточное представление чтобы быть ближе к инструкциям машины МЭСМ-6, третий аргумент у некоторых операций носит косметический характер и сохраняется для удобочитаемости человеком.

Трассировка вычисления НОД для чисел 100 и 15:
OP=('ALLOC', 1) PC=16 BP=1 SP=1 D_MEM=[0]
OP=('CONST', 27) PC=17 BP=1 SP=2 D_MEM=[0, 27]
OP=('CONST', 25) PC=18 BP=1 SP=3 D_MEM=[0, 27, 25]
OP=('CONST', 3) PC=19 BP=1 SP=4 D_MEM=[0, 27, 25, 3]
OP=('BINOP', '*') PC=20 BP=1 SP=3 D_MEM=[0, 27, 75]
OP=('BINOP', '+') PC=21 BP=1 SP=2 D_MEM=[0, 102]
OP=('CONST', 10) PC=22 BP=1 SP=3 D_MEM=[0, 102, 10]
OP=('CONST', 5) PC=23 BP=1 SP=4 D_MEM=[0, 102, 10, 5]
OP=('BINOP', 'DIV') PC=24 BP=1 SP=3 D_MEM=[0, 102, 2]
OP=('BINOP', '-') PC=25 BP=1 SP=2 D_MEM=[0, 100]
OP=('CONST', 15) PC=26 BP=1 SP=3 D_MEM=[0, 100, 15]
OP=('ADR_LOAD', -1, 't') PC=27 BP=1 SP=4 D_MEM=[0, 100, 15, 0]
OP=('CALL', 0, 'gcd') PC=28 BP=4 SP=6 D_MEM=[0, 100, 15, 0, 1, 29]
OP=('LABEL', 'L0') PC=0 BP=4 SP=6 D_MEM=[0, 100, 15, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=1 BP=4 SP=7 D_MEM=[0, 100, 15, 0, 1, 29, 15]
OP=('CONST', 0) PC=2 BP=4 SP=8 D_MEM=[0, 100, 15, 0, 1, 29, 15, 0]
OP=('RELOP', '>') PC=3 BP=4 SP=7 D_MEM=[0, 100, 15, 0, 1, 29, True]
OP=('BR_ZERO', 'L1') PC=4 BP=4 SP=6 D_MEM=[0, 100, 15, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=5 BP=4 SP=7 D_MEM=[0, 100, 15, 0, 1, 29, 15]
OP=('RSTOR', -1, 'res') PC=6 BP=4 SP=6 D_MEM=[15, 100, 15, 0, 1, 29]
OP=('VLOAD', -3, 'a') PC=7 BP=4 SP=7 D_MEM=[15, 100, 15, 0, 1, 29, 100]
OP=('VLOAD', -2, 'b') PC=8 BP=4 SP=8 D_MEM=[15, 100, 15, 0, 1, 29, 100, 15]
OP=('BINOP', 'MOD') PC=9 BP=4 SP=7 D_MEM=[15, 100, 15, 0, 1, 29, 10]
OP=('VSTOR', -2, 'b') PC=10 BP=4 SP=6 D_MEM=[15, 100, 10, 0, 1, 29]
OP=('RLOAD', -1, 'res') PC=11 BP=4 SP=7 D_MEM=[15, 100, 10, 0, 1, 29, 15]
OP=('VSTOR', -3, 'a') PC=12 BP=4 SP=6 D_MEM=[15, 15, 10, 0, 1, 29]
OP=('BR', 'L0') PC=13 BP=4 SP=6 D_MEM=[15, 15, 10, 0, 1, 29]
OP=('LABEL', 'L0') PC=0 BP=4 SP=6 D_MEM=[15, 15, 10, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=1 BP=4 SP=7 D_MEM=[15, 15, 10, 0, 1, 29, 10]
OP=('CONST', 0) PC=2 BP=4 SP=8 D_MEM=[15, 15, 10, 0, 1, 29, 10, 0]
OP=('RELOP', '>') PC=3 BP=4 SP=7 D_MEM=[15, 15, 10, 0, 1, 29, True]
OP=('BR_ZERO', 'L1') PC=4 BP=4 SP=6 D_MEM=[15, 15, 10, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=5 BP=4 SP=7 D_MEM=[15, 15, 10, 0, 1, 29, 10]
OP=('RSTOR', -1, 'res') PC=6 BP=4 SP=6 D_MEM=[10, 15, 10, 0, 1, 29]
OP=('VLOAD', -3, 'a') PC=7 BP=4 SP=7 D_MEM=[10, 15, 10, 0, 1, 29, 15]
OP=('VLOAD', -2, 'b') PC=8 BP=4 SP=8 D_MEM=[10, 15, 10, 0, 1, 29, 15, 10]
OP=('BINOP', 'MOD') PC=9 BP=4 SP=7 D_MEM=[10, 15, 10, 0, 1, 29, 5]
OP=('VSTOR', -2, 'b') PC=10 BP=4 SP=6 D_MEM=[10, 15, 5, 0, 1, 29]
OP=('RLOAD', -1, 'res') PC=11 BP=4 SP=7 D_MEM=[10, 15, 5, 0, 1, 29, 10]
OP=('VSTOR', -3, 'a') PC=12 BP=4 SP=6 D_MEM=[10, 10, 5, 0, 1, 29]
OP=('BR', 'L0') PC=13 BP=4 SP=6 D_MEM=[10, 10, 5, 0, 1, 29]
OP=('LABEL', 'L0') PC=0 BP=4 SP=6 D_MEM=[10, 10, 5, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=1 BP=4 SP=7 D_MEM=[10, 10, 5, 0, 1, 29, 5]
OP=('CONST', 0) PC=2 BP=4 SP=8 D_MEM=[10, 10, 5, 0, 1, 29, 5, 0]
OP=('RELOP', '>') PC=3 BP=4 SP=7 D_MEM=[10, 10, 5, 0, 1, 29, True]
OP=('BR_ZERO', 'L1') PC=4 BP=4 SP=6 D_MEM=[10, 10, 5, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=5 BP=4 SP=7 D_MEM=[10, 10, 5, 0, 1, 29, 5]
OP=('RSTOR', -1, 'res') PC=6 BP=4 SP=6 D_MEM=[5, 10, 5, 0, 1, 29]
OP=('VLOAD', -3, 'a') PC=7 BP=4 SP=7 D_MEM=[5, 10, 5, 0, 1, 29, 10]
OP=('VLOAD', -2, 'b') PC=8 BP=4 SP=8 D_MEM=[5, 10, 5, 0, 1, 29, 10, 5]
OP=('BINOP', 'MOD') PC=9 BP=4 SP=7 D_MEM=[5, 10, 5, 0, 1, 29, 0]
OP=('VSTOR', -2, 'b') PC=10 BP=4 SP=6 D_MEM=[5, 10, 0, 0, 1, 29]
OP=('RLOAD', -1, 'res') PC=11 BP=4 SP=7 D_MEM=[5, 10, 0, 0, 1, 29, 5]
OP=('VSTOR', -3, 'a') PC=12 BP=4 SP=6 D_MEM=[5, 5, 0, 0, 1, 29]
OP=('BR', 'L0') PC=13 BP=4 SP=6 D_MEM=[5, 5, 0, 0, 1, 29]
OP=('LABEL', 'L0') PC=0 BP=4 SP=6 D_MEM=[5, 5, 0, 0, 1, 29]
OP=('VLOAD', -2, 'b') PC=1 BP=4 SP=7 D_MEM=[5, 5, 0, 0, 1, 29, 0]
OP=('CONST', 0) PC=2 BP=4 SP=8 D_MEM=[5, 5, 0, 0, 1, 29, 0, 0]
OP=('RELOP', '>') PC=3 BP=4 SP=7 D_MEM=[5, 5, 0, 0, 1, 29, False]
OP=('BR_ZERO', 'L1') PC=4 BP=4 SP=6 D_MEM=[5, 5, 0, 0, 1, 29]
OP=('LABEL', 'L1') PC=14 BP=4 SP=6 D_MEM=[5, 5, 0, 0, 1, 29]
OP=('RETURN', '') PC=15 BP=1 SP=4 D_MEM=[5, 5, 0, 0]
OP=('DEALLOC', 3) PC=29 BP=1 SP=1 D_MEM=[5]
OP=('VLOAD', -1, 't') PC=30 BP=1 SP=2 D_MEM=[5, 5]
OP=('CONST', 5) PC=31 BP=1 SP=3 D_MEM=[5, 5, 5]
OP=('RELOP', '=') PC=32 BP=1 SP=2 D_MEM=[5, True]
OP=('BR_ZERO', 'L3') PC=33 BP=1 SP=1 D_MEM=[5]
OP=('CLOAD', 0, 'pass') PC=34 BP=1 SP=2 D_MEM=[5, 12345]

Program halted with code: 12345
SUCCESS
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 06:36 am
Powered by Dreamwidth Studios