Доброго времени суток!
Пусть машина находится в режиме работы без округления (считай целочисленный режим). В памяти, по адресам M1+a, M1+b лежат два числа (но могут лежать и на стеке через M15 (M17))
Как может выглядеть программа вычисляющая строгие и не строгие неравенства чисел a и b?
Например, для программы вида (условия в операторе IF):
module ifsimple;
const
pass = 12345;
fail = 54321;
var t1, t2 : integer;
begin
t1 := 5;
t2 := 10;
if t1 <= t2 then
t1 := pass
else
t1 := fail
end;
halt(t1)
end ifsimple.
Я делаю игрушечный компилятор по мотивам книги Вирта "Построение компиляторов" где применяется классический подход - генерация кода на лету, а программа при определенных ограничениях может откомпилироваться за один проход компилятора.
Подобная программа транслируется в код одноадресной виртуальной машины:
TEXT:
00000: ifsimple_main ALLOC 2 ; выделение места на стеке
00001: CLOAD 2 ; загрузка константы 5 на стек
00002: VSTOR -2 ; сохранение в локальную переменную t1
00003: CLOAD 3 ; загрузка константы 10
00004: VSTOR -1 ; сохранение в t2
00005: VLOAD -2 ; загрузка знач. локальной переменной t1 на стек
00006: VLOAD -1 ; загрузка знач. локальной переменной t2 на стек
00007: RELOP <= ; удаление со стека 2-х значений, запись на стек результата сравнения
00008: BR_ZERO 12 ; переход если ложь
00009: CLOAD 0 ; загрузка константы pass
00010: VSTOR -2 ; сохранения вершины стека в перем. t1
00011: BR 14 ; переход на окончание оператора IF
00012: CLOAD 1 ; загрузка fail на вершину стека
00013: VSTOR -2 ; сохранение вершины стека в t1
00014: VLOAD -2 ; загрузка аргумента на стек
00015: SYSCALL halt ; вызов системной процедуры
00016: DEALLOC 1 ; очистка места под аргумент после вызова
00017: STOP 12345 ; останов
CONSTANT TABLE:
00000: pass 12345
00001: fail 54321
00002: 5 5
00003: 10 10
PROCEDURE TABLE
ifsimple_main: 0
И вот, добравшись до генерации кода целевой машины, возникает вопрос как в командах БЭСМ-6 правильно закодировать условный оператор для выражений с <, <=, ==, !=, >=, >.
Из набора команд имеем два варианта условного перехода:
UZA - переход по ω = 0
U1A - переход по ω = 1
В зависимости от типа операции флаг ω вычисляется так:
switch (ω mode) {
case additive: ω = (A[41] != 0); /* A < 0 */ break;
case multiplicative: ω = (A[48] != 1); /* abs(A) < 0.5 */ break;
case logical: ω = (A[48:1] != 0); /* A != 0 */ break;
case 0: ω = 1;
}
Получаем что для кодирования a < b:
xta a,M1
a-x b,M1
uza else_block ; u1a для a >= b
...
Для a == b:
xta a, M1
aex b, M2
u1a else_block ; uza для a != b
...
Как быть с нестрогим неравенством, типа a <= b ?