ПАСКАЛЬ "НР4Т"
1. ВВЕДЕНИЕ
НАЧАЛО РАБОТЫ.
Паскаль НР4Т - это быстроработающая, мощная и легкая в исполь-
зовании версия широкоизвестного языка ПАСКАЛЬ. Она имеет следующие
основные отклонения от базовой версии:
- не реализован тип ФАЙЛ, хотя переменные могут выгружаться на
ленту;
- тип ЗАПИСЬ не может иметь ПЕРЕМЕННУЮ часть;
- ПРОЦЕДУРЫ и ФУНКЦИИ не могут быть параметрами.
Для того, чтобы использовать различные возможности по
аппаратному обеспечению при работе компилятора, введены
дополнительные функции. Среди них: POKE, PEEK, TIN, TOUT, ADDR.
Компилятор занимает приблизительно 12К памяти, а
"пристегиваемые" к объектному коду процедуры (пусковые процедуры)
4К. Вся связь между НР4Т и компьютером, на котором производится
работа, выполняется через вектора, размещаемые в начале пусковых
процедур, что упрощает пользователю написание при необходимости
своих собственных процедур ввода/ вывода.
Паскаль НР4Т применяет много управляющих кодов, особенно в
редакторе. Разумеется, различные компьютерные системы могут иметь
различное устройство клавиатуры и потому реализовать различные
способы введения управляющих кодов. В данной инструкции мы
используем следующие обозначения: RETURN, СС, СН, CI, CP, CS, СХ
(см. раздел "Указания по работе с ПАСКАЛЕМ НР4Т на компьютерах
ZX-Spectrum").
В то время, когда НР4Т ждет ввода строки, они могут быть
использованы следующим образом:
RETURN - для завершения строки
СС - возврат в редактор
СН - стирание последнего набранного символа
CI - переход к следующей позиции TAB
CP - прямая выдача на принтер (если это возможно) или, если
вывод на принтер уже идет - передача вывода на экран
СХ - стирание всей набранной строки.
К пакету прилагается также небольшой загрузчик с тем, чтобы
пользователь мог загружать с ленты данные, выгруженные туда в форма-
те НР4Т.
Так, чтобы загрузить компилятор и пусковые процедуры,
пользователь должен сначала загрузить загрузчик, который
поставляется в формате, пригодном для загрузки операционной системой
компьютера. Если же пользователь не может воспользоваться для
загрузки операционной системой компьютера, то в память напрямую
должен быть введен стартовый загрузчик, выполненный на АССЕМБЛЕРе
или на каком-либо из языков высокого уровня, например, на БЕЙСИКе.
После того, как загрузчик отработает, он начнет искать на ленте
файл, записанный в формате НР4Т. После того, как такой файл будет
найден, он будет загружен в память компьютера. Если же при загрузке
будет выявлена ошибка, на экране появится соответствующее сообщение
и Вам надо перемотать ленту и попытаться повторить загрузку. Если
ошибки повторяются, подрегулируйте уровень громкости Вашего магнито-
фона, а если и это не поможет, постарайтесь воспользоваться другой
копией программы.
После того, как компилятор будет успешно загружен, на экране
появится сообщение: TOP OF RAM?
Это запрос о верхней границе памяти компьютера. В ответ Вы
должны либо ввести положительное десятичное число до 655 3 5 и нажать
RETURN или просто нажато RETURN.
Если Вы ввели число, то оно принимается в качестве RAMTOP+1,
т.е. в качестве первого байта, не входящего в область RAM. Сюда
помещается стек компилятора и, таким образом, Вы можете
резервировать верхнюю область памяти, например, для расширений
компилятора. Это делается преднамеренной подачей числа, меньшего чем
физическая вершина ОЗУ компьютера. Обычно в ZX Спектруме вершина RAM
является началом области графики пользователя (UDG).
Следующий запрос: TOP OF RAM FOR МТМ?
Здесь Вы также можете ввести десятичное число или дать ответ
RETURN, тогда величина будет принята по умолчанию. То значение,
которое Вы введете, будет взято в качестве адреса стека при
исполнении результирующего объектного кода после команды -редактора
'Т' (см. детали в разделе 5). Стек пусковых процедур не должен
совпадать с вершиной RAM, если, например, Вы написали расширение для
пусковых процедур и хотите поместить его в безопасное место в
верхних областях памяти.
И, наконец, последний запрос: TABLE SIZE?
То, что Вы введете, будет принято в качестве объема памяти,
отведенного для таблицы символов компилятора.
Здесь также можно дать положительное целое число с последующим
RETURN или просто RETURN. В последнем случае будет введено число,
равное объему свободной памяти, деленному на 16. Почти во всех
случаях это обеспечивает достаточный размер таблицы символов. В то
же время, таблица символов не должна выходить за пределы адреса
32768. Если же Вы зададите такой размер, что это требование будет
нарушено,то запрос будет повторен.
Перед числом Вы можете в этом ответе поставить букву "Е". Если
Вы это сделаете, то внутренний редактор не будет задействовован и Вы
сможете, например, использовать с компилятором свой собственный
редактор.
После этого компилятор вместе с редактором (если он
задействован) перемещается в конец таблицы символов и управление
передается назначенному редактору.
ПРИМЕЧАНИЕ: Начиная с этого места в методических указаниях
будет использован знак "#" (хэш) перед всеми
числами в шестнадцатиричной форме.
КОМПИЛЯЦИЯ И ЗАПУСК.
Подробности того как создавать, изменять, компилировать и
запускать программы, используя встроенный редактор, см. в разделе 5.
После того, как он начнет работать, компилятор выдает следующее
сообщение:
ХХХХ NNNN text of source line, где
XXXX - адрес начала кода, генерируемого этой строкой;
NNNN - номер данной строки с ведущими нулями.
Если строка содержит более 80 символов, то компилятор вставляет
символы перехода к новой строке.
При необходимости листинг может быть отправлен на принтер путем
применения опции "Р" (см.раздел 4).
Вы можете остановить листинг, нажав CS, если после этого нажать
СС, то вернетесь в редактор, а нажатие любой другой клавиши -
возврат в листингу.
Если во время компиляции происходит ошибка, выдается сообщение
"ERROR" с последующей стрелкой, которая указывает на позицию после
символа, при генерации которого ошибка произошла. Появляется также
номер ошибки (см. Приложение 1). Листинг прекращается. Нажмите "Е",
чтобы вернуться в редактор для редактирования изображаемой на экране
строки; "Р" - для возврата к предыдущей строке; любую другую клавишу
- для продолжения компиляции.
Если программа неправильно завершается (например, без END), то
появится сообщение: NO MORE TEXT - и управление будет передан®- в ре-
дактор.
Если компьютер выходит за пределы пространства, отведенного для
таблицы, то появляется сообщение NO TABLE SPACE и управление переда-
ется редактору. В этом случае надо выгрузить программу на ленту, пе-
резагрузить компилятор и назначить новый (больший) размер таблицы.
Если компиляция завершается нормально, но в ее процессе были
обнаружены ошибки, то на экране появляется сообщение о количестве
ошибок и объектный код уничтожается. Если же все прошло успешно, то
появляется сообщение RUN? Если Вы хотите немедленно проверить Вашу
программу на исполнение, нажмите Y, - в противном случае управление
передается редактору.
В процессе прогона объектного кода пусковые процедуры также
могут генерировать сообщения об ошибках (см. Приложение 1). Вы
можете приостановить работу откомпилированной программы нажатием CS
с последующим СС для прерывания или любой другой клавишей для
продолжения работы.
ЖЕСТКОЕ ЗАДАНИЕ ТИПОВ.
Различные языки программирования имеют в своем распоряжении
средства для того, чтобы удостовериться правильно ли, в соответствии
ли со своим назначением, пользователь применяет те или иные элементы
данных.
С одной стороны стоят машинные языки, в которых не выполняется
никаких проверок ТИПА переменных, к которым обращается пользователь.
Существует такой язык как "TINY PASKAL", в котором данные
символьные, целые и логические могут свободно перемешиваться без
генерации каких-либо ошибок. Далее идет БЕЙСИК, который различает
числовые и символьные переменные и иногда целые или действительные
(например, знак "%" может обозначать целые). С другой стороны стоит
ПАСКАЛЬ, который доходит до того, что позволяет вводить типы данных,
заданные пользователем. И, наконец, язык АДА, в котором могут быть
определены даже различные, не совместимые между собой, числовые
типы.
ПАСКАЛЬ реализует два основных подхода в задании ТИПа. Это
структурное соответствие и именное соответствие. НР4Т использует
именное соответствие для ЗАПИСЕЙ и МАССИВОВ. Например, две
переменных заданы следующим образом:
VAR A:ARRAY ['А'..'С'] OF INTEGER;
В:ARRAY ['А'..'С'] OF INTEGER;
Можно подумать, что возможно выражение вида А:=В, но оно даст
сообщение об ошибке (ERROR 10), поскольку в задании типов были
сформированы два различных типа записей. Другими словами,
пользователь не сделал ничего, чтобы указать, что А и В представляют
данные одинакового типа. Это можно было бы сделать так:
VAR А,В: ARRAY['А'..'С'] OF INTEGER;
Теперь можно свободно присваивать А значение В и наоборот,
поскольку это данные одного ТИПа.
Хотя, на первый взгляд, такой подход, связанный с именным
соответствием кажется несколько сложным, в итоге он ведет к
уменьшению программистских ошибок, так как требует некоторого
предварительного размышления.
2. СИНТАКСИС И СЕМАНТИКА.
ИДЕНТИФИКАТОРЫ.
В качестве значащих принимаются только первые 10 символов иден-
тификатора .
Идентификаторы могут содержать буквы верхнего или нижнего
регистров. Нижний регистр не конвертируется в верхний, поэтому
идентификаторы HELLO, Hello, hello - различные. Зарезервированные
слова и предварительно определенные идентификаторы можно вводить
только в верхнем регистре.
ЦЕЛОЕ БЕЗ ЗНАКА.
ЧИСЛО БЕЗ ЗНАКА.
Целые числа по абсолютной величине не должны превышать 32767.
Более крупные числа рассматриваются как действительные. Мантисса
действительного числа имеет длину в 23^ бита. Поэтому точность
порядка 7 значащих цифр. Заметьте, что* точность теряется, если
результат вычисления намного меньше, чем абсолютные значения
аргументов. Например: 2.00002-2 - это совсем не 0.00002. Это
возникает в связи с потерей точности при представлении десятичных
дробей двоичными дробями.Этого не происходит при работе с целыми
числами, т.е. 20002-20000=2 (точно).
Наибольшее возможное действительное число - 3.4Е38, а
наименьшее - 5.9Е-39.
Нет никакого смысла задавать более 7 цифр в мантиссе, поскольку
остальные цифры будут все равно проигнорированы.
Если для Вас точность расчетов является критической, то
избегайте использование ведущих нулей, т.к. они рассматриваются как
значащие цифры. Т.е. 0.00012 3456 представляется менее точно, чем
1.23456Е-4.
Могут использоваться шестнадцатиричные числа. Обратите
внимание, что после знака "#" должна быть хотя бы одна цифра, иначе
будет выдано сообщение об ошибке (ERROR 51).
КОНСТАНТА БЕЗ ЗНАКА.
КОНСТАНТА БЕЗ ЗНАКА.
Символьные переменные могут иметь более 2 55 символов. Их ТИП
ARRAY[1..N] OF CHAR, где N - число в диапазоне от 1 до 255
включительно. Символьные переменные не должны содержать символ
"конец строки" (CHR(13)). Если это происходит, выдается сообщение
ERROR 63.
Разрешенные символы - полный набор кодов ASCII. Для обеспечения
совместимости со стандартным ПАСКАЛем нулевой символ можно
представлять только как CHR(O).
КОНСТАНТЫ.
Здесь имеется нестандартная конструкция (остальные - как
обычно).
Такая конструкция нужна для того, чтобы константами можно было
задавать управляющие коды. В этом случае постоянная в скобках должна
быть целого ТИПа.
Пример: CONST bs=CHR(10);
cr=chr(13);
ПРОСТОЙ ТИП.
ПРОСТОЙ ТИП.
Скалярные перечислимые типы не могут иметь более 256 элементов.
ТИП.
ТИП.
Зарезервированное слово РАСКЕ (упакованный) - принимается, но
игнорируется, т.к. упаковывание массивов производится само собой,
например, для символьных переменных и др. Единственным случаем,
когда упаковывание массивов является предпочтительным - при работе с
массивами логических переменных, но их более естественно выражать
типом SET (множество).
ПАССИВЫ И МНОЖЕСТВА.
Базовый тип множества может иметь до 256 элементов. Это
позволяет объявлять множество символов или множество любых
перечислимых заданных пользователем типов. Заметьте, однако, что для
целых чисел возможно использование в качестве базового типа только
подмножества. Все подмножества целых чисел воспринимаются как
множества (О...255).
Разрешаются массивы массивов, массивы множеств, записи множеств
и т.п.
МАССИВЫ считаются эквивалентными, если их объявление
выполнялось в одном зарезервированном слове ARRAY. Так, следующие
типы эквивалентны.
tablea=ARRAY[l..100] OF INTEGER;
tableb=ARRAY[l..100] OF INTEGER;
Поэтому переменная tablea не может быть присвоена переменной
tableb.
Это позволяет отыскивать ошибки, когда, например, пытаются
переприсвоить две таблицы, представляющие различные типы данных. Это
ограничение не действует на массивы символьных данных, поскольку они
всегда содержат данные одного типа.
УКАЗАТЕЛИ.
НР4Т разрешает создание динамических переменных применением
стандартной процедуры NEW (см. раздел 3). К динамическим переменным
в отличие от статических (которые имеют закрепленное за ними при
объявлении место в памяти) нельзя обратиться по идентификатору, т.к.
они его не имеют; вместо него используется переменная-указатель.
Переменная-указатель является статической переменной и содержит
адрес динамической переменной. Обращение к динамической переменной
выполняется включением символа после переменной-указателя.
Примеры применения переменных-указателей имеются в Приложении 4.
На использование переменной-указателя в ПАСКАЛЕ НР4Т имеется
ряд ограничений.
1. Не разрешены переменные-указатели к типам, которые еще не
объявлены. В то же время, это не запрещает использование
конструкций, имеющих структуру закольцованного списка, в котором
определение ТИПа может содержать переменную-указатель к самому этому
типу, например:
TYPE
item=RECORD
value: INTEGER;
next:"item
END;
1ink=~item;
2. Переменные-указатели к переменным-указателям не разрешены.
3. Переменные-указатели к одному и тому же ТИПУ рассматриваются
как эквивалентные.
VAR
first: link;
current:"item;
Переменные FIRST и CURRENT - эквивалентны (в данном случае
используется структурная эквивалентность) и их можно присваивать
одну другой и взаимно сравнивать.
4. Существует предварительно заданная константа NIL и когда она
присваивается переменной-указателю, то предполагается, что последняя
не содержит адреса.
ЗАПИСИ.
Наличие ЗАПИСЕЙ (структурированных переменных, составленных из
фиксированного числа полей) соответствует стандартному ПАСКАЛю.
Исключением является то, что не поддерживается переменная часть
списка полей.
Две ЗАПИСИ рассматриваются как эквивалентные только если их
объявление происходило при одном появлении зарезервированного слова
RECORD. (См. раздел 2. выше).
Для доступа к различным полям внутри записи в компактной форме
выражения может применяться оператор WITH.
См. Приложение 4 для примеров использования WITH.
СПИСОК ПОЛЕЙ.
ПЕРЕМЕННАЯ.
ПЕРЕМЕННАЯ.
НР4Т поддерживает два типа переменных - статические и
динамические. Статические переменные объявляются как VAR и им
отводится место в памяти на все время исполнения блока, в котором
они определялись.
Динамические переменные, в свою очередь, создаются при работе
программы с помощью оператора NEW. Они не объявляются и к ним нельзя
обращаться через идентификатор. К ним обращаются косвенно через
статическую переменную-указатель, которая содержит адрес
динамической переменной.
Подробности см. в разделах 2 и 3, а примеры в Приложении 4.
При работе с многомерными массивами программист не обязан
использовать при обращении ту же самую спецификацию индексов, какая
была при объявлении массива (это отличие от 3-й версии ПАСКАЛЯ фирмы
HISOFT). Например: Если переменная объявлялась как
ARRAY[1..10] OF ARRAY[1..10] OF INTEGER
то к первому элементу этого массива можно обращаться либо как
а [ 1 ] [1 ] , либо как а[1,1].
ТЕРМ
ТЕРМ
Нижняя граница множества - всегда нуль. Размер множества всегда
равен максимальному размеру базового множества. Так, множество
символов всегда занимает 32 байта (возможны 256 элементов - по
одному биту на каждый элемент). Кроме того, SET OF 0..10
эквивалентно SET OF 0..255.
ВЫРАЖЕНИЕ.
Простое выражение можно представить в следующем виде:
На базе простого выражения в общем виде диаграмма выражения бу-
дет следующей:
При использовании IN атрибуты множества могут быть любыми как
для типа ПРОСТОЕ ВЫРАЖЕНИЕ, за исключением целых аргументов, для
которых атрибуты берутся так, как будто было установлено [О..255].
При сравнении множеств может использоваться не весь набор
знаков из синтаксической диаграммы, а только >=,<=,<>, или =.
Указатели можно сравнивать только через = или о.
СПИСОК ПАРАМЕТРОВ.
Процедуры и функции не могут быть параметрами.
За идентификатором типа должно стоять двоеточие, иначе будет
сообщение об ошибке ERROR 44.
ОПЕРАТОР.
Ниже приведены ограничения на использование отдельных
параметров.
Оператор CASE.
Оператор CASE может завершаться не только END, но и
конструкцией ELSE <выражение>.
Не разрешается нулевой список CASE. Например, CASE OF END даст
сообщение об ошибке ERROR 13.
Опция ELSE является альтернативой END и выполняется, если
переключатель не найден в списке CASE.
Если используется терминатор END, а переключатель не найден, то
дальнейшее управление передается оператору, следующему за END.
Оператор FOR.
Управляющая переменная оператора FOR может быть только
неструктурированной переменной и не параметром.
Оператор GO ТО.
По этому оператору возможен переход только к метке, находящейся
в этом же блоке.
Метки должны быть объявлены с помощью зарезервированного слова
LABEL в том же блоке, в котором они используются. Метка состоит из,
по крайней мере, одной цифры и до четырех. Метка, стоящая при
операторе, должна стоять перед ним и отделяться двоеточием.
БЛОК.
ПРОЦЕДУРА может содержать (или не содержать) дополнительный
оператор FORWARD. Если он есть, то вставляется после списка
параметров, отделяясь он него точкой с запятой.
Процедуры и функции могут УПОМИНАТЬСЯ до того, как они были
объявлены. Это выполняется с помощью зарезервированного слова
FORWARD. Например:
PROCEDURE а(у:t); FORWARD;
PROCEDURE b(x:t);
BEGIN
a(p);
END;
PROCEDURE a:
BEGIN
b(q);
END;
Заметьте, что тип параметров и результата процедуры объявляются
оператором FORWARD и не повторяется в основном объявлении процедуры.
Помните, что FORWARD - зарезервированное слово.
ПРОГРАММА.
Синтаксическая диаграмма:
Поскольку файлы не задействуются, то формальные параметры здесь
отсутствуют.
3. ПРЕДВАРИТЕЛЬНО ЗАДАННЫЕ ИДЕНТИФИКАТОРЫ.
КОНСТАНТЫ.
HAXINT - наибольшее доступное целое, т.е. 32767.
TRUE, FASLE - логические константы.
ТИПЫ.
INTEGER - СМ. разд. 2.3
REAL - см. разд. 2.3
CHAR - полный расширенный набор ASCII из 2 56 элементов.
BOOLEAN -' (TRUE, FALSE) ; этот тип используется в
логических операциях, включая и результаты сравнения.
ПРОЦЕДУРЫ ВВОДА/ВЫВОДА
WRITE.
Эта процедура используется для вывода данных на экран или на
принтер. Когда выражение, подлежащее выводу, представляет простой
символьный тип, то оператор WRITE(е) передает 8-битное значение (е)
на экран или на принтер.
CHR(8) (CTRL Н) - дает стирание символа на экране.
CHR(12) (CTRL L) - очищает экран,переводит страницу на принтере.
CHR(13) (CTRL М) - выполняет возврат каретки и подачу строки.
CHR(16) (CTRL Р) - если вывод шел на экран, то переключает его
на принтер и наоборот.
Запись в форме WRITE(Р1,Р2,РЗ,......Рп); эквивалентна записи:
BEGIN WRITE(Pl);WRITE(P2);.....;WRITE(Pn) END;
Параметры Pl,P2,...Pn могут иметь одну из следующих форм: <е>
или <е:ш> или <е:ш:п> или <е:ш:Н> Здесь e,m,n, - выражения, а Н
литеральная константа. Теперь мы должны рассмотреть 5 возможных
случаев.
1) Используется <е> или <e:m>. е - целое.
Значение целочисленного выражения <е> преобразуется в стринг с
ведущими пробелами. Размер стринга, подлежащего выводу, может быть
увеличен параметром ш, который задает полное число символов,
подлежащих выводу. Если величина m недостаточна, чтобы вывести <е>
полностью или m не задано, то <е> выводится полностью, a m
игнорируется. Обратите внимание на то, что если m равно <е> без
последующих пробелов, то они не будут выводиться на печать.
2) Используется форма <e:m:H>. е - целое.
В этом случае производится вывод в шестнадцатиричном формате.
Если ш=1 или ш=2, то значение <е> выдается по ширине, равной m
символам. Если ш=3 или ш=4, то ширина равна 4 символам; если ш>4, то
перед шестнадцатиричным значением <е> вставляется необходимое
количество ведущих пробелов. Там, где это требуется, вставляются
ведущие нули. Примеры:
WRITE (1025:m:Н)
ш=1 выдает:1
ш=2 выдает:01
m=3 выдает:0401
m=4 выдает:0401
m=5 выдает: 0401
3) <e> - действительное. Используются формы: <e>,<e:m> или
<e:m:n>.
Значение <е> преобразуется в символьный стринг, представляющий
действительное число. Формат представления задается параметром п.
Если параметр п не присутствует, то результат выдается в
нормализованной форме. Если число отрицательное, то знак минус
помещается перед мантиссой, иначе там помещается пробел. Число
выдается таким образом, что оно имеет от одного до пяти десятичных
знаков. Экспонента всегда имеет знак. Это означает, что минимальное
поле для такого нормализованного представления - 8 символов. Если
задается значение меньше восьми, то вывод производится во всю ширину
12-ти символов. Если задается ш>=8, то вывод производится с одним
десятичным знаком или больше - до пяти (при ш=12). Если ш>12, то
перед числом вводится необходимое количество ведущих пробелов.
Примеры:
WRITE (-1.23Е10:m)
m=7 дает: -1.23000Е+10
m=8 дает: -1.2Е+10
m=9 дает: -1.23Е+10
m=10 дает: -1.230Е+10
m=ll дает: -1.2300Е+10
m=l2 дает: -1.23000Е+10
m=13 дает: -1.23000Е+10
При использовании формы <e:m:n>, число <е> представляется в
форме с фиксированной точкой, где п задает количество десятичных
знаков при выдаче на печать.
Если это число равно нулю, то выполняется вообще только вывод
целой части. Если же выводимое число слишком велико, чтобы
уместиться в отведенное ему поле, то оно выдается в нормализованном
виде (см. выше). Примеры:
WRITE (1Е2:6:2) дает: 100.00
WRITE (1Е2:8:2) дает: 100.00
WRITE (23.455:6:1) дает: 23.5
WRITE (23.455:4:2) дает: 2.34550Е+01
WRITE (23.455:4:0) дает: 23
4) <е> имеет символьный тип или это стринг.
В этом случае может применяться форма либо <е> либо <е:ш>. Они
служат для выдачи символьной информации. Поле имеет ширину от 1
символа до длины всего стринга. Если m значительно выше, то вводятся
ведущие пробелы.
5) <е> - имеет логический тип.
В этом случае может применяться форма либо <е> либо <е:ш>. Они
служат для выдачи логических данных. Выдается либо "TRUE" (ИСТИНА)
либо "FALSE" (ЛОЖЬ) в зависимости от значения логической переменной
с минимальным полем 4 или 5 символов соответственно.
WRITELN.
WRITELN дает переход к печати с новой строки. Этот оператор
эквивалентен WRITE (CHR(13)). Обратите внимание на то, что при этом
автоматически выполняется подача строки.
WRTELN(PI,Р2......РЗ); эквивалентен
BEGIN WRITE(PI,Р2,.....РЗ); WRITELN END;
PAGE.
Процедура PAGE эквивалентна WRITE(CHR(12)); и вызывает очистку
экрана дисплея или переход принтера к новой странице.
READ.
Эта процедура используется для ввода данных с клавиатуры. Это
выполняется через буфер, содержащийся внутри пусковых процедур.
Исходно этот буфер пустой (за исключением маркера "конец строки").
Представьте себе, что доступ к этому буферу выполняется через
текстовое окно, находящееся над буфером, через которое можно увидеть
одновременно только один символ. Если это окно расположено над
символом "конец строки", то прежде чем операция чтения будет
завершена, новая строка должна быть считана в буфер с клавиатуры.
При считывании этой строки распознаются все управляющие коды.
READ (VI,V2,......Vn); эквивалентен:
BEGIN READ(VI); READ(V2);...;READ(Vn) END;
где VI,V2,...должны иметь тип символа, стринга, целого или
действительного.
Оператор READ(V); имеет различные эффекты в зависимости от типа
V. Рассмотрим 4 возможных случая.
1) V имеет тип символа.
В этом случае команда READ V просто дает считывание символа из
буфера клавиатуры и присвоения его V. Если поступает маркер "конец
строки", то функция EOLN выдает значение TRUE и новая строка
считывается с клавиатуры.
Примечание. Обратите внимание на то, что EOLN имеет значение
TRUE при старте программы. Это означает, что если
первый встреченный READ будет иметь тип символа, то
будет введено значение CHR(13) с последующим
переходом к вводу новой строки с клавиатуры и
последующий READ выдаст первый символ новой строки,
если она не пустая. См. также процедуру READLN
ниже.
2) V имеет тип стринга (строки).
По команде READ может быть прочитан стринг символов, и в этом
случае читается последовательность символов до тех пор, пока не
будет достигнуто их количество, заданное размером стринга или пока
не будет встречен маркер "конец строки" и функция EOLN примет
значение TRUE. Если конец строки достигается до того, как прочитан
весь стринг, то конец стринга заполняется нулевыми символами CHR(O),
что дает программисту впоследствии возможность оценить длину
введенного стринга.
Примечание к п. 1 здесь также действует.
3) V имеет целый тип.
В этом случае считывается последовательность символов,
изображающая целое число (см.разд. 2). Все ведущие пробелы и маркеры
"конец строки" пропускаются, т.е. примечание к п. 1 здесь не
действует.
Если считываемое целое по абсолютной величине больше, чем
MAXINT (32767), то выдается сообщение об ошибке "NUMBER ТОО LARGE" и
вычисления прекращаются.
Если первый считываемый символ после того, как ведущие пробелы
и маркеры "конец строки" будут пропущены, не является цифрой или
знаком "+" или "-", то выдается сообщение об ошибке "NUMBER
EXPECTED" и программа прерывается.
4) V имеет действительный тип.
Здесь считывается последовательность символов, представляющая
действительное число. Все ведущие пробелы и маркеры "конец строки"
пропускаются и, как и прежде, первый встреченный символ обязательно
должен быть цифрой или знаком. Если число является слишком большим
или слишком малым (см.разд. 2), то выдается сообщение об ошибке
""OVERFLOW". При нормализованной форме записи числа после "Е"
должен стоять знак или цифра. В противном случае выдается сообщение
об ошибке "EXPONENT EXPECTED". Точно также, если пбсле десятичной
точки не стоит цифра, выдается сообщение "NUMBER EXPECTED".
Действительные числа также, как и целые, могут быть считаны
немедленно, т.е. примечание к п. 1 (см. выше) здесь не действует.
READLN.
READLN(VI,V2,....Vn) эквивалентно:
BEGIN READ(VI,V2,....Vn); READLN END;
READLN просто считывает данные с клавиатуры в новый буфер, при
этом Вы можете использовать управляющие коды, рассмотренные в
разделе 1. Функция EOLN принимает значение FALSE после команды
READLN, если очередная строка не является пустой.
READLN может быть использован для того, чтобы пропустить пустые
строки в начале исполняемого объектного кода, т.е. она имеет эффект
считывания нового буфера.
ФУНКЦИИ ВВОДА.
EOLN.
Это логическая функция, которая принимает значение TRUE, если
следующий считываемый символ это маркер "конец строки" (CHR(13)). В
противном случае она принимает значение FALSE.
INCH.
Функция INCH выполняет сканирование клавиатуры в поисках
нажатой клавиши и, если какая-либо клавиша будет нажата, то
принимает значение, равное символу нажатрй клавиши. Если никакая
клавиша не была нажата, то принимает значение CHR(O). Таким
образом, результат работы этой функции имеет символьный тип.
ПРЕОБРАЗУЮЩИЕ ФУНКЦИИ.
TRUNC(X).
Параметр X должен быть либо действительным, либо целым.
Функция выдает результат в виде наибольшего целого, меньшего или
равного X, если X положительное, или наименьшего целого, большего
или равного X, если X отрицательно. Примеры:
TRUNC (-1.5) -------1
TRUNC(1.9) ------ 1
ROUND(X).
X должен иметь целый или действительный тип. Функция выдает
ближайшее целое число (в соответствии с принятыми стандартами на
округление чисел). Примеры:
ROUND (-6.5) -------6
ROUND (-6.51)-------7
ROUND (11. 7) ------12
ROUND (23.5) ------24
ENTIER(X).
X должен иметь целый или действительный тип. Функция выдает
наибольшее целое, меньшее или равное X для всех значений X.
Например:
ENTIER(-6.5) ------ -7
ENTIER(11.7) ------ 11
Примечание: ENTIER - не является стандартной функцией ПАСКАЛя,
а эквивалентна функции БЕЙСИКа INT. Она бывает очень полезной при
написании быстро работающих процедур для многих математических при-
ложений .
ORD(X).
X может быть любого скалярного типа, но не действительным.
Результат функции - целое число, представляющее порядковый номер
элемента X во множестве, определяющем тип X.
Если X - целое, то ORD(X) равен X. Но желательно такого
преобразования избегать.
ORD("а") = 97
ORD(") = 64
CHR(X).
X должен быть целого типа. Функция выдает символ, код которого
равен X в таблице кодов ASCII. Примеры:
CHR(49)="1"
CHR(91)="["
АРИФМЕТИЧЕСКИЕ ФУНКЦИИ.
Во всех функциях, рассмотренных в этом подразделе, параметр X
должен быть действительным или целым.
ABS(X).
Выдает абсолютное значение X. Результат имеет тот же тип, что и
аргумент X.
SQR(X).
Выдает квадрат параметра X, т.е. Х*Х.
SQRT(X).
Выдает корень квадратный из X. Результат всегда имеет
действительный тип. Если X - число отрицательное, выдается сообщение
об ошибке "MATHS CALL ERROR".
FRAC(X).
Выдает дробную часть числа X. FRAC(X)=X-ENTIER(X)
Как и функция ENTIER, эта функция бывает полезной при написании
многих быстро работающих математических процедур. Например:
FRAC(1.5)=0.5; FRAC(-12.56)=0.44
SIN(X).
Выдает синус величины X, где X задается в радианах. Результат
всегда имеет действительный тип.
COS(X).
Выдает косинус величины X, где X задается в радианах.
Результат всегда имеет действительный тип.
TAN(X).
Выдает тангенс величины X, где X задается в радианах.
Результат всегда имеет действительный тип.
ARCTAN(X).
Выдает угол в радианах, тангенс которого равен числу X.
Результат всегда имеет действительный тип.
EXP(X).
Выдает значение е в степени X, где е=2.71828. Результат всегда
действительное число.
LN (X) .
Выдает натуральный логарифм (т.е. логарифм по основанию е)
числа X. Результат действительное число. Если X <=0, то
генерируется сообщение об ошибке "MATHS CALL ERROR".
ПРОЧИЕ ПРЕДВАРИТЕЛЬНО ОПРЕДЕЛЕННЫЕ ПРОЦЕДУРЫ.
NEW(A).
Процедура NEW(A) отводит место для динамической переменной.
Переменная А - переменная-указатель. После исполнения этой функции А
содержит адрес новой назначенной динамической переменной. Тип
динамической переменной - тот же, что и переменной-указателя,
которая может быть любого типа.
Задействуется динамическая переменная по обращению А - см.
Приложение 4, где приведены примеры использования
переменных-указателей и обращений к ним.
Для переназначения места, отведенного для динамической
переменной используются функции MARK и RELEASE (см. ниже).
MARK(А1).
Память для динамических переменных берется из области, условно
называемой "кучей". Процедура MARK выполняет сохранение состояния
"кучи" динамических переменных, помечая ее и записывая в
переменную-указатель А1. Состояние "кучи" может быть восстановлено
до момента, предшествовавшего исполнению процедуры MARK. Это
выполняется с помощью процедуры RELEASE (см. ниже).
Тип переменной, на которую указывает А1, не имеет значения,
поскольку А1 может использоваться только с MARK и RELEASE, но никак
не с NEW. Примеры см. в Приложении 4.
RELEASE(А1).
Эта процедура освобождает место в "куче" для динамических
переменных и восстанавливает их состояние таким, каким оно было до
использования процедуры MARK.
Таким образом, здесь уничтожаются все динамические переменные,
созданные после последнего исполнения процедуры MARK. Надо подходить
к использованию этой процедуры с осторожностью.
Подробности - см. в Приложении 4.
INLINE ( CI, С2 , СЗ.....) .
Эта процедура позволяет вставить в ПАСКАЛЬ-программу машинный
код Z80. В программу (в текущее значение адреса) вставляются
значения (C1MOD256, C2MOD256, C3MOD256,....). CI, С2, СЗ - должны
быть целыми константами. Примеры см. в Приложении 4.
USER(A).
Эта процедура имеет один целый аргумент А. Она организует обра-
щение к адресу памяти, заданному А. Поскольку НР4Т содержит целые
числа в двойной дополнительной форме (см. Приложение 3), то для то-
го, чтобы обратиться к адресам выше чем #7FFF (32767) должны исполь-
зоваться отрицательные значения А. Например, #С000 - это -16384, по-
этому USER(-16384) выполнит обращение к адресу #СООО. Однако, рабо-
тая с константами для указания на адрес в памяти, гораздо удобнее
использовать шестнадцатиричное представление.
Вызываемая процедура должна заканчиваться командой RET (#С9)
процессора и должна обеспечивать сохранение содержимого регистра
процессора IX.
HALT.
Эта процедура позволяет остановить исполнение программы с
сообщением "HALT AT РС=ХХХХ", где ХХХХ - шестнадцатиричный адрес в
памяти, где произошло исполнение команды HALT. Вместе с листингом
компиляции эта функция поможет определить по какой из двух или
нескольких ветвей пошло исполнение программы. Обычно эта функция
применяется при отладке программы.
РОКЕ(А,С).
Функция РОКЕ засылает значение С в адрес А компьютера. А может
иметь целый тип, а С - любой тип, кроме множества. См. раздел 3 по
поводу представления адресов в памяти компьютера. Примеры:
РОКЕ(#6000,"А") помещает #41 в адрес #6000.
РОКЕ(-16384,3.6ЕЗ) помещает 00 0В 80 70 (в шестнадцатиричной
форме) в адреса, начиная с #СООО.
TOUT (NAME,START,SITZE).
Эта процедура позволяет выполнять запись переменных на ленту.
Первый параметр имеет тип ARRAY[1...8] OF CHAR и является именем
файла, подлежащего выгрузке. По этой процедуре выгружается SIZE
байтов из памяти, начиная с адреса START. Оба эти параметра должны
иметь целый тип.
Например, для выгрузки переменной X под именем "VAR" надо
использовать:
TOUT('VAR ADDR(X),SIZE(X))
Возможность указания истинного адреса в памяти дает
пользователю значительно большую гибкость, чем просто возможность
выгрузки массивов. Например, если память имеет разбивку на экраны,
то может быть организована выгрузка целых экранов. Примеры см. в
Приложении 4.
TIN (NAME,START).
Эта процедура служит для загрузки с ленты переменных и т.п.,
если они были выгружены через TOUT. Имя имеет тип ARRAY[ 1*..8] OF
CHAR, a START - целый тип.Компьютер разыскивает на ленте файл с
именем NAME, после чего выполняется загрузка файла в память, начиная
с адреса START. Количество байтов, подлежащих загрузке читается с
ленты (оно записалось при TOUT).
Пример загрузки переменной, выгруженной в предыдущем разделе:
ТIN(4 VAR N,ADDR(X))
Поскольку исходные файлы записываются редактором в том же
формате, что и файлы, работающие с TIN, TOUT, то можно использовать
TIN для загрузки текстовых файлов в символьные массивы для
обработки. См. Приложение 4.
OUT(X,C).
Эта процедура служит для организации прямого доступа к выходным
портам процессора Z80 без использования процедуры INLINE. Значение
целочисленного параметра X загружается в регистр процессора ВС, а
символьный параметр С - в регистр А, вслед за чем исполняется
команда Ассемблера OUT(С),А. Например: OUT(l,NAN) выдаст символ NAN
по порту 1.
RANDOM.
Эта функция выдает псевдо-случайное число в диапазоне 0...255.
Хотя эта процедура работает очень быстро, она выдает плохие резуль-
таты, если ее многократно используют в циклах, не содержащих опера-
ций ввода/вывода.
Если пользователю нужны лучшие результаты, то он должен
написать свою процедуру на ПАСКАЛе или в машинном коде,
удовлетворяющую поставленной задаче.
SUCC(X).
X может быть любого скалярного типа, кроме действительного.
Примеры:
SUCC(VAV)=VBV
SUCC(v 5 v) = v 6 v
PRED(X).
X может быть любого скалярного типа, кроме действительного.
Примеры:
PRED(NJN)=NIN
PRED(TRUE)=FALSE
PRED(N6N)=n5n
ODD(X).
X должен иметь целый тип. Функция дает логический результат,
равный TRUE, если X нечетное и FALSE, если X - четное.
ADDR(X).
Эта функция берет идентификатор любого типа в качестве
параметра и выдает результат, равный численному значению адреса, в
котором содержится данная переменная с идентификатором X.
Информацию о том, как в ПАСКАЛе хранятся переменные во время
работы программы, см. в Приложении 3. Примеры использования данной
функции см. в Приложении 4.
РЕЕК(А,Т).
Первый параметр этой функции - целое число, обозначающее адрес
в памяти (см. также разд. 3). Второй аргумент - тип. Он показывает
какой тип будет у результата функции. РЕЕК применяется для
извлечения данных из памяти компьютера. Результат может быть любого
типа.
При всех операциях РЕЕК, РОКЕ данные перемещаются в памяти
компьютера в своей специфичной для НР4Т форме (см. Приложение 3).
Например, если в памяти, начиная с адреса #5000 и далее содержатся
значения 50, 61, 73, 63, 61, 6С (в шестнадцатиричной форме), то:
WRITE(РЕЕК(#5000,ARRAY[1..6] OF CHAR)) дает vPaskalN
WRITE(PEEK(#5000,CHAR)) дает VPN
WRITE(PEEK(#5000,INTEGER)) дает 24912
WRITE(PEEK(#5000,REAL)) дает 2.46227E+29
SIZE(X).
Параметром этой функции является переменная. Результат
целочисленный. Это количество памяти, израсходованное на хранение
данной переменной.
INP(P).
Функция предназначена для прямого обращения к портам процессора
без использования процедуры INLINE. Значение целочисленного парамет-
ра Р помещается в регистр ВС процессора и результат символьного типа
получается после исполнения команды АССЕМБЛЕРа IN А,(С).