Многомодульные программы
Язык программирования PLM-51 позволяет писать .
Оттранслированный программный модуль сохраняется в виде отдельного файла в объектном формате, где кроме машинных команд сохраняется информация о именах переменных, адресах команд, требующих модификации при объединении модулей в единую программу и отладочная информация.
Раздельная трансляция программы возможна при использовании двух программ: транслятора исходного текста программы plm-51 и редактора связей rl-51.
На первый взгляд раздельная трансляция не должна вызывать каких либо проблем. Однако это не так. При компиляции исходного текста программы если транслятор обнаружит переменную или подпрограмму, которые не были заранее объявлены, то будет сформировано сообщение об ошибке и объектный модуль будет стёрт с диска компьютера.
Для того, чтобы транслятор вместо формирования сообщения об ошибке записал в объектный модуль информацию, необходимую для редактора связей, нужно осуществить объявление внешних переменных подпрограмм и меток. Для объявления внешних переменных после обычного объявления добавляется слово EXTERNAL. При таком объявлении при трансляции исходного текста программы для переменной память данных для переменных не распределяется, а создаются соответствующие записи для редактора связей, позволяющие осуществить соответствующие вызовы подпрограмм и переходы между модулями, а также обращение к переменным другого модуля. Пример объявления внешних переменных на языке программирования PLM-51:
declare RejRab byte external, UrovGr byte external, NomKan word external, Sost bit external, Soob bit external;В этом объявлении перечисляются переменные, точное значение которых редактор связей должен получить из другого модуля и модифицировать все , в которых эти переменные используются.
Все используемые подпрограммы тоже должны быть предварительно объявлены. При использовании подпрограмм из других модулей они должны быть объявлены как внешние. При этом должны быть полностью объявлены все параметры подпрограмм.
Пример объявления внешних подпрограмм на языке программирования PLM-51:
TestOZU: procedure byte external; end TestOZU;
Rd558: procedure (AdrRAM,NachAdr,Nbyte) byte external; var (AdrRAM,NachAdr,Nbyte )byte; end Rd558;
Wr558: procedure (AdrRAM,NachAdr,Nbyte) byte external; var (AdrRAM,NachAdr,Nbyte )byte; end Wr558;
Для того, чтобы редактор связей мог связать вызов подпрограммы из одного модуля с самой подпрограммой в другом модуле, информация об этой подпрограмме должна быть помещена в объектный модуль. Для этого подпрограмма должна быть оттранслирована с атрибутом PUBLIC. Пример определения подпрограммы, доступной для других модулей, в исходном тексте модуля:
WrNadp: procedure(i,StrPtr) public; declare StrPtr address, char based StrPtr byte constant, i byte;
do while char<>0; BufInd(i)=char; StrPtr=StrPtr+1; i=i+1; end; end WrNadp;
IndNom: procedure public; declare Adres byte; if BufInd(2)=0 then Adres=0; else Adres=8; if RejNab=NabTlf1 then call WrNadp(Adres,.('T1',0)); if RejNab=NabTlf2 then call WrNadp(Adres,.('T2',0)); if RejNab=NabRadA then call WrNadp(Adres,.NadpRa); if Adres=0 then call WrInd; else call InitPolnInd(2); end IndNom; Переменные, к которым можно обращаться из других модулей, тоже должны быть объявлены с атрибутом PUBLIC.
Программа rl-51 объединяет несколько объектных файлов (модулей) в один. Для объединения нескольких модулей в исполняемую программу имена всех модулей передаются в редактор связей в качестве параметров при запуске этой программы. Пример вызова редактора связей из командной строки DOS для объединения трёх модулей:
rl51.exe progr.obj, modul1.obj, modul2.obj В результате работы редактора связей в этом примере будет создан исполняемый модуль с именем progr.
Необходимость предварительного объявления внешних переменных и подпрограмм приводит к тому, что исходный текст программы загромождается этими объявлениями и найти собственно программу становится сложно. Кроме того при таких объявлениях возможно возникновение ошибок. Поэтому лучше вынести объявления подпрограмм и переменных в отдельные файлы, которые затем могут быть подключены в исходный текст программы директивой INCLUDE.
Наименьшая вероятность ошибиться при описании переменных и подпрограмм у программиста, который писал исходный текст модуля, к подпрограммам и переменным которого нужно обращаться из других модулей. Поэтому правила хорошего тона предполагают, что этот программист будет поставлять не только объектный модуль, но и файл описания своих переменных с атрибутом EXTERNAL. Такие файлы называются файлами заголовками и обычно записываются с расширением *.h. Пример исходного текста модуля приведён ниже:
/*Исходный текст модуля comm.plm*/ $CODE $NOLIST Kommand: do; $INCLUDE (C:\COMP\PLM51\BIN\Rg51FA.Dcl) $INCLUDE (stdio.h) /*Подключение других файлов заголовков*/ $INCLUDE (dcl.h) $LIST declare NomPult byte external, Bufer(7) byte external, RejRab byte public, NomKan word public, PrmSoob: procedure using 2; declare i byte; for i=0 to KolBytes; do while not RI;end; BufInd(i)=SBuf; RI=0; end; Soob=true; end PrmSoob; PriemKom: procedure interrupt 4 using 2; KodKom=(SBuf and 0f0h)/16; KolBytes=SBuf and 0fh; RI=0; If KodKom=KomSoob then call PrmSoob; If KodKom=KomSost then call PrmSost; end PriemKom; /*------- Конец модуля ---------*/ Исходный текст файла-заголовка этого модуля:
/*Начало файла заголовка comm.h*/ declare RejRab byte external, NomKan word external, PriemKom:procedure external;end PriemKom; /*------- Конец файла заголовка---------*/ Теперь для того, чтобы воспользоваться приведённым выше модулем достаточно записать строку:
$INCLUDE (comm.h) Естественно, так как процесс трансляции разбит на два этапа, то ошибки могут возникать не только на этапе трансляции модулей, но и при связывании модулей в исполняемую программу. Наиболее распространённые ошибки - это забыть включить имя объектного модуля в строку вызова редактора связей, забыть объявить переменную или подпрограмму как PUBLIC или использовать одни и те же адреса для переменных или констант в различных модулях. Сообщения об этих ошибках выводятся в файл с расширением *.m51.
Полный путь написания программ на языке программирования plm51 показан на рисунке 1 файла .
[] []