Язык программирования Форт


в этой книге, не являются


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

  1. тренировке,
  2. углублению понимания принципов, изложенных в этой книге,
  3. развитию техники программирования,
  4. иногда определению слов широкого практического применения.

Вы должны попытаться проделать все упражнения, но, если у вас возникнут затруднения, не стесняйтесь заглянуть в ответы : некоторые задачи бросают вам вызов. Упражнения также помогут вам продвигаться в изучении языка. Мы предлагаем серию упражнений после часа-двух интенсивного изучения текста. Наконец, попробуйте сами придумать собственные упражнения, связанные с вашими личными интересами. Один из лучших способов изучения какого-либо языка программирования -- писать собственные упражнения и программы.
  • Определите в уме, что будет выведено на экран следующими операциями:

    1. 20 2 / .
    2. 2 20 / .
    3. 1 2 3 * * .
    4. 3 2 1 + / .
    5. 100 5 DUP * / .

  • Преобразуйте следующие выражения в обратную постфиксную форму:

    1. 1 * 2
    2. 1 * 2 / 2
    3. 1 + 2 / 3
    4. (1 + 2) / 3
    5. 3 / (2 + 1)
    6. (3 + 4) / (2 + 1)

  • Опишите слово POWER4 для возведения числа в четвертую степень, используя слово CUBE.
  • Опишите слово NEWPOWER4 (возведение_в_четвертую_степень) используя слово SQUARE вместо CUBE.
  • Согласно теореме Пифагора квадрат гипотенузы прямоугольного треугольника равен сумме квадратов прилежащих сторон. Определите слово PYTHAGORUS для определения квадрата гипотенузы по заданным в стеке длинам его сторон. Вам может потребоваться слово SWAP (переставить), которое переставляет между собой два числа, находящиеся на верху стека. Так, например,
    4 5 SWAP
    оставит два верхних числа:
    5 4
  • Определите слово AREA (площадь), которое должно вычислять площадь круга, помноженную на 100, если задан радиус. Используйте число 314 вместо значения числа Пи, помноженного на 100.
  • Используя слово AREA, определите слово VOLUME (объем) для вычисления объема цилиндра, помноженного на 100. В стеке должны лежать значения радиуса -- на вершине и значение высоты цилиндра вторым сверху. Переделайте VOLUME в XVOLUME, которое ожидает данные из стека в обратном порядке (высота цилиндра -- на вершине, радиус -- вторым сверху). Какая программа имеет большую эффективность (с точки зрения быстродействия) ?




    Мы собираемся предложить вам модифицировать нашу графическую программу. Проще всего заниматься этим, если вы запишете ее на диск, а затем отредактируете, чтобы внести изменения по условиям упражнения. Форт-система обычно сохраняет программы на дискетах в нумерованных блоках емкостью 1024 символа в каждом, что соответствует размеру экрана (16 строк по 64 символа). Поскольку разные версии Форта отличаются способами хранения и редактирования блоков на диске, рекомендуем обратиться к документации на вашу Форт-систему, чтобы узнать, как сохранить программу на диске. Для того чтобы ввести копию программы на диск, вы будете набирать ее на клавиатуре и пользоваться редактором. Затем программу можно будет загрузить, если ввести номер блока и после него слово LOAD (загрузить), например
    68 LOAD
    Эта команда вызовет интерпретацию слов, которые с помощью редактора были записаны на диск, так же, как если бы их вводили с клавиатуры. Компьютер не знает и ему безразлично, откуда производится ввод, с клавиатуры или из блока на диске. Большое преимущество этого состоит в том, что можно модифицировать или редактировать программу на диске, не вводя ее каждый раз целиком с клавиатуры. Старую скомпилированную программу можно забыть (т.е. удалить ее из памяти ЭВМ), если ввести FORGET TASK перед вводом измененной программы словом LOAD. Если вы пока не хотите обременять себя изучением редактора, можете каждый раз вводить программу с клавиатуры. Но нельзя просто ввести скорректированное определение какого-либо слова с клавиатуры, если оно входило в определение какого-либо последующего слова. Дело в том, что это последующее слово было скомпилировано раньше совместно со старым определением скорректированного вами слова. В мы подробно обсудим разные редакторы и ввиду того, что многие редакторы, поставляемые с Форт-системами, достаточно примитивны, мы предложим вам редактор, который, возможно, понравится больше. Однако вам все же придется научиться пользоваться редактором вашей Форт-системы хотя бы только для того, чтобы ввести редактор, описанный в .



      Прежде чем двигаться дальше, вы должны освоить применение Форта в качестве калькулятора. И не столько для того, чтобы освоить арифметические операции, сколько для того, чтобы научиться прослеживать состояние стека в уме.

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

        1. 5 + 5 + 5
        2. 5 4
        3. (5 + 5) х 5
        4. (5 + 5) / 5
        5. 0.5 х (5 + 5)
        6. 10 / (5 + 5) (наши числа целые ... найдите выход)
        7. (5 + 4) / (5 + 5)
        8. 5х5+5х4+4х4
        9. (5 + 4) х (5 + 4)
        10. (5 + 4)^2

      2. Проделайте примеры из упражнения 1 по-другому, т.е. перестроив числа и операторы.
      3. Раскрывая алгебраическое выражение, нужно начать с выражения в скобках, которое находится в самой глубине этого выражения. Опишите последовательность, в которой вы будете делать вычисление следующего выражения:
        16 х (2 х ((3 + 5) / 4)) = ?
        Например, первой операцией должно быть сложение 3 и 5. Теперь переведите вашу последовательность действий в постфиксную форму и найдите решение на Форте. Вы убедитесь, что постфиксная форма не приводит к неопределенности.
      4. Оцените значение следующих выражений, как вы это делали в упражнении 3.

        1. (2 + (5 х (9 + 3) / 6)) 32 =?
        2. (32 х (2 х (3 х (5 + 6) х 3))) = ?
        3. 2 х ((22 х (5 + 4)) + (2 + 5 х 10))) = ?

      5. Рассмотрим пример из упражнений 1 и 2. Скорее всего, вы решали его следующим образом:
        5 4 + 5 4 + *
        Как вы уже знаете, имеется слово DUP, которое делает копию числа, находящегося на вершине стека, т.е.
        4 3 DUP
        приводит к тому, что в стеке останется
        4 3 3
        Можете ли вы сделать упражнение, используя DUP и вводя только по одному разу числа 5 и 4 ? Можете ли вы использовать слово DUP в остальных упражнениях ? Слова для манипуляций в стеке очень полезны, они упрощают операции, экономя время и память.



      Они могут показаться вам вначале очень простыми, но потом будут усложняться. Если даже они покажутся вам скучными, пожалуйста, проделайте их. Одной из самых важных компонент изучения Форта является освоение работы со стеком настолько, чтобы вы чувствовали себя с ним комфортно, а слова, связанные с манипуляциями в стеке, стали бы вашей второй натурой. Затраченное вами время сторицей окупится впоследствии.

      1. Напишите слово или слова, с помощью которых содержимое стека изменялось бы в соответствии с заданием. Стараи тесь обойтись минимумом слов. (Мы пользуемся здесь буквами вместо чисел, чтобы у вас возникла уверенность, что эти при меры пригодятся и в более общих ситуациях.)
        До После До После До После (а) а b b а (б) а b а b b (в) а b а b а (г) а b а а b (д) а b b b а (е) а b с b с а (ж) а b с а с b (з) а b c с b а (и) а b с b а с (к) а b c с а b (л) а b c а b b c (м) а b с а а b с (н) а b а а b b (о) а b c а а b b с с
      2. Принимая содержимое стека таким, как показано, напишите слово или слова для вычисления выражений. Снова ста райтесь обойтись минимальным количеством слов.
        Стек Выражение Стек Выражение (а) а b ab (б) а b ab^2 (в) а b2 а + b (г) а b а b (д) а b a^2b^3 (е) а b а(а + b) (ж) a b a^2+2ab+b^2 (указание: разложите на множители) (з) а b с (а + b)/с (и) а b с (a+b)/(b+c) (к) а b с (а+с)/(b+с) (л) а b c (a+b)/(2c) (м) а b c а/(2с)+Ь/(2с) (н) а b с (b-a)(b-c) (о) а b c d ab+ac+ad (п) a b c d ab+abcd
        Не применяйте ROLL и PICK !
      3. Напишите новое определение слова OVER (NEWOVER), используя другие слова.
      4. Слово 2DUP выполняет следующие операции в стеке :
        ( n1 n2 - n1 n2 n1 n2 )
        Оно применяется для чисел двойной длины. Напишите определение этого слова под именем NEW2DUP, используя для этого только два слова.
      5. Определите слова DUP и OVER, используя PICK. Проделайте это для обоих стандартов. Дайте этим словам новые имена во избежание путаницы.
      6. Определите ROT, используя слово ROLL. Проделайте это для стандартов Форт-79 и Форт-83. Дайте этому слову новое имя.
      7. Слово 2SWAP выполняет в стеке следующие операции:
        ( n1 n2 nЗ n4 - nЗ n4 n1 n2).
        Определите это слово на Форт-79 и Форт-83.
      8. Определите слово ROTSTACK, которое производило бы ротацию элементов стека независимо от его длины. Если в стеке находится а Ь с d e f, то после исполнения ROTSTACK в нем должно быть Ь с d e f а. Используйте для этого только два слова. Проделайте это на Форт-79 и Форт-83.
      9. Объем сферы выражается формулой 4/ЗПи * r^3. Напишите слово для определения объема, умноженного на 100, если в стеке задано значение r. (Указание: используйте число Пи = 3.14, умножив его на 100.)
      10. Определите слово, помещающее в стек произведение двух самых нижних чисел в стеке, не разрушая содержимого стека. Все, что вам известно : в стеке находятся два или более числа. (На практике вы не должны допускать разрастание стека, чтобы не приходилось делать что-либо подобное.)
      11. Слово MOD дает остаток от деления нацело, т.е. 11 3 MOD выдает в результате 2. Дайте определение слова MOD.



    1. Используйте .NUMS со следующими числами: 1,3,7,15,31,63,127 и 255. Подметили ли вы общий рисунок ? Какая зависимость существует между числом 2, возведенным в целую степень, и двоичным представлением ?
    2. Теперь проделайте то же самое с числами 2,4,8,16,31,64,128 и 256. Видите ли вы, почему шестнадцатеричное представление удобно для работы с байтами ?
    3. Перейдите в двоичную систему и введите восьмиразрядное число с единицами во всех разрядах. Используйте .NUMS. Вы снова сможете убедиться в удобстве шестнадцатеричной системы. Проделайте это упражнение для 16-разрядного числа. Вернитесь к десятичному основанию.
    4. Перейдите к основанию 16 и введите 1 плюс шестнадцатеричное число, которое эквивалентно байту со всеми единицами в разрядах. Возведите это число в квадрат и выведите его словом .NUMS. Сколько используется разрядов ? Почему ? Подумайте еще раз, почему удобна шестнадцатеричная система ?
    5. Определите слова HEX, OCTAL и BINARY.
    6. Понятно ли вам, почему, если вы хотите использовать шестнадцатеричные числа, недопустимо давать имена такого типa: АА, А4, FF и т.д. и в то же время имя GG будет приемлемым ?

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


  • Подберите маску и подходящее слово для того, чтобы изменить приведенные числа, как показано в таблице. Не используйте XOR, если есть более простое решение.
    Исходное Преобразованное Исходное Преобразованное число число число число (а) 10101011 10100011 (е) 10101111 00001111 (б) 10100011 10100111 (ж) 10100000 00001111 (в) 10100011 00000000 (з) 10101010 01010101 (г) 10100011 11111111 (и) 11110000 00001111 (д) 10101111 10100000
  • Опишите слово для преобразования любого слова, находящегося на вершине стека, в "О".
  • Слово = (во всех версиях, кроме Форт-83) возвращает единицу, если два верхних числа в стеке равны. Иначе оно возвращает "0". Определите слово =. (Совет: нужно дважды использовать XOR, один раз с маской и также /.)
  • В некоторых версиях Форта слово о возвращает 1, если два верхних числа не равны, и 0 в противном случае. Определите слово о двумя способами: с использованием слова - и без него.
  • Опишите в Форт-83 слово NOT под именем NOT1, используя XOR. Опишите его, используя -.
  • Опишите слово, которое, если дана маска с определенными установленными в "1" разрядами, возвращает 1 в соответствующих разрядах второго сверху числа в стеке, если их значение равно 1 и 0 в противном случае. (Совет: используйте слово = из упражнения 3).
  • Опишите слово, которое, если задана маска с определенными разрядами, установленными в "I", будет возвращать 1 соответствующих разрядах второго сверху числа, если они равны 0, и 0 в противном случае.
    Приемы, использованные в упражнениях 6 и 7, могут быть полезны для проверки состояния разрядов памяти, например для проверки того, включен ли принтер.


    Убедитесь в том, что слово .BIN находится в вашей системе. Если это не так, снова введите ею (см. выше). Определи те новое слово, которое печатает двоичные числа без знака следующим образом :
    : U.BIN DUP BASE @> 2 BASE ! SWAP U. BASE ! ;
    (В чем различие между .BIN и U.BIN?)

    1. Напишите одно слово, которое показывает число, находящееся на вершине стека в виде десятичного со знаком, десятичного без знака, двоичного со знаком и двоичного без знака.
    2. Используйте слово U.BIN для того, чтобы подготовить на экране таблицу приведенных ниже чисел, показывая их и виде чисел со знаком и без знака в двоичной и десятичной системе 1, 2, 3, 32766, 32767, 32768, 32769, 65533, 65534, 65535.
    3. Глядя на таблицу из упражнения 2 (и если нужно, проведя дополнительные эксперименты), напишите алгебраической выражение для преобразования отрицательных чисел в диапазоне -1 - 32768 в положительные числа, которые выводятся с помощью слова U.
    4. Еще раз, просматривая таблицу из упражнения 2, напишите слово, которое будет менять знак числа, находящегося и стеке, не используя -, а с помощью операций над битами (вы уже описали слово NEGATE). Как это связано с дополнением исходного числа по модулю два?
    5. Используя результаты упражнения 4 и операцию +, напишите определение слова - для выполнения вычитания.



  • Определите слово . LSB для печати младшего байта числа, находящегося в стеке. Не используйте PAD и С@. (Подсказка: какое значение старших восьми разрядов должно иметь число в стеке перед операцией . ? Как установить эти разряды в 0 ?)
  • Определите слово .MSB для печати старшего байта положительного числа, находящегося в стеке. (Совет: вспомните, что к старшему байту числа добавляется 1 каждый раз, когда к нему прибавляется 256, и что оператор / производит округление с уменьшением.)
  • Переопределите .LSB, пользуясь методом определения .MSB. (Указание: вы должны применить DUP к числу, находящемуся в стеке, и, кроме того, SWAP и -.)
  • Дайте новое определение .LSB и .MSB под именами .LSB2 и .MSB2, используя PAD и С@. Очень часто одно и то же можно на Форте сделать разными способами. Наилучший метод -- это обычно компромисс между требуемыми ресурсами памяти и временем исполнения. Какое из определений .LSB и .MSB будет самым быстрым ?
  • Напишите слово для деления числа без знака, находящегося на вершине стека, на 256, не используя для этого никаких чисел.
  • Напишите слово для добавления числа 256 к числу на вершине стека путем прибавления 1 к чему-то.


    Наиболее удобно ( и быстро) коды ASCII преобразуются с помощью операций над отдельными битами, с которыми вы уже знакомы. Обратитесь к и для справки о значениях разрядов, которые нужно преобразовать в приводимых заданиях.

    1. Напишите слово, которое меняет любой код больше 127 на код меньше 127, но не влияет на код меньше 127. (Совет: измените один разряд из "1" в "0".)
    2. Напишите слово для преобразования любого управляющего кода в печатный символ. Сделайте это двумя способами: с помощью поразрядных операций и с помощью сложения.
    3. Напишите слово для преобразования символов нижнего регистра в символы верхнего регистра.
    4. Напишите слово, которое делает обратное преобразование.
    5. Напишите слово, которое позволяет выдать в стек адрес памяти, а затем печатает символ ASCII, который находится по этому адресу.
    6. Напишите слово, которое снимает символ с клавиатуры и помещает его по адресу, который выдает в стек слово PAD.


    Содержание раздела