ПАСКАЛЬ.
РУКОВОДСТВО ПРОГРАММИСТА.

1. НАЗНАЧЕНИЕ И УСЛОВИЯ ПРИМЕНЕНИЯ

Система программирования Паскаль включена в ФОДОС-2 для расширения класса задач, решаемых операционной системой. Это связано с тем, что язык Паскаль удобен как для выполнения различных вычислений, так и для обработки нечисловой информации, включая экономические задачи, работу со списками и т.д.

В состав системы программирования входят удобные средства отладки программ в диалоговом режиме. Допускается возможность ведения библиотек программ, а также использование в программах на Паскале подпрограмм, написанных на Макроассемблере и Фортране.

Для работы с языком Паскаль в операционной системе ФОДОС-2 рекомендуется, чтобы в составе комплекса находилось оперативное запоминающее устройство (память) ёмкостью не менее 16-ти К слов. Система Паскаль включает следующие файлы:

PASCAL.SAV

- компилятор с языка Паскаль на Макроассемблер;

PASCAL.OBJ

- исполняющая система, использующая только базовый набор инструкций центрального процессора;

IMP.SAV

- программа обеспечивает некоторую оптимизацию текста на Макроассемблере, полученного в результате обработки прикладной программы транслятором Паскаля.

FORM.SAV

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

RANIO.OBJ

- подпрограмма для выполнения операций ввода/вывода прямого доступа.

DEM.PAS

- текст контрольно-демонстрационной задачи.

Дополнительно к перечисленным, необходимы файлы MACRO.SAV и LINK.SAV.

Создание и выполнение программы на языке Паскаль может быть выполнено с помощью следующих шагов:

Протокол примера действий, перечисленных выше, может иметь следующий вид:

         .R EDIT
         *EWDEMO.PAS¤¤
           ...             ; СОЗДАНИЕ ФАЙЛА С ТЕКСТОМ
           ...             ; ПРОГРАММЫ
         ¤EX¤¤
         .R PASCAL
         *DEMO=DEMO
         .R MACRO
         *DEMO=DEMO
         *^C
         .R LINK
         *DEMO=DEMO,PASCAL ; ИЛИ DEMO=DEMO,SY:PASCAL, ЕСЛИ
                           ; PASCAL.OBJ НАХОДИТСЯ НА SY:,А НЕ НА DK:
         *^C
         .RUN DEMO
           ...             ; ВЫПОЛНЕНИЕ ПОЛУЧЕННОЙ ПРОГРАММЫ

В следующих разделах документа приведённые процедуры будут описаны более подробно.

2. СОЗДАНИЕ ИСХОДНОГО ФАЙЛА НА ПАСКАЛЕ.

Исходный файл с текстом программы на языке Паскаль является обычным текстовым файлом в смысле системы ФОДОС-2. Создание исходного файла может быть выполнено любым из системных редакторов ФОДОС-2.

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

Для выделения (разделения) отдельных страниц в листинге программы могут использоваться знаки <FF> (аналогично программам на Макроассемблере).

3. ТРАНСЛЯЦИЯ ПРОГРАММЫ НА ЯЗЫКЕ ПАСКАЛЬ.

Компилятор Паскаль использует текст программы в качестве входного файла. Во время работы компилятор создаёт файл с текстом программы на языке Макроассемблер. Дополнительно к этому выходному файлу может создаваться (но не обязательно) файл с листингом, например:

.R PASCAL
* PROG,PROG = PROG

что приводит к трансляции программы на языке Паскаль из файла PROG.PAS и созданию файла PROG.MAC с текстом на Макроассемблере и файла PROG.LST с листингом.

В командной строке компилятора можно явно указывать имена устройств и ключи, управляющие трансляцией, например:

.R PASCAL
*PROG,LP:/N=PROG

что вызовет трансляцию программы PROG.PAS с получением файла PROG.MAC и листинга на устройстве печати (LP:). Листинг будет содержать только строки программы, содержащие ошибки и диагностические сообщения (указывается ключом "N").

Если листинг вообще получать не нужно, то следует использовать, например, следующую команду:

.R PASCAL
*PROG = PROG

С помощью ключей, используемых в командной строке и/или тексте программы, можно управлять процессом трансляции.

ПРИМЕЧАНИЕ. Некоторые ключи могут использоваться только в тексте программы.

3.1. Ключ "D".

Использование данного ключа приводит к включению в транслируемую программу информации для отладчика. Эта информация содержит имена переменных и процедур, а также номера операторов. В дополнение к этому в процессе компоновки в состав программы будет автоматически включён отладчик из библиотеки исполняющей системы Паскаль.

Использование данного ключа с ключом "S" позволит отладчику установить соответствие номеров операторов и исходного текста программы из листинга. Поэтому в этом случае нужно всегда создавать файл с листингом программы (см. раздел с описанием процедур отладки).

3.2. Ключ "Е".

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

3.3. Ключ "F".

Использование этого ключа позволяет ускорить выполнение действий над операндами типа REAL, т.е. арифметические операции над числами в формате с плавающей запятой. Эта оптимизация может использоваться для процессоров без плавающей запятой. Оптимизация по скорости выполнения осуществляется за счёт генерации компилятором соответствующих вызовов подпрограмм. В том случае, если ключ "F" не используется, то компилятор генерирует машинные инструкции для работы с плавающей запятой, а при выполнении программы исполняющая система осуществляет их эмуляцию. Время, затрачиваемое на эмуляцию, больше, чем выполнение инструкций обращения к подпрограммам.

Однако использование ключа "F" приводит к увеличению размера программы в оперативной памяти.

3.4. Ключ "L".

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

3.5. Ключ "N".

Данный ключ запрещает распечатку исходного текста программы (операторов) в файл листинга за исключением строк (и, соответственно, операторов), содержащих ошибки.

3.6. Ключ "S".

Этот ключ приводит к включению в генерируемый компилятором текст на Макроассемблере операторов исходного языка в качестве комментариев. Использование данного ключа облегчает анализ текста программы на Макроассемблере.

Ключ "S" несколько модифицирует действие ключа "D", как было описано выше.

3.7. Использование ключей в тексте программы

Все ключи, рассмотренные выше, допускают использование их в тексте программы. Это осуществляется использованием комментариев специального вида. Первым знаком комментария должен быть "¤". Следующий знак должен совпадать с символическим обозначением ключа, например, "(*¤S*)" приводит к включению в текст на Макроассемблере исходных операторов в качестве комментариев.

За мнемоникой ключа может использоваться знак "+" или "-". Эти знаки предназначены для "включения" действия ключа ( + ) или "выключения" ( - ), т.е. отмены его действия.

Ключи "A", "T" и "С" могут использоваться только внутри текста программы и не могут применяться в командной строке.

3.8. Ключ "A".

Данный ключ отменяет генерацию проверок на допустимость значений индексов при работе с массивами - (*¤А-*), обычно компилятор генерирует инструкции, проверяющие выход значений индексов за допустимые границы. Если генерация проверок запрещена, то программа будет занимать несколько меньше оперативной памяти и будет выполняться несколько быстрее.

3.9. Ключ "T".

 Ключ (*¤Т-*) запрещает генерацию инструкций, проверяющих переполнение стека. Всякий раз при вызове процедуры стек проверяется на наличие места для размещения локальных переменных. Отказ от использования проверок стека незначительно уменьшает размер оперативной памяти, занимаемой программой, и убыстряет её выполнение.

3.10. Ключ "С".

 Специальный вид комментариев позволяет включать в текст программы на языке Паскаль фрагменты на языке Макроассемблер. Это осуществляется ключом "С", используемым в начале комментариев. Компилятор Паскаль анализирует входные строки для Макроассемблера для определения ссылок на соответствующие параметры и переменные. Например, для того, чтобы использовать значение глобальной переменной "АВС", нужно обращаться к ней с помощью "ABC(R5)", а для доступа к локальной переменной или параметру процедуры "XYZ" - использовать запись "XYZ(SP)":

    (*¤C
         TST     ABC(R5)        ;ПЕРЕМЕННАЯ ABC # 0 ?
         BNE     10¤            ;ДА
         MOV     XYZ(SP),R0     ;ПОЛУЧИТЬ ЗНАЧЕНИЕ XYZ В R0
         ADD     #123.,R0       ;ПРИБАВИТЬ 123 К R0
         MOV     R0,@#100       ;ЗАПИСАТЬ R0 ПО АБСОЛЮТНОМУ
                                ; АДРЕСУ
  10¤:   INC     XYZ(SP)        ;УВЕЛИЧИТЬ НА 1 ПЕРЕМЕННУЮ
                                ; XYZ
    *)

ПРИМЕЧАНИЕ. По умолчанию во фрагментах на языке макроассемблер система счисления десятичная, а не восьмеричная.

3.11. Листинг программы

Листинг, создаваемый компилятором Паскаль, содержит помимо исходного текста программы четыре колонки (пример листинга см. в разделе, посвящённом процедурам отладки).

Первая колонка содержит номера исходных строк программы. Эта колонка в листинге обозначается как "LINE". Нумерация строк выполняется подряд, начиная с номера 1.

Вторая колонка, обозначаемая "STMT", содержит локальные номера операторов исходной программы и используется при отладке программ. Следует отметить, что один оператор может размещаться на нескольких строках. С другой стороны, несколько операторов могут размещаться на одной строке. Поэтому в колонке номеров операторов значения могут возрастать более чем на один при переходе от одной строки к другой.

Третья колонка содержит номера уровней вложенности процедур. Эта информация полезна для анализа "доступности" переменных в тех или иных процедурах, поскольку переменные, объявленные (определённые) на одном уровне, могут быть доступны на том же уровне и на уровнях, номера которых выше данного. Основная программа находится на 1-ом уровне вложенности. Процедуры и функции, определённые в программе, считаются имеющими уровень два.

В процедуре уровня два может, например, быть определена функция, которая будет иметь уже уровень вложенности три. Данная функция считается локальной и не может быть доступной из основной программы, т.е. из уровня один.

В третьей колонке отмечается уровень вложенности блоков операторов, ограниченных "BEGIN" и "END". Другими словами, операторы типа "BEGIN" и "REPEAT" приводят к увеличению на единицу номера уровня вложенности, пока не встретится соответствующий "END" или "UNTIL". Таким образом номера уровней вложенности могут использоваться для анализа программистом общей структуры программы с точки зрения вложенности блоков.

3.12. Диагностика ошибок трансляции

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

Грубые ошибки, например, в блочной структуре программы, могут вызвать целый ряд (цепочку) других ошибок. В этом случае исправление первой ошибки приведёт к "исчезновению" всех остальных ошибок. Использование ключа "N" при создании листинга приведёт к получению в листинге только строк программы, в которых обнаружены ошибки, например:

.R PASCAL
*PROG,LP:/N = PROG

Общее число ошибок, обнаруженных во время трансляции, распечатывается в конце листинга. Одновременно выводится объём оперативной памяти, которая осталась неиспользованной до конца трансляции. Аналогичная информация выводится па экране системного терминала.

Возможны следующие сообщения об ошибках:

OVERFLOW

переполнение;

MISSING END

пропущено "END";

ТОО MANY SYMBOLS

слишком много переменных и процедур;

ТОО MANY LEVELS

слишком много уровней вложенности процедур и функций;

ТОО MANY WARNINGS

слишком много предупреждений;

INPUT LINE TOO LONG

длинная входная строка;

INVALID CHARACTER

недопустимый знак встретился на строке;

8 OR 9 IN OCTAL CONSTANT

в восьмеричной константе обнаружились цифры 8 или 9;

LABELS MUST BE INTEGERS

в качестве меток допустимо использовать только целые числа;

CONSTANT OVERFLOW

в программе слишком много констант; в компиляторе не хватает памяти для размещения всех констант;

MISSING LABEL DEFINITION

отсутствует определение метки;

UNDEFINED FORWARD PROCEDURE OR FUNCTION

недопустимо использовать процедуру или функцию прежде, чем они будут определены;

BAD PROGRAM NAME

недопустимое имя программы;

IMPROPER SYMBOL

недопустимый символ;

MISSING BEGIN

пропущено "BEGIN";

MISSING '.' AT PROGRAM END

в конце программы отсутствует ".";

ALL VAR DEFINITIONS PRECEED PROCEDURE DEFINITIONS

определения всех переменных должно находиться в программе перед определением процедур;

BAD ORIGIN FOR VARIABLE

недопустимое начальное значение для переменной;

BAD VARIABLE LIST

недопустимый список переменных;

BAD TYPE

недопустимое определение типа;

BAD LABEL

неправильная метка;

BAD FUNCTION NAME

недопустимое имя для функции;

BAD PROCEDURE NAME

недопустимое имя для процедуры;

BAD FUNCTION RESULT TYPE

недопустимый тип результата функции;

FORTRAN PARAM. MUST BE CALL BY REFERENCE

фортрановский параметр должен всегда передаваться по ссылке;

DON’T REPEAT PARAMETER LIST

не следует указывать список формальных параметров более одного раза;

',' USED INSTEAD OF ';'

"," была использована вместо ";";

MISSING ')' AT END OF PARAM LIST

пропущена ")" в конце списка формальных параметров;

BAD PARAMETER

недопустимый формальный параметр;

BAD SCALAR TYPE

недопустимый скалярный тип;

BAD SUBRANGE

недопустимое указание интервала;

BAD TYPE SPECIFICATION

недопустимое определение (указание) типа;

ARRAY INDEX TYPE ERROR

ошибка в задании типа индекса для массива;

BAD RECORD

недопустимая запись;

BAD FIELD LIST

недопустимое определение списка полей;

FIELD LIST MUST BE IN PARENTHESES

список полей должен указываться в скобках;

BAD VARIANT

недопустимый вариант;

DUPLICATE FIELD NAME

повторно используется имя для поля записи;

BAD CONSTANT

недопустимая константа;

LABEL NOT DECLARED

используется неопределённая метка;

LABEL REDEFINITION

переопределение метки недопустимо;

LABEL DEFINED AT WRONG LEVEL

определение метки на неправильном уровне;

UNDEFINED SYMBOL

неопределённый символ;

MISSING SEMI-COLON

пропущена ";";

INVALID DECLARATION. PROBABLY MISSING END

недопустимый оператор; возможно, что пропущено "END";

INVALID SYMBOL

недопустимый символ;

NOT IMPLEMENTED

данная возможность не реализована в компиляторе;

MISSING LABEL

пропущена метка;

BAD 'EXIT'

пропущено "EXIT";

DUPLICATE CASE LABEL

повторно используется метка в операторе "CASE";

ELSE NOT LAST IN CASE STMT

"ELSE" не находится в конце оператора "CASE";

MISSING END IN CASE STMT

пропущено "END" в операторе "CASE";

BAD CASE LABEL

недопустимая метка выбора в операторе "CASE";

MISSING UNTIL

пропущено "UNTIL";

BAD FOR STATEMENT

неправильный формат оператора цикла "FOR";

BAD WITH STATEMENT

недопустимый оператор "WITH";

WITH IN REG 0

для оператора "WITH" используется регистр 0;

TOO MANY ARGUMENTS

слишком много аргументов;

BAD ARGUMENT

недопустимый аргумент;

TOO FEW ARGUMENTS

указано мало аргументов;

NEW OR DISPOSE ARG NOT POINTER TYPE

в процедурах "NEW" и "DISPOSE" может использоваться только переменная-указатель;

BAD READ STATEMENT

недопустимый оператор "READ";

BAD WRITE STATEMENT

недопустимый оператор "WRITE";

FORMAT MUST BE INTEGER TYPE

для указания параметров формата может использоваться только целочисленные переменные или константы;

FILE VARIABLE MISSING

пропущена переменная файла;

BAD FILE NAME

недопустимое имя файла;

ILLEGAL ASSIGNMENT

недопустимое назначение;

BAD EXPRESSION

ошибка в выражении;

MISSING ')'

пропущена ")";

MISSING OPERATOR

пропущен оператор;

MISSING OPERAND

пропущен операнд;

STRANGE '[' -- BAD SET OR MISSING ARRAY DEF

необъяснимое появление "[", что может быть связано с недопустимым множеством или неопределённым массивом;

UNDEFINED OPERAND -- ASSUMING INTEGER

неопределённый операнд; компилятор присваивает ему тип "INTEGER";

FUNCTION ARGUMENT MISSING

пропущен аргумент функции;

FUNCTION ARG MUST BE REAL OR INTEGER

аргумент функции должен иметь тип "REAL" или "INTEGER";

ARGUMENT MUST BE INTEGER TYPE

аргумент должен иметь тип "INTEGER";

ARG MUST BE REAL

следует использовать аргумент типа "REAL";

ARG MUST BE INTEGER

следует использовать аргумент типа "INTEGER";

ARG MUST BE NON-REAL SCALAR

аргумент должен иметь скалярный тип, не являющийся "REAL";

BAD 'ABS' ARG

недопустимый аргумент функции "ABS";

'ODD' APPLIED TO NON-INTEGER EXPRESSION

процедура "ODD" должна использоваться только с целочисленным аргументом (переменной, выражением и т.д.);

BAD SET ELEMENT

недопустимый элемент множества;

MISSING FIELD VARIABLE

пропущено указание поля записи;

UNDEFINED POINTER BASE TYPE

неопределённый тип, на который ссылается переменная указатель;

BAD INDEX TYPE

недопустимый тип индекса;

ILLEGAL OPERATOR

недопустимый оператор;

ILLEGAL TYPE OF OPERAND

недопустимый тип операнда;

INCOMPATIBLE ARRAYS

несовместимые массивы;

BAD 'IN' OPERANDS

недопустимые операнды для оператора "IN";

OUT OF FLOATING AC'S

для выполнения программы не хватает аккумуляторов процессора плавающей запятой (встретилось сложное выражение);

OUT OF REGISTERS

не хватает регистров для выполнения программы (встретилась сложная конструкция);

BOOLEAN EXPRESSION NEEDED

в данном месте программы необходимо использовать логическое выражение;

INCOMPATIBLE TYPE

несовместимый тип;

MUST BE SIMPLE VARIABLE

следует использовать простую переменную;

UNRESOLVED FORWARD TYPE REFERENCE

не определён тип из-за ссылок вперёд на неопределённые типы данных;

ARRAY INDEX OUT OF RANGE

индекс массива выходит за заданные границы;

FATAL ERROR

фатальная ошибка компилятора; возможен аппаратурный сбой и ошибка в самом компиляторе;

TOO MANY ERRORS IN THIS LINE

слишком много ошибок в данной строке;

EXPECTED '.' MISSING. ASSUMED WHERE INDICATED

должна присутствовать "."; показано подразумеваемое положение ".";

ALL CHARACTERS IGNORED UNTIL ...

все знаки до "..." игнорируются;

INDEX OUT OF RANGE

индекс выходит за допустимые границы.

4. ТРАНСЛЯЦИЯ ПРОГРАММЫ МАКРОАССЕМБЛЕРОМ

Компилятор транслирует программы с языка Паскаль на язык Макроассемблер (как было описано выше). Полученная программа нуждается в трансляции Макроассемблером для получения объектного модуля, например:

.R MACRO
*PROG = PROG

Макроассемблер может выдавать также листинг транслируемой программы, но обычно он не представляет особого интереса. Если всё же листинг программы на Макроассемблере необходим, то рекомендуется выполнять трансляцию компилятором с языка Паскаль, используя ключ "S", что приводит к включению в текст на Макроассемблере исходных строк на Паскале в качестве комментариев.

ПРИМЕЧАНИЕ. Следует помнить, что компилятор Паскаля и Макроассемблер создают файлы листинга, имеющие одинаковый тип ".LST". Поэтому последовательность команд:

.R PASCAL
*PROG/S,PROG = PROG .R MACRO
*PROG,PROG = PROG

приведёт к тому, что файл с листингом, полученный компилятором Паскаля, будет замещён одноимённым файлом листинга, созданным Макроассемблером

5. КОМПОНОВКА ПРОГРАММЫ НА ЯЗЫКЕ ПАСКАЛЬ

После получения объектного файла его необходимо скомпоновать с исполняющей системой Паскаль из объектной библиотеки (PASCAL.OBJ) для получения программы в формате загрузки, например:

.R LINK
*PROG = PROG,PASCAL

Библиотека PASCAL.OBJ с исполняющей системой Паскаль содержит набор модулей, к которым обращается программа, полученная компилятором Паскаля. Системный компоновщик ФОДОС-2 включит в состав программы нужные модули из библиотеки и создаст программу в формате загрузки.

Внешними называются процедуры, которые компилируются и ассемблируются отдельно от основной программы. Включение внешних процедур в компонуемую программу осуществляется перечислением в командной строке компоновщику спецификаций входных файлов, содержащих модули внешних процедур. Например, если внешние процедуры содержатся в файлах "A", "В" и "С", то командная строка будет иметь вид:

.R LINK
*PROG=PROG,A,B,C,PASCAL

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

.R LINK
*PROG = PROG,PASCAL//
*A/O:1
*B/O:1
*C/O:1//

Более подробная информация о правилах построения оверлейных программ приводится в главе "Редактор связей. Руководство оператора" (кн. 3) при описании системного компоновщика "LINK".

6. ЗАПУСК И ВЫПОЛНЕНИЕ ПРОГРАММЫ

Запуск программы, написанной на языке Паскаль, осуществляется обычными средствами системы ФОДОС-2, т.е. использованием команд монитора "R" или "RUN", которые описаны в главе "Командный язык системы" (кн. 2).

Например:

 .R PROG

При загрузке программы возможны ошибки (системные), которые описаны в главе "Сообщения системы" (кн. 6). Сообщения, возникающие при выполнении программы на языке Паскаль, будут описаны ниже.

7. СООБЩЕНИЯ

В данном разделе представлены тексты сообщений об ошибках, возникающих при выполнении программы на языке Паскаль. Тексты сообщений снабжены пояснениями причин ошибок и, следовательно, способами их устранения.

NO ROOM ON DEVICE OR FILE NOT FOUND

данное сообщение связано с ошибками при выполнении процедуры RESET, если специфицированный файл не был найден, или при работе процедуры REWRITE возникло отсутствие возможности для создания нового файла, т.е. нет места в каталоге носителя и т.п.

NOT A VALID DEVICE

в процедуре RESET или REWRITE было указано устройство, драйвер которого отсутствует в системных таблицах резидентного монитора ФОДОС-2.

END OF FILE ON DEVICE

данная ошибка связана с выполнением процедуры READ или GET, если в тот момент значение функции EOF было TRUE.

I/O CHANNEL NOT OPEN

ошибка связана с выполнением операции ввода/вывода с каналом, который не был предварительно открыт процедурами RESET или REWRITE.

NOT ENOUGH AVAILABLE MEMORY

сообщение свидетельствует о том, что динамическая область памяти исчерпана (как правило, при выполнении процедуры NEW); другая причина данного сообщения - недостаток памяти для рекурсивного вызова процедуры.

INTEGER ERROR

ошибка связана с выполнением арифметических операций с переменными типа INTEGER; как правило, - это переполнение при умножении или выполнении процедур TRUNC или ROUND.

FLOATING POINT ERROR

сообщение об этой ошибке связано с неправильным выполнением арифметической операции над переменными типа REAL в процессе вычислений.

LOG OF NEGATIVE
EXP OVERFLOW
SQRT OF NEGATIVE

данные ошибки возникают при передаче неправильных параметров в функции языка Паскаль: LOG, ЕХР или SQRT.

DIVIDE BY ZERO

ошибка связана с попыткой выполнить деление на 0;

BAD SET EXPRESSION

ошибка при вычислении выражения, связанного с множеством: анализируемый элемент не принадлежит данному множеству;

ARRAY BOUND ERROR

 при вычислении выражения или т. п. значение индекса приняло недопустимое значение;

TRAP TO 4

произошло прерывание по вектору четыре, которое связано с обращением к несуществующей ячейке памяти или использованием недопустимого режима адресации в инструкции процессора; обычно эта ошибка появляется из-за ошибок в фрагментах, написанных на Макроассемблере;

BAD SUPPORT PACKAGE
RESERVED INSTRUCTION TRAP
MISSING SPECIAL FEATURE

-

ошибка связана с использованием исполняющей системы Паскаля, не соответствующей типу центрального процессора, а также применением инструкций (в фрагментах на Макроассемблере), отсутствующих в наборе инструкций центрального процессора;

SUPPORT CONDITIONALS ERROR

ошибка при выполнении логической операции;

NEW OF LENGTH 0

ошибка связана с выполнением процедуры "NEW" при создании переменной нулевой длины;

FATAL I/O ERROR

произошла неустранимая ошибка ввода/вывода;

TOO MANY FILES OPEN

сделана попытка открыть слишком много файлов для ввода/вывода.

8. ТРАНСЛЯЦИЯ ВНЕШНИХ ПРОЦЕДУР

Внешними называются процедуры или функции, которые компилируются и ассемблируются отдельно от основной программы на языке Паскаль. Компоновщик используется для объединения внешних процедур и основной программы и получения программы в формате загрузки. Средства внешних процедур позволяют облегчить процесс разработки и отладки программного обеспечения, поскольку внесение изменений в основную программу не требует повторной компиляции и ассемблирования внешних процедур. Отладка больших программ существенно упрощается путём создания полностью тестированных внешних процедур. В этом случае при отладке основной программы её компилируют с ключом "D". Однако локальные переменные внешних процедур становятся недоступными отладчику. Размер отладочной информации в программе существенно уменьшается. В отдельных случаях, когда программа очень велика по размеру занимаемой оперативной памяти, единственная возможность проведения отладки - использование внешних процедур, прошедших этап тестирования.

Другими словами, когда над большим программным продуктом работает несколько программистов, полезно использовать совместно разработанную и отлаженную библиотеку внешних процедур.

Внешние процедуры и функции создаются аналогично обычным процедурам в языке Паскаль. Использование ключа "Е" при трансляции, приводит к объявлению всех процедур и функций на первом уровне вложенности глобальными. Первые 6 знаков в имени процедуры или функции объявляются в качестве глобальной точки входа (метки), которая будет использована компоновщиком при объединении внешних модулей и основной программы. Специальная форма комментариев (*¤Е+*) может также использоваться для определения процедуры в качестве внешней. Программа, которая использует внешнюю процедуру, должна включать заголовок этой процедуры, за которым следует ключевое слово "EXTERNAL". Надо соблюдать осторожность при задании типов и порядка следования параметров процедуры, поскольку компилятор лишён возможности проверить эту информацию.

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

Например:

Глобальные переменные (файл GLOBAL.PAS):

 
      VAR                (* ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ *)
          I: INTEGER;
          R: REAL;
          C: CHAR;
 

Основная программа (файл MAIN.PAS):

 
      (* ВНЕШНЯЯ ПРОЦЕДУРА *)
 
      PROCEDURE EXPROC(X:INTEGER); EXTERNAL;
 
      BEGIN              (* НАЧАЛО MAIN *)
          I:=1; R:=3.1415926; C:='X';
          EXPROC(5);     (* ВЫЗОВ ВНЕШНЕЙ ПРОЦЕДУРЫ *)
      END.               (* КОНЕЦ MAIN *)
 

Внешняя процедура (файл EXTERN.PAS):

 
      (*¤E+*)
 
      PROCEDURE EXPROC(Y:INTEGER); (* ВНЕШНЯЯ ПРОЦЕДУРА *)
 
      BEGIN      (* НАЧАЛО ВНЕШНЕЙ ПРОЦЕДУРЫ *)
         WRITELN('I= ',I:2);
         WRITELN('R= ',R);
         WRITELN('C= ',C);
         WRITELN('PROCEDURE ARGUMENT= ',Y:3);
      END;       (* КОНЕЦ ПРОЦЕДУРЫ *)
 

Ниже представлена последовательность команд для выполнения программы:

 
         .R PASCAL
         *MAIN=GLOBAL,MAIN
         .R PASCAL
         *EXTERN=GLOBAL,EXTERN
         .R MACRO
         *MAIN=MAIN
         *EXTERN=EXTERN
         *^C
         .R LINK
         *PROG=MAIN,EXTERN,PASCAL
         *^C
         .R PROG

9. ОСОБЕННОСТИ ВЫПОЛНЕНИЯ ПРОГРАММЫ НА ЯЗЫКЕ ПАСКАЛЬ

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

При выполнении программа на языке Паскаль использует две области данных: глобальная область и стек. В глобальной области содержатся все переменные, определённые на уровне ноль, т.е. в начале программы. Область стека используется для хранения локальных переменных для процедур и адресов передачи (возврата) управления. Пятый регистр R5 всегда содержит адрес начала глобальной области, а регистр шестой (SP) указывает на начало программного стека. Содержимое этих регистров не должно меняться во фрагменте на Ассемблере (или должно сохраняться, а затем восстанавливаться).

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

(SP) ===>

Статистический указатель

 

Локальные переменные (если они есть)

 

Адрес возврата

 

Параметры (если есть)

 

Результат, возвращаемый функцией

Статический указатель содержит адрес области стека, выделенной при последнем вызове процедуры. Этот указатель используется для вычисления адресов переменных промежуточных уровней (переменных, которые не являются ни локальными, ни глобальными). Все локальные переменные для текущей процедуры могут использоваться путём индексации относительно текущего указателя стека - SP. Доступ к глобальным переменным осуществляется индексацией регистра R5. Доступ к промежуточной переменной может осуществляться путём "движения" по стеку с использованием статических указателей до тех пор, пока не будет найдена требуемая область стека. После этого индексация осуществляется относительно найденной базы. Для того, чтобы сделать доступ к переменным более простым для программиста на Макроассемблере, компилятор определяет имя переменной в качестве смещения относительно соответствующего указателя (R5 или SP).

Аналогично, точки входа в процедуры и функции компилятор заменяет на одноимённые метки. Следует помнить, что компилятор не проверяет правильность обращений к переменным во фрагментах на Макроассемблере.

Пример:

         FUNCTION SWAPBYTES (I:INTEGER):INTEGER;
         BEGIN
                 (*¤C
                         SWAB    I(SP)
                 *)
                 SWAPBYTES := I;
         END;

Если необходимо всю процедуру написать на Макроассемблере, то это можно осуществить, просто заключив весь фрагмент в заголовок процедуры, т.е. указать начало и конец процедуры по правилам Паскаля. В теле процедуры фрагменты на Паскале и Макроассемблере могут чередоваться, например:

         PROCEDURE EXAMPLE;
         BEGIN
            (*¤C
                    ;ФРАГМЕНТ НА МАКРОАССЕМБЛЕРЕ
            *)
       WRITE (' ТЕКСТ СООБЩЕНИЯ');(* ФРАГМЕНТ НА ПАСКАЛЕ *)
            (*¤C
                    ;ЕЩЕ ФРАГМЕНТ НА МАКРОАССЕМБЛЕРЕ
            *)
         END;

ПРИМЕЧАНИЕ. Следует помнить, что функции сохраняют содержимое регистров R0-R4 (включая регистры-аккумуляторы процессора с плавающей запятой), а процедуры - не сохраняют.

10. ПРОГРАММА IMP

Программа IMP написана на языке Паскаль и предназначена для выполнения некоторой оптимизации программ, создаваемых компилятором Паскаль в операционной системе ФОДОС-2.

Как указывалось выше, компилятор транслирует программу с языка Паскаль на язык Макроассемблер. Программа IMP обрабатывает текст программы на Макроассемблере, выполняет отдельные виды оптимизации и создаёт более эффективную программу тоже на языке Макроассемблер.

Оптимизации подвергаются инструкции переходов (JMP, BR и т.п.). IMP выполняет замену инструкции JMP на BR, если это возможно. При этом экономится 1 слово памяти. Например:

      JMP        L20

заменяется на:

      BR         L20

В некоторых случаях выполняются более сложные виды оптимизации:

      BGT        L30
      JMP        L50
L30:

Заменяется на:

      BLE        L50

В этом случае экономится 2 слова памяти.

10.1. Вызов и загрузка

Вызов программы IMP осуществляется командами монитора R или RUN. После загрузки программа запрашивает имя файла, в котором находится текст программы, которую нужно оптимизировать. После этого IMP запрашивает спецификацию выходного файла для оптимизированной версии программы.

После ввода спецификаций файлов IMP начинает работать. В конце IMP распечатывает статистику о процессе оптимизации, т.е. число слов, на которое сократился размер программы, и процентное уменьшение размера программы.

Пример:

                 .R IMP
                 INPUT FILE?  DK:PROG.MAC
                 OUTPUT FILE? DK:PROG1.MAC
                 IMPROVEMENT    50 WORDS   8.7%
                 .

ПРИМЕЧАНИЕ. По умолчанию тип входного и выходного файлов "МАС".

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

Текст программы на Макроассемблере не должен содержать макрокоманд. Регистры должны обозначаться только как %0, %1,...,%6, %7. В тексте программы можно использовать комментарии.

Процедура оптимизации выполняется сравнительно медленно. Поэтому оптимизировать программу следует только после того, как она полностью отлажена.

10.2. Сообщения программы IMP

Ниже приводятся тексты сообщений, выдаваемых IMP с пояснениями.

NO <> IN LINE NNNN LINE

в строке с номером "NNNN" отсутствуют скобки "<" и ">".

ERROR AT BRJMP NODE NNNN

в строке с номером "NNNN" обнаружена ошибка, возможно, связанная с использованием ключа "С" и вставленным в текст на Паскале фрагмента на Макроассемблере.

ERROR AT JMP NODE NNNN

в строке с номером "NNNN" обнаружена ошибка, возможно, связанная с использованием ключа "С" и вставленным в текст на Паскале фрагмента на Макроассемблере.

11. ПРОГРАММА FORM

Программа FORM написана на языке Паскаль и предназначена для выполнения форматирования исходного текста различных пользовательских программ на Паскале, а также для создания и распечатки таблиц перекрёстных ссылок.

ПРИМЕЧАНИЕ. При форматировании программы производится проверка её блочной структуры.

11.1. Вызов и загрузка

Вызов программы FORM осуществляется командами монитора R или RUN. После загрузки программа выводит на терминал "*" и ожидает командной строки в формате CSI.

Командная строка для FORM может содержать до 2-х выходных и один входной файл.

Спецификация входного файла определяет исходный текст программы, которая должна быть подвергнута форматированию. Тип файла по умолчанию - ".PAS".

Спецификация первого выходного файла задаёт файл, в который будет помещён отформатированный текст исходной программы на Паскале. Эта спецификация не является обязательной. Тип файла по умолчанию - ".PAS".

Спецификация второго выходного файла задаёт файл, в который будет помещена таблица перекрёстных ссылок программы и её листинг. Спецификация данного выходного файла не является обязательной. Тип файла по умолчанию - ".LST".

Пример:

         .R FORM
         *PROG1,LP:=PROG
         NO ERROR IN BLOCKSTRUCTURE
         .

Сформатированный текст программы на Паскале можно использовать для последующей работы, т.е. транслировать компилятором, редактировать, отлаживать и т.д.

11.2. Сообщения программы FORM

Сообщения, выдаваемые программой FORM на терминал:

LINE NNNN ТОО LONG

строка исходной программы с номером NNNNN содержит более 147 знаков, что является недопустимым:

MISSING POINT AT PROGRAM END

в конце программы на языке Паскаль отсутствует ".";

COMMAND STRING ERROR

командная строка для FORM содержит ошибку;

ERROR IN BLOCKSTRUCTURE

блочная структура программы на Паскале содержит ошибку;

NO ERROR IN BLOCKSTRUCTURE

при форматировании программы ошибок в блочной структуре не обнаружено; данное сообщение свидетельствует о нормальном завершении работы программы FORM.

Следующие сообщения появляются во втором выходном файле, создаваемом программой FORM (в листинге таблиц перекрёстных ссылок):

NEXT LINE ТОО LONG

следующая строка листинга содержит более 147 знаков;

MISSING 'END' OR 'UNTIL' NUMBER NNNN

пропущено "END" или "UNTIL" с номером NNNN;

MISSING 'THEN' NUMBER NNNN

пропущена операторная скобка "THEN" с номером NNNN;

MISSING 'OF' TO 'CASE' NUMBER NNNN

пропущен "OF" в операторе "CASE" с номером NNNN;

ONLY ONE 'EXIT' ALLOWED

в данном контексте допустим только один оператор "EXIT";

MISSING 'EXIT' IN 'LOOP' NNNN .

пропущено "EXIT" в операторе цикла с номером NNNN.

Ниже перечисляются нормальные заголовки, появляющиеся в листинге сформатированной программы:

CROSS REFERENCE LISTING OF VARIABLES

таблица перекрёстных ссылок переменных;

LIST OF PROCEDURES

список процедур;

X IS CALLED BY Y

процедура "X" вызывается процедурой "Y";

X CALLS UP Y

процедура "X" вызывает процедуру "Y";

INDENTED PROCEDURE LIST

порядковый список процедур.

12. СРЕДСТВА ОТЛАДКИ ПРОГРАММ

Отладка программ на языке Паскаль осуществляется специальным модулем, входящим в состав исполняющей системы Паскаль. Отладчик позволяет полностью управлять выполнением программы, распечатывать и модифицировать значения переменных и т.п.

Включение отладчика в состав выполняемой программы осуществляется автоматически при использовании ключа "D" в процессе компиляции. Данный ключ приводит к включению в состав генерируемой программы дополнительной информации о размещении операторов и именах переменных. Использование ключа "S" позволяет существенно расширить объём информации, доступной в процессе отладки. Однако, в этом случае нужно обязательно получить файл с листингом отлаживаемой программы. Тогда при выполнении точки останова или возникновении ошибки отладчик будет распечатывать соответствующую исходную строку программы на языке Паскаль, в которой произошёл останов.

При запуске отлаживаемой программы отладчик распечатывает свой идентификатор на терминале. Если при компиляции использовался ключ "S", то отладчик запросит спецификацию файла, содержащего листинг отлаживаемой программы. Файл с листингом должен размещаться на внешнем запоминающем устройстве каталоговой организацией и создаваться одновременно с компиляцией отлаживаемой программы.

Когда отладчик готов к приёму команды, то он распечатывает знак "]" в левом углу терминала. После этого можно вводить команды отладчику. Поскольку модуль отладчика также написан на языке Паскаль, то он считывает команды (вводит команды) обычными операторами ввода, которые имеются в Паскале. Поэтому, если введённая команда содержит ошибку, отладчик распечатает соответствующее сообщение и повторит запрос команды.

Все примеры работы с отладчиком в данном разделе демонстрируются на программе DBGTST (которая находится в файле DBGTST.PAS). Компиляция этой программы осуществляется командами:

         .R PASCAL
         *DBGTST,DBGTST=DBGTST/S/D

При компиляции создаётся файл с листингом программы DBGTST.LST. Распечатка листинга имеет следующий вид:

  DBGTST               P  A  S  C  A  L         13-12-82        PAGE 1
              ДВК  "ЭЛЕКТРОНИКА  НЦ 8020/2,3,4
 
  LINE  STMT LEVEL  NEST   SOURCE STATEMENT
 
    1                     PROGRAM DBGTST;
    2
    3                     VAR    A,B:INTEGER;
    4
    5                        PROCEDURE  SUM(C,D,E:INTEGER);
    6
    7                         VAR        I:INTEGER;
    8
    9                            FUNCTION ADD(P,Q:INTEGER)
   10                                            :INTEGER;
   11                            VAR     X,Y:INTEGER;
   12
   13                        BEGIN (* START OF ADD *)
   14     1     3     1       X:=P;
   15     2     3     1       Y:=Q;
   16     3     3     1       IF Y=0 THEN ADD:=X
   17     5     3     2        ELSE ADD:=ADD(0,X)+ADD(Y,0);
   18     6     3     1      END; (* END OF ADD *)
   19
   20                         BEGIN (* START OF SUM *)
   21     1     2     1          I:=ADD(C,D);
   22     2     2     1          I:=ADD(I,E);
   23     3     2     1       END; (* END OF SUM *)
   24
   25                     BEGIN (* START OF MAIN *)
   26     1     1     1       A:=1;
   27     2     1     1       B:=2;
   28     3     1     1       SUM(3,4,5);
   29     4     1     1   END. (* END OF MAIN *)

Из текста программы можно видеть, что она содержит глобальную процедуру "SUM" и две переменные "A" и "В". Термин "глобальная" используется в данном случае потому, что переменные "A" и "В" и процедура "SUM" могут быть доступны на протяжении всей программы. Функция "ADD" является локальной, т.е. внутренней для процедуры "SUM". Поэтому функция "ADD" может вызываться только внутри процедуры "SUM", но не из основной программы. Аналогично, переменная "I" является локальной для процедуры "SUM", а переменные "X" и "Y" - локальными для функции "ADD".

Остальная часть данного раздела посвящена описанию команд отладчика.

ПРИМЕЧАНИЕ. Данная версия отладчика Паскаль допускает работу только под управлением BJ- или FB-мониторов.

12.1. Точка останова (;B)

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

Для того, чтобы установить точку останова, необходимо напечатать имя процедуры или функции, затем запятую, за которой следует номер оператора (где следует установить точку останова) и "". В каждой процедуре и функции операторы нумеруются последовательно, начиная с 1-го. Номера операторов распечатываются в листинге программы в колонке, помеченной "STMT".

Если несколько операторов размещаются на одной строке, то в колонке "STMT" листинга распечатывается номер первого оператора в этой строке.

ПРИМЕЧАНИЕ. Следует помнить, что в каждый момент времени может быть только одна точка останова.

Примеры:

 ] MAIN,3;B
 ] SUM,2;B
 ] ADD,1;B

После того, как установлена точка останова на операторе, отладчик будет получать управление всякий раз перед выполнением этого оператора. Следует учесть, что отладчик не проверяет допустимость номера оператора в команде, определяющей точку останова. Поэтому, если, например, установить точку останова на операторе "FOO,99", который не существует, то управление отладчику никогда не попадёт. Однако это даёт возможность опытному программисту определять точки останова в оверлейных процедурах, которые не находятся в оперативной памяти в момент определения точки останова.

Отмена точки останова осуществляется командой "0" или "".

Пример:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] SUM,1;B
  ] ;G
  BREAKPOINT AT SUM,1  I:=ADD(C,D);
  ] ;P
  PROGRAM TERMINATION AT MAIN,4  END. (* END OF MAIN *)
  ]

12.2. Запуск (;G) и продолжение (;P) программы

В предыдущем примере команды ";G" и "" использовались для запуска или продолжения выполнения программы. Если точка останова определена, то в команде "" можно задать число раз, которое будет пропущена точка останова (т.е. управление будет передано отладчику только после того, как оператор выполнится указанное число раз). Это осуществляется с помощью числового аргумента команды:

  ] ADD,1;B
  ] ;G
  BREAKPOINT AT ADD,1
  ] 3;P
  BREAKPOINT AT ADD,1
  ]

В показанном примере, после начальной точки останова, отладчик получит управление после того, как функция "ADD" будет выполнена 3 раза, т.е. на 4-ый раз.

При выполнении программы в пошаговом режиме команда "N;P" приведёт к выполнению "N" операторов. Только после этого управление будет передано отладчику.

12.3. Пошаговый режим выполнения (;S)

Команды "N;S", где N не равно нулю, переводит отладчик в пошаговый режим выполнения программы. При этом управление будет передаваться отладчику после выполнения очередного оператора, как будто там была определена точка останова. Команда продолжения "" приводит к выполнению одного очередного оператора программы. Если использовать команду "N;P", то без остановки будет выполнены "N" операторов. Выход из пошагового режима задаётся командой "0;S" или просто ";S".

Пример использования пошагового режима:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] 1;S
  ] ;G
  BREAKPOINT AT MAIN,1  A:=1;
  ] ;P
  BREAKPOINT AT MAIN,2  B:=2;
  ] ;P
  BREAKPOINT AT MAIN,3  SUM(3,4,5);
  ] 13;P
  BREAKPOINT AT ADD,4  IF Y=0 THEN ADD:=X
  ]

12.4. Трассировка выполняемых операторов (;T)

Если отладчик находится в режиме трассировки, то перед выполнением очередного оператора распечатываются его координаты, т.е. имя процедуры и номер этого оператора. Если использовался ключ "S" при компиляции, то распечатывается также исходная строка, содержащая оператор. Таким образом трассировка позволяет контролировать (наблюдать) процесс выполнения программы. Режим трассировки устанавливается командой "N;T", где N не равно нулю. Завершение режима трассировки (выход из этого режима) осуществляется по команде "0" или "".

ПРИМЕЧАНИЕ. Следует помнить, что, если в одной строке находится несколько операторов, то строка будет распечатана только один раз:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] SUM,2;B
  ] ;G
  BREAKPOINT AT SUM,2  I:=ADD(I,E);
  ] 2;T
  ] ;P
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,6  END; (* END OF ADD *)
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,6  END; (* END OF ADD *)
  ADD,6  END; (* END OF ADD *)
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,6  END; (* END OF ADD *)
  ADD,6  END; (* END OF ADD *)
  SUM,3  END; (* END OF SUM *)
  MAIN,4  END. (* END OF MAIN *)
  PROGRAM TERMINATION AT MAIN,4  END. (* END OF MAIN *)
  ]

12.5. Трассировка выполняемых процедур (;C)

В большинстве случаев трассировка всей программы может потребовать много времени. Для решения этой проблемы отладчик обеспечивает более короткую форму трассировки - трассировку вызовов процедур и функций.

Данный режим трассировки задаётся командой "N;C", где N не равно нулю. Завершение данного режима трассировки осуществляется командой "0" или "".

В данном режиме трассировки отладчик распечатывает информацию о входе в процедуру или функцию, а также при их соответствующем завершении:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] 1;C
  ] ;G
  ENTERING SUM FROM MAIN,3  SUM(3,4,5);
  ENTERING ADD FROM SUM,1  I:=ADD(C,D);
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  LEAVING  ADD
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  LEAVING  ADD
  ENTERING ADD FROM SUM,2  I:=ADD(I,E);
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  LEAVING  ADD
  ENTERING ADD FROM ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  LEAVING  ADD
  LEAVING  ADD
  LEAVING  SUM
  PROGRAM TERMINATION AT MAIN,4  END. (* END OF MAIN *)
  ]

12.6. Слежение за переменной (;W)

Команда слежения используется для "наблюдения" за значением переменной. Если указанная переменная изменяет свое значение, то отладчик получает управление, как и в точке останова. Для установки наблюдения за переменной необходимо напечатать имя переменной, а затем ";W". Чтобы снять наблюдение, используется команда "-1;W".

Перед выполнением очередного оператора отладчик проверяет, изменилось ли значение наблюдаемой переменной. Если значение изменилось, то отладчик печатает об этом coобщение и переходит в состояние ожидания команды.

ПРИМЕЧАНИЕ. Следует помнить, что отладчик выполняет останов после оператора, который привёл к модификации значения переменной. Для того, чтобы распечатать тот оператор, который вызвал модификацию, необходимо использовать команду "¤L", описанную ниже.

После продолжения выполнения программы наблюдение за переменной будет продолжаться.

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

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

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] SUM,1;B
  ] ;G
  BREAKPOINT AT SUM,1  I:=ADD(C,D);
  ] I/
  0
  ] I;W
  ] ;P
  WATCHED VALUE CHANGED.
  BREAKPOINT AT SUM,2  I:=ADD(I,E);
  ] I/
  7
  ] ;P
  WATCHED VALUE CHANGED.
  BREAKPOINT AT SUM,3  END; (* END OF SUM *)
  ] I/
  12
  ] MAIN,4;B
  ] ;P
  WATCH TERMINATED.  VALUE DIDN'T CHANGE.
  BREAKPOINT AT MAIN,4  END. (* END OF MAIN *)
  ]

12.7. Распечатка содержимого переменных

Отладчик может распечатывать содержимое переменных в четырёх форматах: INTEGER, BYTE, REAL, CHAR. Для распечатки переменной следует ввести её имя и команду, определяющую формат распечатки:

/

INTEGER в десятичном виде;

\

BYTE в десятичном виде;

%

REAL в формате с плавающей запятой;

'

один знак в символьном виде (CHAR).

Формат распечатки INTEGER обычно используется при распечатке значений переменных, объявленных как INTEGER.

Формат BYTE бывает полезным при выводе скалярных типов или переменных типа BOOLEAN. Символьная информация также может распечатываться форматом BYTE. Формат REAL используется для вывода переменных типа REAL, а формат CHAR - переменных типа CHAR.

Следует помнить, что отладчик не имеет информации o типах переменных. Поэтому можно распечатывать одну и ту же переменную по различным форматам, однако результаты при этом будут разные, например:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] MAIN,3;B
  ] ;G
  BREAKPOINT AT MAIN,3  SUM(3,4,5);
  ] A/
  1
  ] B/
  2
  ] I/
  CAN'T FIND VARIABLE CALLED "I"
  2
  ] SUM,2;B
  ] ;P
  BREAKPOINT AT SUM,2  I:=ADD(I,E);
  ] I/
  7
  ]

Для удобства распечатки массивов можно использовать счётчик повторения после знака, определяющего формат распечатки. Например, для распечатки знакового массива "X", состоящего из 30-ти знаков, необходима команда "Х'30". Если этот же массив имеет тип REAL, то его можно распечатать по команде "Х/30". При распечатке элементов целых массивов одновременно выводятся и их адреса в виде ".+N", где N - это смещение в байтах от начального адреса массива. Адрес элемента выводится перед распечаткой значения элемента.

При указании адреса переменной, хотя обычно используется один идентификатор, можно применять простые выражения. Например, для распечатки 10-го элемента массива целых чисел следует воспользоваться командой "Х+20". Очевидно, что десятый элемент целочисленного массива находится, начиная с 20-го байта. После того, как была распечатано значение переменной, её адрес можно обозначать ".". Например, если была распечатана переменная "Х+20/" и нужно распечатать следующий элемент массива "Х+22/", то можно воспользоваться командой ".+2/". Из текущего адреса можно также вычитать значения, т.е. допустима конструкция типа ".-4".

При использовании переменных-указателей можно проследить любой уровень ссылки использованием оператора "^" (косвенная адресация для распечатки переменных-указателей). Например, если переменная "X" указывает на целое, то это число можно распечатать командой "Х^/". Оператор "." идентичен оператору "+" и может применяться при распечатке сложных записей. Конструкция "Х.4" полностью эквивалентна "Х+4", что означает третье слово записи, на которую указывает переменная "X" (все смещения задаются в байтах).

Имеющиеся операторы дают возможность распечатывать очень сложные структуры данных, например, "Х.4^.2.100^.4".

Для того, чтобы узнать адрес переменной или записи (вместо её значения), следует использовать оператор "=". Например, "Х=" приведёт к распечатке адреса переменной "X", а не её значения. Однако при работе с абсолютными адресами следует соблюдать осторожность. Локальные переменные функций или процедур размещаются в стеке. Поэтому их адреса меняются (или могут меняться) от вызова к вызову. Также не следует пытаться распечатать значения переменных, про которые отладчик "говорит", что он найти их не может ("CAN'T FIND VARIABLE").

12.8. Изменение содержимого переменных

Отладчик позволяет изменять значения переменных, используя оператор присваивания ":=". Для того, чтобы присвоить переменной "A" значение "1", можно использовать оператор "А:=1". Оператор "Х:='строка'" присвоит знаковому массиву строку знаков. Поскольку отладчик не располагает информацией о типах переменных, то в операторе ":=" нужно указывать тип. Например, чтобы присвоить переменной "X" типа REAL значение 1.234, нужно ввести команду "X:=R1.234".

Примеры:

  ] A:=1
  ] FILENAME:='TEST.DAT'
  ] CORRELATION:=R.09332123456E-2

12.9. Распечатка списка имён переменных

Если отладка программы выполняется без листинга или часто используются локальные процедуры и функции, в которых определены локальные переменные, то бывает полезным распечатать список переменных, которые в данный момент являются доступными. Распечатку имён переменных можно выполнить командой "¤V". Список распечатывается, начиная с имени текущей локальной процедуры (функции), за которым следуют имена переменных, определённых в данной процедуре (функции). Далее распечатываются процедуры, находящиеся на уровнях вложенности, имеющих меньшие номера, а также их локальные переменные. В конце списка выводятся имена глобальных переменных. Список всех переменных может быть достаточно большим, однако, используя команду <CTRL/0>, можно прекратить распечатку.

Примеры:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] ¤V
 
  MAIN
     A
     B
  ] SUM,1;B
  ] ;G
  BREAKPOINT AT SUM,1  I:=ADD(C,D);
  ] ¤V
 
  SUM
     C
     D
     E
     I
 
  MAIN
     A
     B
  ] ADD,1;B
  ] ;P
  BREAKPOINT AT ADD,1  X:=P;
  ] ¤V
 
  ADD
     P
     Q
     X
     Y
 
  SUM
     C
     D
     E
     I
 
  MAIN
     A
     B
  ]

12.10. Распечатка списка вызванных процедур

Если выполнение программы прервано, например, по точке останова, то обычно бывает полезно понять, каким путём выполнение программы привело к точке останова. Много важной информации можно получить в этом случае по команде "¤S", которая распечатывает стек вызовов процедур и функций. Распечатка содержит имя процедуры или функции и номер оператора, в котором данная процедура была вызвана. Текущая процедура распечатывается первой, затем выводится имя процедуры, которая вызвала данную и т.д.

Пример:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] ADD,1;B
  ] ;G
  BREAKPOINT AT ADD,1  X:=P;
  ] ¤S
  ADD,1  X:=P;
  SUM,1  I:=ADD(C,D);
  MAIN,3  SUM(3,4,5);
  ] 2;P
  BREAKPOINT AT ADD,1  X:=P;
  ] ¤S
  ADD,1  X:=P;
  ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  SUM,1  I:=ADD(C,D);
  MAIN,3  SUM(3,4,5);
  ]

12.11. Распечатка последних выполненных операторов

Отладчик всегда запоминает информацию о последних 10-ти выполненных операторах. Если необходимо понять, как произошёл переход в точку останова, то можно воспользоваться командой "¤L", которая распечатает номера последних 10-ти операторов, которые были выполнены, например:

  PASCAL DEBUGGER V2.2
 
  LISTING FILE NAME? DBGTST
  ] ADD,3;B
  ] ;G
  BREAKPOINT AT ADD,3  IF Y=0 THEN ADD:=X
  ] ;P
  BREAKPOINT AT ADD,3  IF Y=0 THEN ADD:=X
  ] ¤L
  MAIN,2  B:=2;
  MAIN,3  SUM(3,4,5);
  SUM,1  I:=ADD(C,D);
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ADD,5  ELSE ADD:=ADD(0,X)+ADD(Y,0);
  ADD,1  X:=P;
  ADD,2  Y:=Q;
  ADD,3  IF Y=0 THEN ADD:=X
  ]

13. КОНТРОЛЬНО-ДЕМОНСТРАЦИОННАЯ ЗАДАЧА

Состав контрольно-демонстрационной задачи:

DEM.PAS - программа получения суммы чисел. Результат вычисления выводится на экран.

Порядок выполнения задачи следующий:

.AS MY1: DK:
.RUN PASCAL 
*DEM=DEM 
.MACRO DEM 
.R LINK
DEM=DEM,PASCAL
.RUN DEM

На экране появится сообщение:

ВВЕДИТЕ 5 ЧИСЕЛ ЧЕРЕЗ ПРОБЕЛЫ

Ввести пять чисел, например: 1 2 3 4 5

На экран будет выведено:

1 2 3 4 5
СУММА ЧИСЕЛ = 15.00

Ниже приводится исходный текст задачи на языке Паскаль.

PROGRAM SEC (INPUT,OUTPUT);
CONST N=5;
VAR
    А : REAL;
    SUM : REAL;
    I : INTEGER;
BEGIN
    SUM:=0;
    WRITELN('введите ',N: 1,'чисел через пробелы');
    FOR I:=1 TO N DO
     BEGIN
      READ(A);
      SUM:= SUM + А;
     END;
    WRITELN('-----------------------------------------');
    IF((SUM/SUM)=1) THEN
     WRITELN('сумма чисел =', SUM:6:2 )
    ELSE WRITE('ошибка в программе!');
END.

ПРИЛОЖЕНИЕ

СПИСОК КОМАНД ОТЛАДЧИКА

¤L

вывод списка 10-ти последних операторов, которые были выполнены.

¤S

распечатка списка (стека) вызванных процедур и функций.

¤V

распечатка списка имён переменных, доступных в данной точке программы.

PROC,STMT;B

установить точку останова на операторе "STMT" в процедуре с именем "PROC".

0;B

отменить точку останова.

;P

продолжить выполнение программы после точки останова.

N;P

пропустить точку останова "N" раз или выполнить "N" операторов в пошаговом режиме.

;G

начать выполнение программы (аналогично ""),

1;T

установить режим трассировки выполняемых операторов.

0;T

отменить режим трассировки выполняемых операторов.

1;C

установить режим трассировки вызовов процедур и функций.

0;C

отменить режим трассировки вызовов процедур и функций.

1;S

установить пошаговый режим выполнения программы.

0;S

отменить пошаговый режим выполнения программы, т.е. перейти в обычный режим.

VAR;W

установить слежение за изменением значения переменной "VAR".

-1;W

отменить слежение за значением переменной.

VAR/

распечатать значение переменной типа INTEGER.

VAR/N

распечатать "N" значений целочисленных переменных (массива).

VAR\

распечатать значение переменной в десятичном виде (как байта).

VAR\N

распечатать "N" последующих байтов в десятичном виде.

VAR%

распечатать значение переменной типа REAL.

VAR%N

распечатать "N" значений переменных с плавающей запятой.

VAR'

распечатать значение переменной типа CHAR в символьном виде.

VAR'N

распечатать "N" последующих значений переменных в символьном виде.

VAR=

распечатать абсолютный адрес переменной.

VAR:=NUMBER

присвоить целочисленное значение (NUMBER) переменной "VAR".

VAR:='TEXT'

присвоить символьную строку переменной.

VAR:=RNUMBER

присвоить значение с плавающей запятой (NUMBER) переменной.

"+", "."

операторы сложения.

"-"

оператор вычитания.

"^"

оператор ссылки (косвенная адресация).