1.11.2. ВЫХОДНОЙ ЯЗЫК

Результатом работы компилятора является целевая программа в "машинном коде", имеющая следующий синтаксис:

$ Программа = { Директива }.

$ Директива =

$ Инструкция | "BLOCK" "," Значение ";".

$ Инструкция =

$ КодОперации "," Значение ";" |

$ КодОперации =

$ ADD | SUB | MUL | DIV | LOAD | STORE |

$ ADDC | SUBC | MULC | DIVC | LOADC |

$ JUMPEQ | JUMPNE | JUMPLT | JUMPGT | JUMPLE | JUMPGE

$ JUMP | READ | WRITE | HALT.

$ Значение = Число.

Программа представляет собой последовательность директив, а каждая директива является либо "инструкцией", т.е. машинной командой, либо директивой резервирования памяти.


Мы считаем, что оперативная память машины состоит из ячеек, каждая из которых имеет адрес - целое положительное число (таким образом, ячейки пронумерованы с 1). Каждая ячейка может содержать либо одну инструкцию, либо одно целое число.

Выполнение программы всегда начинается с первой ячейки.

Помимо оперативной памяти в машине имеется сумматор, который может содержать одно число.


Директива

BLOCK,Int;

означает, что в этом месте программы следует оставить незанятыми Int ячеек памяти. Обычно эта директива находится в конце программы и используется для выделения ячеек памяти, предназначенных для хранения значений переменных.


Каждая инструкция имеет вид:

Op,Value;

где Op - название выполняемой операции, а Value операнд этой операции. Смысл операнда Value определяется названием операции. Для некоторых операций Value является адресом некоторой ячейки, которая используется при выполнении операции. Для других операций Value представляет собой целое число, которое также используется при выполнении операции. Для некоторых операций, однако, операнд не требуется, и в этом случае Value должно быть равно нулю.


Инструкция LOAD,Addr; загружает в сумматор содержимое ячейки с адресом Addr. Инструкция STORE,Addr; записывает содержимое сумматора в ячейку с адресом Addr.


Инструкция LOADC,Int; загружает число Int в сумматор.


Инструкции ADD, SUB, MUL и DIV имеют вид Op,Addr; и вычисляют соответственно сумму, разность, произведение и целую часть частного двух чисел. При этом первое число берется из сумматора, второе - из ячейки с адресом Addr, а результат записывается в сумматор.


Инструкции ADDC, SUBC, MULC и DIVC имеют вид Op,Int; и вычисляют соответственно сумму, разность, произведение и целую часть частного двух чисел. При этом первое число берется из сумматора, второе число равно Int, а результат записывается в сумматор.


Инструкция READ,Addr; читает с устройства ввода очередное число и помещает его в ячейку с адресом Addr. Инструкция WRITE,0; записывает число, находящееся на сумматоре, на устройство вывода.


Инструкция HALT,0; прекращает работу программы.


Инструкция JUMP,Addr; передает управление на ячейку с адресом Addr.


И наконец, последняя группа инструкций - это условные переходы JUMPEQ, JUMPNE, JUMPLT, JUMPGT, JUMPLE и JUMPGE, которые имеют вид Op,Addr;. Выполняются они следующим образом. Сначала содержимое сумматора сравнивается с нулем. Если проверяемое условие выполнено, то управление передается инструкции с адресом Addr, если не выполнено - следующей инструкции. Какую проверку выполнять определяют две последние буквы в имени инструкции. EQ означает проверку того, что содержимое сумматора равно 0, NE - что оно не равно 0, LT - что оно меньше 0, GT - что оно больше 0, LE - что оно меньше или равно 0, GE - что оно больше или равно 0.


Программа вычисления факториала, приведенная выше, будет переведена компилятором в следующую программу в машинном коде:

001 READ,21; 008 JUMPGE,16; 015 JUMP,6;

002 LOADC,1; 009 LOAD,19; 016 LOAD,20;

003 STORE,19; 010 ADDC,1; 017 WRITE,0;

004 LOADC,1; 011 STORE,19; 018 HALT,0;

005 STORE,20; 012 LOAD,20; 019 BLOCK,3;

006 LOAD,19; 013 MUL,19;

007 SUB,21; 014 STORE,20;

Слева от директив выписаны соответствующие им адреса.