|
Часть 6
Г Л А В А 7
============
КОМПИЛЯТОР
==========
Компилятор JPI Мodula-2 имеет одно-проходимую структуру, это значит, что он выдает
сгенерированный код одновременно с чтением исходного текста; временные файлы не используют-
ся.
Импортирование выполняется рекомпиляцией файлов модулей определений (DEF-файлов), если
потребуется. Это устраняет необходимость специальных файлов "Таблицы идентификаторов" и оз-
начает, что определения модулей не нуждаются в явной компиляции; они вызывают последующую
компиляцию, как только будут модифицированы. Это также устраняет ограничения порядка компи-
ляции, которые обычно соответствуют определениям модулей; реализации модулей могут быть от-
компилированы в любом порядке.
Выходом является переместимый обьектный файл (OBJ-файл) в формате Intel/Microsoft.
Группа таких файлов собирается в один выполняемый файл (EXE-файл) линкером.
OBJ-ФАЙЛЫ
=========
OBJ-файл содержит специальную информацию, которая упрощает компоновку, проверяет неп-
ротиворечивость (целостность) и минимизирует размер EXE-файла.
Записи включения - это вставки, которые сообщают компоновщику имена файлов, используе-
мых модулем. Это означает, что только имя главного модуля необходимо определить для компо-
новки.
Записи версии - это также вставки, которые записывают дату/время используемых DEF-фай-
лов. Компоновщик проверит, все ли модули соответствуют этим версиям; если нет, появляется
возможность фатальной противоречивости, которая может быть устранена перекомпиляцией (см.
опцию Make ниже).
OBJ-файл построен как библиотеки, что означает, что модуль разбит на секции, которые
включаются компоновщиком, если используются. Это устраняет потребность в больших модулях из
универсальной библиотеки. Каждая глобальная процедура - это секция сама по себе, так же и
группы обьявленных данных, принадлежащие к соответствующим частям VAR или CONST.
ПРЕДСТАВЛЕНИЕ ДАННЫХ
====================
Базисная единица памяти - 8-битовый байт. Каждый обьект Мodula-2 представлен числом
байтов, определенным его типом. Типы подмножества представляются, как их базовые типы.
Взятие ADDRESS обьекта дает сброс первого байта его в памяти. Для многобайтовых число-
вых типов последний значащий байт хранится в младшем адресе.
Типы CARDINAL представлены двоичными числами без знака:
SHORTCARD : 1 байт
CARDINAL : 2 байта
LONGCARD : 4 байта
Целые типы представлены как двоичные числа с 2-мя дополнениями:
SHORTINT : 1 байт
INTEGER : 2 байта
LONGINT : 4 байта
Тип REAL представлен как пары мантисса/экспонента для процессора 8087 (см. док., отно-
сящуюся к 8087).
REAL : 4 байта
LONGREAL : 8 байтов
Перечислимые типы представлены, как двоичное число без знака (перечисление)
<= 256 значений : 1 байт
>= 256 значений : 2 байта
BOOLEAN : 1 байт
CHAR : 1 байт
Тип "абсолютный указатель" занимает 4 байта, где первые 2 содержат значение смещения,
а последние 2 - значения сегмента. NIL представлен как (0,0). Базовый указатель занимает 2
байта, содержащих сегмент. Процедурные переменные FAR представлены, как абсолютные указате-
ли на первый оператор кода процедуры. Процедурные переменные NEAR представлены как 16- би-
товые смещения в пределах подходящего сегмента кода.
Множества представлены упакованной битовой картой с одним битом для каждого потенци-
ального члена элементарного типа, как указано [0..N]. Число требуемых байтов равно 1 + (N
DIV 8). Элемент E (0 <= E <= N) представлен битом номер Е MOD 8 в байте номер E DIV 8.
Элементы массивов хранятся в последовательных ячейках памяти и располагаются по воз-
растанию индексов. Общий размер - это размер элемента, умноженный на число элементов.
Поля записей также хранятся в последовательных ячейках и в порядке, в котором они опи-
саны в определении типа; каждое поле хранится согласно своему типу. Общий размер - это сум-
ма размеров полей.
Вариантные части имеют особенность: поля различных альтернатив накладываются (совмест-
ная память) и общий размер вариантной части есть сумма размеров полей большей альтернативы.
Пример:
TYPE R = RECORD
F1: INTEGER; (* Байты 0-1 *)
CASE F2: BOOLEAN IS (* Байт 2 *)
| FALSE: F3, (* Байт 3 *)
F4, (* Байт 4 *)
F5: CHAR; (* Байт 5 *)
| TRUE: F6: CARDINAL (* Байты 3-4 *)
END;
F7: SET OF [0..20]; (* Байты 6-8 *)
END; (* SIZE (R) = 9, VSIZE(R.F6) = 5 *)
СОГЛАШЕНИЯ О ВЫЗОВАХ
====================
Эта часть требует ознакомления с архитектурой 8086-процессора; мы будем обращаться к
регистрам по именам: AX(,AL), BX, CX, DX, SI, DI, BP, SP, CS,SS,DE,ES.
Область стека
-------------
Процедура активизации использует аппаратный стек (определенный SS или SP) для несколь-
ких целей:
- Передачи параметров.
- Сохранения адреса возврата.
- Сохранения регистров, которые используются и должны быть сохранены.
- Сохранения содержимого 8087-сопроцессора, если недостаточно стекового пространства
8087, и оно оставлено для вспомогательных вычислений с плавающей точкой.
- Построения таблицы внешних контекстов для доступа к переменным, локальным по отноше-
нию к близлежащим процедурам.
- Память для локальных переменных (созданных пользователем либо компилятором).
- Копии параметров массива открытых значений с тем, чтобы они могли быть модифицирова-
ны без модификации фактических параметров.
- Сохранения приоритетов вызывающих процессов.
Параметры поставляются в стек вызывающими процессами; остаток строится вызванной про-
цедурой на входе. Регистр BP указывает на базу стека активизации и используется для доступа
к локальным переменным и параметрам.
Общий рисунок имеет вид:
старый SP ->+--------------------+Высшие адреса
:параметры :Действующие параметры
+--------------------+
:возврат - CS :Возвратный сегмент для
: :FAR
:возврат - IP :Возврат смещения
новый BP ->+--------------------+
:сохраненный BP :BP вызывающей программы
:таблица BP :Регистры BP объемлющих
: :процедур
:локальные переменные:Локальные переменные
: :пользователя
:локальные временные :Локальные анонимные
: :переменные
:сохраненные регистры:Регистры вызывающей
: :программы
:копии значений :Копии массивов парамет-
: :ров
:приоритеты :Сохраненные приоритеты
: :(процессов)
:сохраненный 8087 :Содержимое 8087 процес-
: :сора вызывающей про-
: :граммы
новый SP ->+--------------------+Нижние адреса
Только требуемые части строятся в действительности; для очень простых процедур доста-
точно сохранения регистра BP.
Завершаясь, процедура восстановит стек и сохраненные регистры (см. директиву $C) в
состояние, в котором они находились до вызова; это включает освобождение памяти, используе-
мой параметрами.
Передача параметров
-------------------
Параметры выводятся в стек в том порядке, в котором они появляются в объявлении проце-
дуры. Конкретно, что выводится - зависит от типа соответствующего формального параметра и
является ли он переменной или нет. Все параметры-переменные и любые открытые массивы пере-
даются указателем: передается полный адрес в формате сегмент-смещения, и процедура исполь-
зует его для доступа в памяти к фактическому параметру. Такой параметр занимает 4 байта вне
зависимости от типа.
Переменные параметры, исключая открытые массивы, передаются помещением фактического
значения параметра в стек. Занимаемая память задается типом параметра, исключая тот факт,
что 1-байтовый тип занимает 2 байта в стеке.
Для значения параметров открытых массивов процедура (необязательно, см. директиву $V)
будет делать копию передаваемого значения в локальной памяти и модифицировать адрес, пере-
данный в точку, в копии.
Для параметров открытых массивов (переменных или нет), вызывающая процедура будет по-
мещать (перед адресом) размер (2-байтовый) в байтах фактического массива.
Результаты функций
------------------
Результаты из функций возвращаются разными способами, зависящими от их типа.
Типы REAL и LONGREAL возвращаются на вершине стека процессора 8087.
Другие скалярные, небольшие множества, указатели и процедуры-переменные возвращаются в
регистрах 8086-процессора в зависимости от их размера: 1 байт в AL, 2 байта в AX и 4 байта
в DX:AX.
Множества других размеров, массивы и записи возвращаются в стеке под параметрами: пе-
ред помещением параметров вызывающая процедура распределяет требуемую память.
ОПЦИИ (В КОМАНДНОЙ СТРОКЕ)
==========================
Вызывая компилятор, опции определяют, что требуется от него. Они (опции) определяются
после имени файла при вызове компилятора из командной строки MS-DOS или из меню других опе-
рационных сред. Например:
M2 /C MyMain /ML
Опции:
/F - Разрешает, чтобы имена файлов отличались от имен модулей.
/Н - Использованная совместно с Make (см. ниже) покажет, какие файлы нужно перекомпи-
лировать.
/J - Производит небиблиотечные OBJ - файлы, подразумевая, что все они будут включены в
процесс компоновки. Это необходимо для некоторых компоновщиков.
/L - Производит протокол, содержащий информацию о скорости компиляции.
/М - Вызывает утилиту Маке. Файл, переданный компилятору, должен содержать главный мо-
дуль и Маке, основываясь на импорте, будет искать все модули, требуемые программой. Для
каждого из них проверяется, является ли соответствующий OBJ - файл новым, на основании вре-
мени и даты, когда файл использовался. Те, которые необходимо перекомпилировать - переком-
пилируются. Учитываются только те файлы, чьи модули реализации доступны.
/N - Включает строки-номера в OBJ - файл. Это позволяет, например, отладчику знать со-
ответствие между адресами кода и строками исходной программы.
/D - Запрещает реорганизацию выражений. Это гарантирует подсчет выражений слева напра-
во, но результат - в неоптимальном коде.
/Р - Во время компиляции высвечивает имя текущей процедуры для обозначения течения
процесса.
/R - Использованная вместе с Маке, будет рекомпилировать все, вне зависимости от про-
верки. Может быть необходима, поскольку Маке только сравнивает фактическое время/дату фай-
лов; он не читает OBJ - файлы для поиска записи о версии.
/V - Делает все переменные изменчивыми: вместо того, чтобы пытаться сохранить перемен-
ные в регистрах, сохраняет их в памяти. Это может облегчить отладку.
ДИРЕКТИВЫ (В ИСХОДНОМ ТЕКСТЕ)
=============================
Директивы, появляющиеся в исходном тексте, используются для определения различных де-
талей, касающихся того, как должен производиться код. Они определены в специальных коммен-
тариях, где первый символ - $. Каждая директива обозначена одиночной буквой, за которой
обычно следует параметр; несколько директив могут быть даны в одном комментарии, разделен-
ные запятыми.
Большинство директив - флажки: параметр "+" или "-" отмечает, доступен признак или
нет. Они могут быть сброшены до предыдущего значения (перед новой директивой) посредством
"=".
Пример:
(*$V-,M mycod,N*)
....
(*$V=,F*)
Директивы действительны от места, где они впервые встречаются, до конца исходного
текста или пока не отменится другой директивой текущее.
Некоторые директивы, определенные в модуле определений, отменяют любые назначения в
модуле реализации. Это C, G, F, K, N.
Директивы:
$A+/- Разрешает (по умолчанию)/запрещает алиасы для глобальных переменных.
Компилятор будет предполагать, что переменные, объявленные с заблокированной директи-
вой, не могут быть доступны прямо и косвенно в одно и то же время.
$B+/- Включает (по умолчанию)/исключает обработку <УПРСТОП> (Ctrl-Break) в программе.
При включении ее нажатие клавиши <УПР-СТОП> прервет программу; может динамически включать
ся/отключаться библиотечными процедурами. Эта директива должна быть в головном модуле.
$C h Выбирает, какие регистры будут сохранены процедурами. Шестнадцатеричный номер h
определяет регистры: AX=1, CX=2, DX=4, BX=8, DS=10, ES=20, SI=40, DI=80. По умолчанию F0=
DS+ES+SI+DI. BP всегда сохраняется.
$D n Определяет имя n сегмента (данных), в который должны помещаться глобальные пере-
менные, объявленные в модуле. По умолчанию используется имя модуля. В любом случае перед
именем должно быть D_. Эта директива должна появиться перед ключевым словом MODULE как в
описательной, так и в исполнительной частях.
$E+/- Включение/выключение (по умолчанию) упрощенного обращения к вариантам записи по
алиасным именам. Вследствие перекрывания компилятор будет нормально считать изменения полей
вариантных записей, вызывая их в памяти.
$F Процедуры будут вызываться посредством FAR-вызовов. Также процедурные типы имеют 32
бит. Это по умолчанию и относится только к глобальным процедурам. Локальные - всегда NEAR.
$G+/- Включает (по умолчанию)/выключает префиксы модулей во внешних именах. Включение
гарантирует, что внешние имена уникальны.
$H+/- Включает/выключает (по умолчанию) трактование составных констант как переменных,
разрешая их модифицирование. Это возможно, поскольку они находятся в памяти.
$I+/- Включает/выключает (по умолчанию) проверку индекса. В случае включения, обраще-
ние к несуществующему элементу массива вызовет ошибку выполнения. Предполагается, что все
переменные имеют разрешенные значения в соответствии с их типом (см. $R ниже). Также пред-
полагается, что преобразование типов индексов не вызовет проблем.
$J+/- Включение/выключение (по умолчанию) процедур прерывания посредством выработки
возврата IRET вместо обычной команды RET.
$K+/- Включение/выключение (по умолчанию) соглашения по вызовам процедур для языка
"Си". Это определяет, что вызывающая (не вызываемая) процедура убирает параметры и устанав-
ливает DS-регистр на группу, называемую "DGROUP".
$M n Определяет имя (n) (кодового) сегмента, в который поместить код. По умолчанию ис-
пользуется имя модуля. В любом случае имени предшествует С_. Эта директива должна появиться
до ключевого слова MODULE как в файле определения, так и в исполнительном.
$N Процедуры будут вызываться вызовами NEAR. Это требует, чтобы вызывающие процедуры
находились в том же сегменте. Также тип процедуры должен быть 16-битовым.
$O+/- Включает/выключает (по умолчанию) проверку переполнения по всем числовым опера-
циям. При включении числовое переполнение вызовет ошибку выполнения.
$P+/- Включает/выключает (по умолчанию) создание внешних имен для локальных процедур.
Включение упрощает отладку, но может вызвать конфликт имен.
$Q+/- Включает/выключает (по умолчанию) трассировку процедур. При включении процедуры
будут выполняться с командой прерывания 60Н на входе и 61Н на выходе. Обработчики этих пре-
рываний должны быть полностью установлены.
$R+/- Включает/выключает (по умолчанию) проверку подмножеств. При включении ошибка вы-
полнения вырабатывается посредством присвоения и передачи параметров, если значение выходит
за пределы границы типа получателя.
$S h Определяет размер стека в 16-ричном числе "h" для программы. Эта директива должна
быть в головном модуле.
$S+/- Включает/выключает (по умолчанию) проверку переполнения стека. При включении вы-
рабатывается ошибка выполнения в случае, если исчерпан объем стека.
$V+/- Включает (по умолчанию)/выключает копирование параметров значений открытого мас-
сива. Выключение увеличивает эффективность, но потенциально неверно.
$W+/- Включает/выключает (по умолчанию) изменчивость переменных. Изменчивые переменные
не содержатся в регистрах операторов. Это может быть существенно, если конкурирующие про-
цессы взаимодействуют посредством разделенных глобальных переменных. Опция командной строки
/V дублирует эту директиву полностью.
$X+/- Включает/выключает (по умолчанию) слежение за процедурами со стороны процессора
8087. Это необходимо, если вызывающие процедуры вложенных функций исчерпывают стек 8087.
$Y+/- Включение/выключение (по умолчанию) совпадающих вариантных полей. В случае вклю-
чения разрешается использовать одинаковые имена полей в различных вариантных альтернативах
при условии, что они имеют одинаковый тип и находятся на одинаковом смещении в записи.
$Z+/- Включение/выключение (по умолчанию) проверки для разыменовывания указателей NIL,
которые в этом случае вырабатывают ошибку исполнения. Когда директива включена, все локаль-
ные переменные инициализируются в "0". Если включение осуществлено в головном модуле, все
глобальные переменные обнуляются.
ИНТЕРФЕЙС С ДРУГИМИ ЯЗЫКАМИ
===========================
Поскольку компилятор производит стандартные OBJ-файлы, возможно компоновать их с ко-
дом, написанном на других языках и откомпилированным другими компиляторами.
Все, что вызывается из Modula-2, должно быть объявлено в терминах Modula-2, так что
определения модулей (OBJ-файлы) должны быть написаны даже для частей, которые не исполняют-
ся на языке Modula-2. Но настоящий OBJ-файл вырабатывается другим компилятором.
Чтобы это работало, различные части должны согласовываться по структуре выполнения
всей программы. Поэтому надо знать структуру выполнения как Modula-2, так и других исполь-
зуемых языков.
Просмотр MAP-файлов, созданных компоновщиком, оказывает большую помощь при сборке
фрагментов вместе и просто для понимания.
Структура выполнения Modula-2 может быть скроена директивами:
$D - выбор сегмента, куда пойдут данные;
$M - выбор сегмента, куда пойдет код;
$G - выключает префикс имени модуля;
$N - производит процедуры NEAR;
$F - производит процедуры FAR;
$C - выбирает, какие регистры сохраняются процедурами;
$K - следует соглашениям о вызовах языка "Си".
Сегменты, группы и классы
-------------------------
Концепция сегмента - фундаментальна для процессора 8086, и она усовершенствована кон-
цепциями группы и класса в OBJ-языке.
Сегмент - это совокупность элементов, чей общий размер меньше, чем 64К. Имеет имя. Лю-
бой элемент принадлежит одному сегменту.
Группа - совокупность сегментов, чем общий размер также меньше 64К. Также имеет имя.
Любой сегмент принадлежит одной группе или не принадлежит группе.
Во время компоновки множества OBJ-файлов все элементы должны быть упорядочены в физи-
ческой памяти так, чтобы обеспечить наличие элементов одного сегмента или группы в пределах
одной области в 64К.
Сегменты уточняются посредством концепции поименованных классов, которые имеют приори-
тет при упорядочении элементов; элементы с одинаковым именем класса располагаются по со-
седству, в пределах классов элементы из одного сегмента располагаются по соседству. Классы
имеют приоритет, так что если 2 элемента имеют одно имя сегмента, но разные имена классов,
они даже не считаются принадлежащими одному сегменту в 64К.
Компоновщик согласует классы в порядке, в котором они встречаются во время компоновки.
Компилятор использует это для достижения правильного расположения памяти в конечной прог-
рамме: сначала идет код (классы CODE, FCODE), затем глобальные данные (M_DATA), затем сте-
ковые данные (STACK) и, наконец, динамические данные (HEAP).
Компилятор для каждого модуля произведет 4 сегмента и одну группу с именами, получен-
ными из имени модуля:
C_module - содержит код для процедур;
K_module - содержит структурные константы;
S_module - содержит специальные сегментные константы;
D_module - содержит глобальные переменные;
G_module - группа, содержащая С_, К_ и S_сегменты.
Сегменты могут быть переименованы директивами компилятора: $D обращаюся к D_сегменту,
$M к C_, K_, S_сегментам и к G_группе. Это позволяет заставить различные модули использо-
вать одинаковые сегменты: например, используя (*$D DATA *) во всех модулях можно поместить
все глобальные переменные в один 64К- байтовый сегмент.
Следующий сегмент INITCODE содержит инициализационный код для модулей и код для голов-
ного модуля. Если (* $M CODE*) определена, INITCODE и C_CODE помещены в группу, называемую
G_CODE, позволяя всем кодам находиться в пределах одной группы в 64К.
Поскольку имеется одиночный сегмент данных и группа кодов для каждого модуля, их инди-
видуальный код и глобальные данные ограничены 64К байтами каждый. Полная группа может иметь
произвольно большой код и данные.
Адресация элементов
-------------------
Физический адрес состоит из двух частей: адрес сегмента и смещение. Все элементы в од-
ной группе или сегменте имеют один и тот же адрес сегмента, но разные смещения.
Чтобы адресовать элемент, сегментный регистр должен содержать его адрес сегмента. Этот
(неявный) регистр объединяется с явным значением смещения, чтобы адресовать элемент. Вызовы
FAR, с другой стороны, определяют как адрес сегмента, так и смещения явно.
Таким образом, отдельные объекты могут быть доступны без перезагрузки сегментного ре-
гистра, только если они принадлежат одному сегменту или группе. Аналогично, процедура может
быть вызвана только вызовом NEAR, если вызывающая процедура находится в пределах того же
кодового сегмента (так, чтобы CS-регистр не нужно было бы изменять).
Является ли процедура NEAR или FAR (директивы $N и $F), отображается ее командой
RETurn (возврат) - она не должна ничего делать с сегментом, в котором находится, или с чем-
нибудь еще в нем.
Соглашения об именах
--------------------
Различные OBJ-файлы обращаются к элементам друг друга посредством экспортируемых внеш-
них имен. Онм могут быть уникальны и определенны.
Компилятор формирует внешнее имя элемента, используя в качестве префикса перед именем
исходного кода имя модуля, в котором он объявлен. Символы $ или @ отделяют эти два имени; $
для FAR-процедур, @ для NEAR-процедур и данных. Вставку префикса можно отключить директивой
$G.
Элементы, объявленные в локальных модулях непосредственно внутри глобальных модулей,
получают префиксами имена как глобальных, так и локальных модулей, разделенных @.
Пример:
(*$D XYZ*)
DEFINITION MODULE M: (* Сегменты C_M, K_M, S_M, D_XYZ *)
V: INTEGER; (* Внешнее имя M@V (сегмент D_M) *)
PROCEDURE F; (* Внешнее имя M$F (сегмент С_M) *)
(*$N,G-*)
PROCEDURE N1; (* Внешнее имя N1 (сегмент C_M) *)
(*$G+*)
PROCEDURE N2; (* Внешнее имя M@N2 (сегмент С_М) *)
(*$F*)
MODULE L;
PROCEDURE LP; (* Внешнее имя M@L$LP (сегмент С_М) *)
.....
END L;
END M.
ПОДДЕРЖКА СОПРОЦЕССОРА 8087
===========================
Компилятор вырабатывает команды для сопроцессора 8087 для операций с плавающей точкой.
Во время выполнения они будут выполняться самим 80x87-чипом или будут эмулированы программ-
но.
Эмулятор включается, если любая часть программы использует команды с плавающей точкой.
Во время выполнения эмулятор проверяет наличие чипа 80х87 и, если да, перепоправляет вызы-
вающие эмулятор процедуры к 8087-командам. Такой же EXEфайл может, таким образом, выпол-
няться на любой машине с максимально возможной скоростью.
Если известно о наличии 80х87-чипа, для экономии памяти во время компоновки может быть
предусмотрен пустой эмулятор. Это сделано путем замещения файла SYSTEM.OBJ OBJ-файлом, ко-
торый определяет необходимые общие внешние имена в "0"; также должен быть использован дру-
гой MATHLIB.OBJ. Два таких файла поставляются с расширением .7BJ.
Обычно особые ситуации для 8087 запрещены. Программы-обработчики могут быть инсталли-
рованы (установлены) посредством импортирования модуля FloatExc (см. ГЛАВУ 8).
Обработчики прерываний
----------------------
Возможно написать обработчики прерываний на Modula-2, хотя не следует пытаться делать
это без полного понимания процессора 8086 и MS-DOS.
Обработчик прерывания пишется, как процедура Modula-2; директива $J+ даст ей соответс-
твующий оператор возврата и директива $C FF заставит сохранить все регистры. Директива $ W+
может быть использована для сохранения в памяти общих глобальных переменных.
Аппаратные прерывания могут быть включены/выключены процедурами EI и DI из модуля
SYSTEM.
Обработчик устанавливается путем назначения его адреса одному из векторов прерываний в
младших разрядах памяти.
Пример:
MODULE Int;
VAR PrtInt [0:5*4]: ADDRESS;
(* Прерывание 5: печать экрана. *)
OldInt: ADDRESS;
(*$W+*)
Flag: BOOLEAN;
(*$W-*)
(*$J+,C FF*)
PROCEDURE Handler;
BEDIN
...
END Handler;
(*$J-,C F0*)
BEGIN
OldInt := PrtInt;
PrtInt := ADR(Handler);
...
PrtInt := OldInt;
END Int.
Самые предприимчивые смогут также писать программы с возможностью прекратиться и ос-
таться резидентом, используя вызов MS-DOS 031H. Обработка прерываний должна быть отключена
($B-) и стек может быть малым, например, $S 500. Наконец, требования к динамической области
ЕХЕ-файла должны будут удовлетворены с использованием утилит SETHEAPS; в противном случае
не останется памяти для других программ.
Г Л А В А 8
============
БИБЛИОТЕКА JPI Modula-2
=======================
ВВЕДЕНИЕ
========
Эта глава описывает библиотечные модули, поставляемые с компилятором JPI Modula-2. JPI
Modula-2 поставляется с 12-ю различными модулями, все вместе содержат 250 процедур.
Большинство из этих модулей - это обычные модули, написанные на языке Modula-2. Все
они имеют описательную часть Modula-2, но некоторые из исполнительных написаны на языке Ас-
семблера.
Следующие части этой главы описывают каждый модуль в деталях, но вначале представлен
обзор модулей. Описано, также, как обращаться из модуля к модулю.
Модули могут быть разделены последовательно по более абстрактным функциям, где каждый
уровень использует более низкие уровни:
Уровень Модуль
System : SYSTEM
Assembly : AsmLib, MATHLIB
Utility : Str,Lib,Storage,Process,Graph,FloatExc
IO : IO, FIO
Window : Window
|