ГЛАВА 3. МОДУЛИ TURBO PASCAL. Читая и изучая главу 1, Вы научились писать стандартные программы на Паскале. Но как быть в случае нестандартного программирования на персональном компьютере, связанного с управлением экрана, вызовами DOS и графикой? Для того, чтобы их писать, необходимо иметь понятия о модулях, аппаратуре компьютера в достаточной степени, чтобы работать с ними. В этой главе описано, что такое модуль, как его использовать, какие модули доступны, как их писать и затем компилировать. Что такое модули? В Turbo Pascal возможен доступ к большому числу встроенных констант, типов данных, переменных, процедур и функций. Некоторые специфичны для Turbo Pascal, другие - для IBM PC и совместимых с ним РС или для DOS. Количество различных программ велико, но почти никогда они все сразу в программах не используются. Все эти программы разделены на связанные между собой группы, называемые модулями, и Вы можете использовать только те модули, которые Вам необходимы. Модуль - это набор констант, типов данных, переменных, процедур и функций. Каждый модуль аналогичен отдельной программе; т.е имеет: главное тело, которое вызывается перед стартом Вашей программы и производит необходимые действия по инициализации, когда это необходимо. Короче говоря, каждый модуль - это библиотека объявлений, которую можно вставить и использовать внутри программы, что позволяет разделить программу на части и компилировать их отдельно. Объявления внутри модуля связаны друг с другом. Например, модуль Crt содержит все объявления для программ работы с экраном РС. Turbo Pascal предоставляет восемь стандартных модулей. Шесть из них System, Overlay, Graph, DOS, Crt, и Printer - осуществляют поддержку Ваших программ на Turbo Pascal; все они сохранены в TURBO.TPL. Две другие - Turbo3 и Craph3 - осуществляют поддержку совместимости программ, написанных в версии 3.0. Более подробно, как их использовать и их основные функции, рассмотрены в главах с 10 по 15 Руководства программиста. Примечание: Turbо Vision предоставляет целый набор модулей. См. руководство по Turbo Vision для деталей. Структура модуля. Модуль обеспечивает набор средств, благодаря возможности использования процедур и функций, поддерживающих константы, типы данных и переменных, но их действительная реализация скрыта из-за того, что модуль разделен на два раздела: интерфейс и реализация. Все объявления и описания модуля становятся доступными программе, использующей его. Структура модуля похожа на структуру программы, но имеет и отличия: unit <идентификатор>; interface uses <список модулей>; {общие объявления} implementation uses <список модулей>; {личные объявления} {реализация процедур и функций} begin {код инициализации} end. Заголовок модуля - слово unit, за которым следует имя модуля - идентификатор. Следующий элемент - ключевое слово interface. Это слово обозначает начало раздела интерфейса модуля, доступного для всех других модулей и программ, использующих этот модуль. В предложении uses указываются модули, которые может использовать этот модуль. Слово uses может появляться в двух местах: - сразу же после слова interface; в этом случае, константы или типы данных, объявленные в интерфейсах этих модулей, могут быть использованы в любых объявлениях. - сразу же после слова implementation; в этом случае, любые объявления этого модуля могут использоваться только внутри раздела реализации. Это так же допускает циклические ссылки модулей; мы покажем как их использовать ниже. Раздел интерфейса. Это "открытая" часть модуля, она начинается ключевым словом interface, следующим сразу за заголовком, и ограничена ключевым словом imрlеmentation. Интерфейс определяет, что является видимым (доступным) для некоторой программы (или других модулей), использующих этот модуль. Любая программа, использующая этот модуль, имеет доступ к этим видимым элементам. В интерфейсе модуля можно объявить константы, типы данных, переменные, процедуры и функции. Как и в программе, они могут быть расположены в любом порядке, т.е разделы могут встречаться повторно (type...var......type...const...var) Процедуры и функции, доступные для программы, использующей этот модуль описываются в разделе интерфейса. А их действительные тела - операторы, реализующие их, - в разделе реализации. Объявление forward не разрешается. Тела всех обычных процедур и функций находятся в разделе реализации после раздела интерфейса, в котором перечислены их имена и заголовки. uses может появиться и в разделе implementation. Если в разделе реализации имеет место uses, то это слово следует сразу же за словом implementation. Секция реализации. Раздел реализации - закрытая, недоступная часть - начинается со слова implementation. Все, что объявлено в части интерфейса видимо для раздела реализации: константы, типы, переменные, процедуры и функции. Кроме того, в разделе реализации могут быть свои собственные дополнительные объявления, недоступные программам, использующим этот модуль. Программы не могут обращаться и ссылаться на них. Однако эти недоступные элементы могут использоваться (и, как правило, это делается) видимыми процедурами и функциями, заголовки которых появляются в разделе интерфейса. Предложение uses может появляться в разделе implementation. В этом случае uses следует непосредственно за ключевым словом implementation. Если процедуры были объявлены как внешние, то в исходном файле должна быть директива {$L имя файла} в любом месте до конца модуля end. Обычные процедуры и функции, объявленные в разделе интерфейса - которые не являются встроенными - должны появляться в разделе реализации. Заголовок procedure (function) в разделе реализации должен быть такой же, как и в разделе интерфейса, или же иметь короткую форму. В краткой форме за ключевым словом (procedure или function) следует идентификатор (имя). Подпрограмма содержит свои собственные локальные объявления (метки, константы, типы, переменые, процедуры и фукции). За ними следует тело главной программы. Например, в разделе интерфейса объявлены: procedure ISwap (var v1,v2: integer); function IMax (v1,V2:integer); Раздел реализации может быть: procedure ISwap; var Temp : integer; begin Temp := V1;V1:= V2;V2 := Temp; end; {процедуры ISwap} function IMax (v1,v2:integer):integer; begin if V1 > V2 then IMax := V1 else IMax := V2 end; {функции IMax} Подпрограммы раздела реализации (неописанные в секции интерфейса), должны иметь полный заголовок procedure/funсtion. Раздел инициализации. Раздел реализации модуля заключен между словами implementation и end. Но если присутствует слово begin перед end, и операторы между этими словами, то получившийся составной оператор, похожий на тело главной программы, становится разделом инициализации модуля. В разделе инициализации инициализируются структуры данных (переменных), используемые модулем или доступные программам, использующим этот модуль. Вы можете использовать этот раздел для открытия файлов. Например, стандартный модуль Printer использует этот раздел для открытия на вывод текстового файла Lst. Файл Lst впоследствии можно использовать в программах, в операторах Write или Writeln. При выполнении программы, использующей некоторый модуль, раздел инициализации вызывается перед выполнением тела главной программы. Если в программе используется несколько модулей, раздел инициализации каждого модуля вызывается (в порядке, указанном в операторе uses программы) до выполнения тела главной программы. Как используются модули? Модули, которые использует Ваша программа, уже откомпилированы и хранятся в специальном машинном коде; это не файлы типа Include. Даже раздел интерфейса хранится в специальном двоичном формате, который использует Turbo Pascal. Более того, стандартные модули хранятся в специальном файле TURBO.TPL и автоматически загружаются в память с Turbo Pascal. В результате подключения модулей к программе увеличивается время и компиляции программы (незначительно, приблизительно на 1 секунду). Если модули загружаются из отдельных дисковых файлов может потребоваться дополнительное время из-за чтения с диска. Для использования модулей необходимо, чтобы в начале присутствовало предложение uses, за которым следует список имен всех модулей, разделенных запятыми. program MyProg; uses thisUnit,thatUnit,theotherUnit; При компиляции этой информации к таблице символов прибавляется информации из раздела интерфейса, а из раздела реализации к самой программе машинный код. Порядок описания модулей в предложении uses не имеет большого значения. Если thisUnit использует thatUnit, то можно объявить их в любом порядке. Компилятор сам определит, который из них должен следовать первым. Иначе говоря, если thisUnit использует thatUnit, а программа MyProg не вызывает какие-либо программы в подпрограмме thatUnit, то можно "спрятать"подпрограммы в программу thatUnit, опуская их в операторе uses: unit thisUnit uses thatUnit ... program MyProg; uses thisUnit,theotherUnit; ... В этом примере thisUnit может вызвать подпрограмму thatUnit, а MyProg - подпрограммы thisUnit и thеоtherUnit. MyProg не может вызвать thatUnit, т.к эта подпрограмма не описана в его предложении uses. Если предложение uses отсутствует, Turbo Pascal подсоединяет стандартный модуль System. Этот модуль обеспечивает выполнение некоторых стандартных подпрограмм Turbo Pascal и программ, специфичных для Turbo Pascal. Ссылки на описание модуля. Если Вы включили модуль в свою программу, то все константы, типы данных, переменные, процедуры и функции, объявленные в интерфейсе этого модуля становятся доступными для Вашей программы. Допустим, есть модуль: unit MyStuff; interface const MyValue := 915; type MyStars=(Deneb,Antares,Betelgeuse); var MyWord : string[20]; procedure SetMyWord(Star : MyStars); function TheAnswer : integer; implementation ... end. Часть модуля, которая описана в интерфейсе, доступна и может быть использована в Вашей программе. Поэтому, можно написать следующую программу: program TestStuff; uses MyStuff; var I : integer; AStar : MyStars; begin Writeln(MyValue); AStar := Deneb; SetMyWord(AStar); Writeln(MyWord); I := TheAnswer; Writeln(I); end. После включения предложения uses MyStuff в программу, появилась возможность ссылаться на все объявления и описания в секции интерфейса модуля MyStuff (MyWord, MyValue,и т.д).Следующая ситуация: program TestStuff; uses MyStuff; const MyValue := 22; var I : integer; AStar : MyStars; function TheAnswer : integer; begin TheAnswer := -1; end; begin Writeln(MyValue); AStar := Deneb; SetMyWord(AStar); Writeln(MyWord); I := TheAnswer; Writeln(I); end. В этой программе некоторые идентификаторы, объявленные в MyStuff, переопределяются. При выполнении эта программа будет использовать собственные описания для MyValue и TheAnswer, так как они были описаны позже, чем в MyStuff. Если нужно использовать идентификаторы из MyStuff, то в этом случае при описании перед каждым идентификатором помещается MyStuff с точкой(.). Например: program TestStuff; uses MyStuff; const MyValue = 22; var I : integer; Astar : MyStars; function TheAnswer : integer; begin TheAnswer := -1; end; begin Writeln(MyStuff.MyValue); Astar := Deneb; SetMyWord(AStar); Writeln(MyWord); I:= MyStuff.TheAnswer; Writeln(I); end. Эта программа отрабатывает так же, как и первая, даже если MyValue и TheAnswer были переопределены. В действительности, первую программу можно было написать: program TestStuff; uses MyStuff; var I : integer; AStar : MyStuff.MyStars; begin Writeln(MyStuff.MyValue); AStar := MyStuff.Deneb; MyStuff.SetMyWord(AStar); Writeln(MyStuff.MyWord); I := MyStuff.TheAnswer; Writeln(I); end. Заметим, что идентификаторы - константы, типы данных, переменые или подпрограммы, могут быть предварены именем модуля. Предложение uses раздела реализации. Как и в версии 5.0, Turbo Pascal дает возможность использовать предложение uses в разделе реализации. Это предложение должно немедленно следовать за ключевым словом implementation так же, как и предложение uses в разделе интерфейса появляется сразу же за ключевым словом interface. Предложение uses в разделе реализации позволяет сделать недоступными некоторые детали модуля, поскольку модули, используемые в разделе реализации, невидимы пользователям этого модуля. Однако более важно, что это так же позволяет Вам конструировать взаимно-зависимые модули. Поскольку в Turbo Pascal модули необязательно должны быть строго иерархическими, Вы можете задавать циклические ссылки модулей. Следующий раздел показывает пример, который демонстрирует необходимость циклических ссылок. Циклические ссылки модулей. Следующая программа показывает, как два модуля могут использовать друг друга. Главная программа Circular вызывает модуль Display. Модуль Display содержит одну программу в разделе интерфейса, WriteXY, которая имеет три параметра: (X,Y) - координаты точки и сообщение, выводимое на экран. Если значение координат (X,Y) находится в пределах видимости на экране, то подпрограмма WriteXY устанавливает курсор в точку с координатами (X, Y) и выводит сообщение. В противном случае вызывается подпрограмма выдачи ошибок. Итак, WriteXY вычисляет координаты для Write. Как подпрограмма выдачи ошибочных сообщений выдает сообщение? Используя опять же подпрограмму WriteXY. Итак, программа WriteXY вызывает подпрограмму ShowError, которая в свою очередь вызывает WriteXY для выдачи сообщения на экран, т.е для расчета координат. Расмотрим программу Circular. Она чистит экран и три раза обращается к программе WriteXY: program Circular; {вывод текста программой WriteXY} uses Crt,Display; begin CirScr; writeXY(1,1,верхний левый угол экрана); writeXY(100,100,может вне экрана); writeXY(81-Length(вернуть в допустимые), 15,вернуть в допустимые); end. Координаты (X,Y) при втором вызове WriteXY установлены жестко как (100, 100) при экране 80x25. Посмотрим, как работает программа WriteXY. Ниже приведен исходный код модуля Display, который содержит процедуру WriteXY. Если координаты (X,Y) действительно находятся в пределах экрана, она выводит сообщение, в противном случае выводится сообщение об ошибке. unit Display; {содержит подпрограмму выдачи сообщений} interface procedure WriteXY(X,Y : integer; Message : string); begin if (X in[1..80]) and (Y in[1..25]) then begin GotoXY(X,Y); Write(Message); end else ShowError(неверны координаты для writeXY) end; end. Процедура ShowError, вызываемая WriteXY, объявлена в следующем ниже тексте модуля Error. Программа ShowError всегда выводит свои сообщения на 25 строке экрана. unit Error; {содержит подпрограмму выдачи ошибок} interface procedure ShowError (ErrMsg : string); implementation uses Display; procedure ShowError (ErrMess : string); begin WriteXY (1, 25, 'Error: ' + ErrMsg); end; end. Отметим, что в модулях Display и Error, в их предложениях uses в разделах реализации есть ссылки этих модулей друг на друга. Эти два модуля могут ссылаться друг на друга в разделах реализации, потому что Turbo Pascal может компилировать полностью интерфейсные разделы для обоих модулей. Другими словами, компилятор Turbo Pascal допускает ссылку на частично откомпилированный модуль А из раздела реализации модуля B, поскольку интерфейсные разделы модулей A и B не зависят друг от друга (и следовательно, соответствуют строгим правилам Паскаля для порядка объявлений). Разделение других объявлений. Предположим, Вы хотите модифицировать программы WriteXY и ShowError так, чтобы добавить дополнительный параметр, который задает прямоугольное окно на экране: procedure writeXY(SomeWindow:Wind Rec; X, Y : integer; Message : string); procedure ShowError (SomeWindow : WindRec; ErrMsg : string); Вспомним, что эти процедуры находятся в разных модулях. Даже если объявить WindData в разделе интерфейса одного модуля, то это объявление не будет доступно в разделе интерфейса другого модуля. Лучше объявить третий модуль, который состоит из одних объявлений записи окна: unit WindData; interface type WinDRec = record X1, Y1, X2, Y2 : integer; ForeColor, BackColor : byte; Active : boolean; end; implementation end; Сейчас интерфейсные разделы обоих модулей Display и Error могут видеть WindData. Это допустимо, потому что в модуле WindData нет предложения uses, а модули Display и Error имеют ссылки друг на друга в разделе implementation (реaлизации). Стандартные модули. Файл TURBO.TPL содержит все стандартные модули, кроме Graph и модулей совместимости (Graph3 и Turbo3): System, Overlay, Crt, Dos и Printer. Эти модули загружаются в память вместе с Turbo Pascal; они всегда доступны для любой программы. Файл TURBO.TPL хранится в том же справочнике, что и TURBO.EXE (или TPC.EXE). System. Модуль System содержит все стандартные и встроенные процедуры и функции Turbo Pascal. Любая подпрограмма Turbo Pascal, не являющаяся стандартной и не находящаяся ни в одном другом модуле, находится в System. Этот модуль присоединяется к каждой программе. Модуль System детально описан в главе 10 "Модуль System" Руководства программиста. Dos. Dos определяет многочисленные процедуры и функции Turbo Pascal, которые эквивалентны наиболее часто используемым вызовам Dos, таким как GetTime, SetTime, DiskSize и т.д. Кроме того, здесь определяются две программы низкого уроня - MsDos и Intr, которые позволяют использовать любой вызов MS-DOS или системные прерывания. Registers - тип данных для параметров в MsDos и Intr. Кроме того, определяются некоторые другие константы и типы данных. Модуль Dos детально описан в главе 11 "Модуль Dos" Руководства программиста. Overlay. Модуль Overlay обеспечивает поддержку системы оверлеев. Более подробно Overlay описан в главе 13 "Оверлеи" Руководства программиста. Crt. Crt обеспечивает набор специальных средств объявлений для ввода/вывода на PC: констант, переменных и программ. Их можно использовать для работы с экраном (работа с окнами, управление курсором, управление цветом). Есть возможность вводить с клавиатуры и управлять звуковым сигналом. Более подробно Crt описан в главе 15 "Модуль Crt" Руководства программиста. Printer. В модуле Printer объявляется переменная текстового файла LST, которая связывается с драйвером устройства, позволяя посылать стандартный вывод на печатающее устройство, используя Write и Writeln. Например, включив модуль Printer в программу, можно сделать следующее: write (Lst,'The sum of',A:4,'and',B:4,'is'); c:=A+B; writeln (Lst,c:8); Graph. Этот файл не входит в файл TURBO.TPL, но должен находиться в том же вместе, где и вспомогательные файлы, расширения которых .BGI и .CHR. Поместите GRAPH.TPU в текущий справочник или используйте справочник модулей для указания полного пути до GRAPH.TPU. (Если Вы используете жесткий диск и программу Install, Ваша система уже установлена так, что Вы можете использовать Graph). Файл Graph - это набор быстродействующих эффективных графических подпрограмм, которые позволяют в полной мере использовать графические возможности PC. Этот модуль реализует независимый от устройства графический драйвер, поддерживающий графические адаптеры CGA, EGA, Hercules, AT&T400, MCGA, 3270 PC, VGA и 8514. Дополнительное описание Graph и графического интерфейса фирмы Borland (BGI) можно найти в главе 12 "Модуль Graph и BGI" Руководства программиста. Turbo3 и Graph3. Эти модули предназначены только для совместимости. Turbo3 содержит 2 переменные и несколько процедур, не поддерживаемых Turbo Pascal. Graph3 поддерживает полный набор графических программ версии 3.0. Полная информация по эти модулям включена в файл TURBO3.INT. После введения в эти модули давайте посмотрим собственные модули. Создание собственных модулей. Вы написали модуль IntLib, поместили в файле INTLIB.PAS и откомпилировали; результат компиляции - файл INTLIB.TPU. Для того, чтобы можно было его использовать в программе, его необходимо описать в операторе uses. Таким образом программа будет выглядеть: program MyProg; uses IntLib; Заметим, что Turbo Pascal предполагает, что файл, в котором находится модуль, имеет такое же имя (до 8 символов), что и имя модуля. Если Ваш модуль - MyUtilities, то Turbo Pascal ищет файл с именем MYUTILIT.PAS. Компиляция модулей. Модуль компилируется также как и программа: создается при помощи редактора, вызывается команда Compile/Compile (или Alt-F9). Но, вместо файла с расширением .EXE, создается файл с расширением .TPU (модуль Turbo Pascal). Можно оставить этот файл, как одиночный файл. Можно поместить его в TURBO.TPL при помощи TPUMOVER.EXE. В любом случае, Вы можете поместить файл .TPU в справочник модулей, который Вы задаете в окне ввода Unit Directories (Options/ Directories). Таким образом, Вы можете ссылаться на эти файлы, когда они не находятся в текущем справочнике или в TURBO.TPL. (Эта команда позволяет дать несколько справочников для поиска модулей). Вы можете иметь только один модуль для исходного файла; компиляция останавливается, когда достигается последний оператор end. Чтобы найти модуль, указанный в операторе uses, компилятор вначале просматривает резидентные модули - модули, загруженные в память во время запуска компилятора Turbo Pascal из TURBO.TPL. Если этого модуля нет среди резидентных, компилятор считает, что он должен быть на диске. Он считает, что модуль должен иметь расширение .TPU. Он вначале ищет в текущем справочнике, а затем в справочниках, заданных командой O/D/Unit Directories или директивой /U в командной строке TPC. Например, конструкция uses Memory; где Memory не резидентный модуль заставляет компилятор искать MEMORY.TPU в текущем справочнике, а затем в каждом из справочников модулей. Когда команды Compile/Make и Compile/Build компилируют модули, заданные в операторе uses, исходные файлы ищутся так же, как и .TPU файлы и имя исходного файла модуля принимается то же, что и имя модуля с расширением .PAS. Пример. Напишем небольшой модуль. Назовем его IntLib и поместим в него две простые программы: процедуру и функцию: unit IntLib; interface procedure ISwap (var I, J : integer); function IMax (I, J : integer) : integer; implementation procedure ISwap; var Temp : integer; begin Temp := I; I := J; J := Temp; end; {of proc ISwap} procedure IMax; begin if I > J then IMax := I else IMax := J; end;{функции IMax} end.{модуля IntLib} Сохраним его в файле INTLIB.PAS и откомпилируем его. Результирующий код помещается в файл INIT.TPU. Поместите его в справочник модулей, если он есть, или оставьте в том же справочнике, где находится программа. Следующая программа использует модуль IntLib: program IntTest; uses IntLib; var A, B : integer; begin Write ('Enter two integer values : '); Readln (A, B); ISwap (A, B); Writeln ('A= ', A, 'B= ', B); Writeln ('The max is ', IMax (A, B); end. {программы IntTest} Поздравляем! Только что вы создали модуль и программу, которая его использует. Модули и большие программы. До сих пор мы использовали библиотеки модулей (набор полезных программ) и отдельные программы, которые используются несколькими программами. Другой случай использования модулей - построение больших программ. Существует два аспекта в Turbo Pascal, позволяющих использовать модули: - Turbo Pascal имеет огромную скорость компиляции и редактирования; - Turbo Pascal может управлять несколькими файлами кода одновременно, такими как программа и модули. Обычно большая программы делится на модули, которые группируют процедуры по их функциям. Например, программы редактора можно разделить на инициализацию, вывод, чтение и запись файла, форматирование и т.д. Так же может быть глобальный модуль - модуль используемый всеми другими модулями, а так же главной программой - он определяет глобальные константы, типы данных, переменные, процедуры и функции. Схема большой программы: program Editor uses DOS,Crt,Printer {стандартные модули из TURBO.TPL} EditGlobals, {модули, написанные пользователем} EditInit, EditPrint, EditRead, EditWrite, EditFormat; {объявления программы,процедуры и функции} begin {главная программа} end.{программы Editor} Заметим, что модули этой программы могут находиться в TURBO.TPL или существовать как отдельные .TPU файлы. В последнем случае, Turbo Pascal будет управлять Вашим проектом. Это значит, что при перекомпиляции программы Editor, Turbo Pascal, проверив дату файлов .PAS и .TPU, перекомпилирует только те модули и файлы, которые были модифицированы. Другая причина использования модулей в больших программах определяется ограничением размера кодовых сегментов. Процессор 8086 (и совместимые с ним) ограничивают размер сегмента кода до 64К. Это значит, что главная программа и любой сегмент не может превышать 64 К. Turbo Pascal позволяет снять ограничения, помещая каждый модуль в отдельный сегмент. Верхняя граница определяется памятью машины (PC) и операционной системой, то есть 640К на большинстве PC. Без использования модулей размер программы ограничен до 64К кода (См.главу 6 "Управление проектом" для получения более подробной информации о больших программах). Оверлейные модули. Бывают случаи, когда невозможно загрузить все Ваши модули из-за недостатка памяти. Может быть потому, что память для работы меньше 640К, или потому, что Вам требуется больше памяти под данные. Другими словами, загрузочный модуль в данный момент не помещается в памяти. Turbo Pascal предлагает решение - оверлеи. Оверлей - это кусок программы, загружаемый в память, когда необходимо, и затем выгружаемый из нее. Это значит, что в память программа загружается не вся, а частями по необходимости. Оверлеи в Turbo Pascal базируются на модулях. Наименьшая часть кода, которая может быть загружена или выгружена - это модуль. Вы можете определить сложный набор оверлеев, указав какие модули могут или не могут быть в это время в памяти. Работой оверлеев управляет специальная интеллектуальная программа - монитор оверлеев. Для детального изучения оверлеев, как описать их и использовать читайте главу 13 Руководства программиста "Оверлеи". Утилита TPUMOVER. Допустим, что нужно добавить к стандартным модулям в TURBO.TPL написанный и отлаженный модуль для того, чтобы он автоматически загружался в память при компиляции. Как поместить его в библиотеку стандартных модулей Turbo Pascal? Это можно сделать при помощи утилиты TРUMOVER.EXE. Кроме того, эта утилита ипользуется для пересылки и удаления модулей из библиотечного файла с целью уменьшения размера TURBO.TPL и экономии памяти при его загрузке. Более подробно об утилите TРUMOVER смотрите в Приложении А. Как Вы поняли, писать собственные модули не сложно. Удачно сконструированный и реализованный модуль только упрощает разработку сложных программ. Проблема решается только один раз, а не повторно для каждой программы. Более того, использование модулей обеспечивает эффективное и простое средство для создания очень больших программ.