МАНИПУЛИРОВАНИЕ ЭЛЕМЕНТАМИ СТЕКА
Если вы начнете составлять пограмму на Форте, то очень ско-
ро почувствуете, что вам требуются слова, позволяющие произво-
дить различные действия с элементами стека. Представьте, напри-
мер, что при делении 60 на 11 вам понадобилось сохранить оста-
ток, а не частное. Слово /MOD засылает остаток в стек вторым
элементом, а брать из стека можно только верхний элемент. Для
удаления с вершины стека частного и перемещения туда остатка в
Форте имеется слово DROP:
MIN ( n 1 n 2 ==> n З)
Значением пЗ является
наименьшее из чисел nl и п2.
DROP ( n 1 ==> )
Удаление верхнего
элемента стека.
Значением пЗ является
наибольшее из чисел nl и п2.
Здесь по умолчанию принято, что числа nl и п2 имеют знак.
Для получения абсолютного значения числа служит слово:
Значением п2 является |nl| -
абсолютное значение числа nl.
2 DUP ( n 1 n 2 ==> n1 n 2 n 1 n 2)
|
Форт располагает и другими словами, выполняющими ариф-
метические операции, но и перечисленных здесь вполне достаточно
для понимания программ, приведенных далее в книге.
На уровне машинной реализации арифметические операции
Форта выполняются над числами в двоичном представлении (с ос-
нованием 2), однако имеется возможность вводить и выводить чис-
ла, представленные в других системах счисления, отличных от
двоичной и десятичной. Основание (или модуль) для представле-
ния числа задается значением системной переменной BASE. Если
ее значение равно 10 (что имеет место при инициализации Форт-
системы), то арифметические операции выполняются в десятичной
системе счисления. Для изменения основания на 16, т.е. перехода
в шестнадцатиричную систему счисления, предусмотрено слово
HEX, а для обратного перехода в десятичную систему - слово
DECIMAL. Например, перевод числа 20 из десятичной системы в
шестнадцатиричную записывается так:
HEX . 14
Удалить с вершины стека два элемента можно с помощью слова
Удаление двух верхних
элементов стека.
Иногда требуется скопировать верхний элемент стека. Это
позволяет сделать слово:
Создание дубля верхнего
элемента стека.
Дублирование двух верхних элементов стека выполняется словом:
Создание дублей двух верхних
элементов стека.
Обратите внимание, что слово 2DROP приводит именно к такому
результату, а не к (nl => nl nl nl), т.е. эта команда дублирует
два элемента стека, а не записывает один элемент дважды.
Иногда может потребоваться создать копию второго элемента
стека и поместить его на вершину. Это можно сделать с помощью
слова:
OVER ( n 1 n 2 ==> n 1 n 2 n 1 )
|
Создание копии второго
элемента и помещение его на
вершину стека.
122
123
Для того чтобы получить доступ ко второму элементу, можно
не создавать его копию, а просто поменять два верхних элемента
стека местами, это действие выполняет слово SWAP:
С помощью этих слов можно выполнять со стеком все операции,
которые потребуются для программирования задач искусственного
интеллекта.
SWAP ( n 1 n 2 ==> n 2 n 1 )
|
Меняет местами два верхних
элемента стека.
Теперь покажем, как с помощью введенных слов манипулиро-
вания элементами стека получить доступ к остатку от деления,
выполненного словом /MOD. Если полученный остаток уже нахо-
дится на вершине стека, то для его снятия нужно обратиться к
слову DROP, а затем переместить остаток на вершину словом
SWAP, т.е. нужно выполнить такую последовательность команд:
MOD SWAP DROP
Выполнение комбинации слов SWAP DROP приводит к выталкива-
нию из стека его второго элемента, поэтому данную комбинацию
целесообразно оформить как новое слово Форта:
: NIP SWAP DROP;
В дальнейшем мы будем использовать это новое слово, хотя оно и
не относится к числу стандартных. Определив слово NIP, мы тем
самым расширили множество слов, которые можно применять при
составлении программ.
До сих пор мы имели дело со словами, которые обращаются к
двум верхним элементам стека. Рассмотрим теперь слова, которые
выполняют действия с тремя верхними элементами (в словах PICK
и ROLL количество аргументов не ограничивается). Слово ROT
передвигает третий элемент на вершину стека, т.е. производит
ротацию или циклическую перестановку трех верхних элементов:
ROT (n1 n2 n З ==> n2 n З n1)
|
Перестановка nl на вершину
стека.
Действие, обратное этому, выполняется словом -ROT:
-ROT (n1 n2 n3 = => n З n1 n2)
|
Перемещение верхнего элемента
на третье место в стеке.
Наконец, иногда может оказаться полезной условная операция над
стеком:
Создание копии верхнего элемента стека, если им является не ноль.
Д ОСТУП К Д АННЫМ
Для чтения и записи (т.е. выборки и запоминания) данных в
памяти компьютера необходимы слова, реализующие операции до-
ступа к ней. Форт предоставляет возможность обращаться к памя-
ти, используя непосредственно внутренние адреса, аналогично
операторам РЕЕК и РОКЕ в Бейсике. Для доступа к данным, в
частности к переменным, используются слова, которые считывают
и запоминают их значения. Первое из них имеет такой синтаксис:
Заносит на стек число, нахо- дящееся в памяти по адресу addr (произносится " разыменовать" ).
|
@ ( addr ==> п)
Синтаксис второго слова:
! ( n addr ==> )
Записывает число п в область па-
мяти, начинающуюся с адреса
addr (произносится " присвоить" ).
В 8-разрядном компьютере числа Форта занимают 16 бит и под
каждое из них отводится два машинных слова. Порядок располо-
жения байтов (т.е. где находятся старшие разряды числа - по
адресу addr или addr+1) зависит от типа компьютера.
Введя слова доступа к памяти, можно выполнять действия с
переменными. Например, для перевода чисел в шестнадцатирич-
ную систему счисления необходимо переменной BASE присвоить
новое значение, равное 16. Это можно сделать следующим
образом:
16 BASE! ,
Однако если мы теперь разыменуем переменную BASE командой
BASE @
и напечатаем полученное значение, то все равно получим число
10. (Почему? ).
Иногда бывает необходимо выбрать значение области памяти
величиной в один байт, а не считывать все 16 бит, отведенных под
число. Это бывает нужно, например, для извлечения из памяти
символа, который в коде ASCII занимает один байт. Доступ к
символу осуществляется словами:
124
125
Замена адреса его содержимым
(произносится " с-разыменовать" ).
Значение старшего разряда числа,
находящегося на вершине стека,
равно 0.
Запись младшего разряда числа
по адресу addr (произносится " с-
присвоить" ).
Кроме указанных слов общего назначения в Форте имеются
слова для выполнения специализированных функций. Изменение
значения адреса производится словом
+! ( n add r ==> )
Добавление значения п к адресу
addr (произносится " плюс-прис-
воить" ).
Слово +! увеличивает значение адреса и может использоваться
при реализации цикла для увеличения на очередном шаге его
счетчика. Два других слова не входят в число стандартных слов
Форта, но тем не менее весьма полезны. Первое из них
Запись значения флага " истина" по адресу addr.
|
ON ( addr ==> )
Вторым является слово OFF ( addr ==> ) Запись значения флага ложь по адресу addr.
ФЛАГИ, ЛОГИЧЕСКИЕ ОПЕРАТОРЫ
И СРАВНЕНИЕ ЧИСЕЛ
В Форте-83 флаги (признаки) используются для фиксации ре-
зультатов проверок и принимают значения да/нет или исти-
на/ложь. Значение флага истина представляется числом -1, а
значение ложь - числом 0. Выбор для кодирования значения ис-
тина числа -1, а не 1 объясняется тем, что в машинной реализа-
ции числа -1 во всех битах стоят единицы. (В Форте арифметичес-
кие операции выполняются над числами, представленными в дво-
ичной системе счисления). В машинной реализации значения ложь
во всех битах находятся нули. В связи с этим в Форте оказалось
легко реализовать слово NOT, которое изменяет значение истина
на значение ложь и обратно. NOT - это булевская операция, кото-
рая выполняет логическое отрицание путем изменения значений
всех битов числа на противоположные:
Значением п2 является логи-
ческое дополнение значения nl.
Для любого бита в представлении значения nl верно следующее:
если в нем находится 1, то станет 0; если же в этом бите стоит 0,
то он будет заменен на 1. Точно так же изменяются машинные
представления значений флагов и при выполнении следующих ло-
гических операций:
AND ( n1 n2 ==> nЗ ) Значением пЗ является логичес-
кая конъюнкция nl и п2. В каж-
дом бите машинного представле-
ния пЗ будет находиться 1 только
в том случае, если в обоих соот-
ветствующих битах nl и п2 также
находятся единицы.
Значением пЗ является логичес-
кая дизъюнкция nl и п2. В каж-
дом бите машинного представле-
ния пЗ будет находиться 0 только
з том случае, если в обоих соот-
ветствующих битах nl и п2 также
находится 0.
Значением пЗ является результат
логической операции " исключаю-
щее или". В каждом бите машин-
ного представления пЗ будет на-
ходиться 1 только в том случае,
если в соответствующих битах nl
и п2 находятся противоположные
значения.
Введенные логические операции являются полезными при состав-
лении комбинаций признаков. Например, если потребуется флаг,
который истинен только при условии, что истинны оба флага flagl
и flag2, то его можно образовать, соединив последние логической
связкой AND.
При составлении программ необходимы средства для помеще-
ния значений флагов в стек. Вместо чисел 0 и -1, выражающих
значения флагов, лучше ввести средствами Форта логические
126
константы TRUE (истина) и FALSE (ложь), которые соответствуют
этим числам, - тогда программа будет легче читаться.
Слова, которые возвращают значения флагов, называются бу-1
левс к ими операциями, поскольку они принимают только два зна-
чения - истина и ложь. В Форте имеется несколько булевских
операций, позволяющих проводить сравнение чисел. Наиболее рас-
пространенными среди них являются следующие:
Если nl = n2, то f - истинно
(произносится " равно" ).
Если nl < n2, то f - истинно
(произносится " меньше, чем" ).
Если nl > n2, то f -истинно
(произносится " больше, чем" ).
Если nl не равно n2, то f -истинно (произносится " не равно" ).
Операции, которые сравнивают число с нулем., реализуются следу-
ющими словами Форта:
Значением f является истина,
если nl равно 0. _
Значением f является истина,
если nl меньше 0.
Значением f является истина,
если nl больше 0.
Флаги, вырабатываемые булевскими операциями, используь
ся управляющими словами для того, чтобы направлять вычис
ления в программе по той или иной ветви.
УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ
Итак, вы познакомились с арифметическими операциями
Форта, с действиями над элементами стека, доступом к данным,
находящимся в памяти, а также определением логических значе-
ний флагов и их комбинаций. С помощью слов, выполняющих эти
функции, можно составлять процедуры в виде определения через
двоеточие. Однако для написания серьезных программ необходимы
128
управляющие слова, которые позволяют принимать решения о
том, какой оператор будет выполняться следующим. Форт базиру-
ется на управляющих конструкциях структурного программиро-
вания. Слова Форта состоят из фрагментов, оформленных в виде
модулей, каждый из которых получает и передает управление
через свои точки входа и выхода.
На рис. 6.3 приведен пример неструктурированной програм-
мы, а на рис. 6.4 для сравнения показаны управляющие конст-
рукции языка Форт, представленные в виде отдельных модулей.
Обратите внимание на то, что каждая конструкция имеет единст-
венный вход и единственный выход. (Из этого правила имеются
только два исключения - оператор LEAVE (выйти) в цикле DO,
который мы не будем использовать, и прерывание программы из-за
ошибки. Оператора GOTO в Форте нет.)
На рис. 6.4А и 6.4В проиллюстрированы основные способы
ветвления программ. Конструкция ELSE может быть опущена.
Приведенные структуры в обозначениях языка Форт записываются
в виде следующих выражений: