Л.И. Брусиловский, Ю.А. Михайлов
РАЗРАБОТКА МОБИЛЬНОГО МУЛЬТИПРОГРАММНОГО ОБЕСПЕЧЕНИЯ НА БАЗЕ СП PASCAL-2
1. Введение
В последнее время все большую популярность завоевывают языки высокого уровня, имеющие средства доступа к "нижнему уровню" и позволяющие создавать сложные пакеты программ, обладающих высокой степенью мобильности. 3 первую очередь это языки ADA [l]/ С[2], Modula-2 [3] и диалекты языка Pascal [4]. Сравнение названных языков программирования со стороны разработки мобильного программного обеспечения (кроме Modula-2) приведено в [5].
Язык Modula-2 часто представляется как "Паскаль без недостатков". В то же время в различных реализациях языка Pascal предприняты попытки устранить
ряд его "узких мест". В первую очередь это касается мобильной СП Pascal-2 [6,7], реализация которой имеется для таких операционных систем, как RT/11 /TSX-Plus/ SHAREpluS, RSX-11M, 1 A S , RSTS/E (линия ЭВМ PDP-11), VMS (линия ЭВМ VAX), MS-DOS/PC-DOS (линия ЭВМ IBM PC/XT/AT), VersaDOS (линия ЭВМ на базе микропроцессоров фирмы Motorola) [6-8].
В СП Pascal-2 введены расширения стандартного языка Pascal, которые не только уравнивают его возможности с Modula-2, но в ряде случаев выгодно его отличают. Это, например:
- возможность передачи в качестве параметров многомерных массивов с переменными границами;
- константы с типом;
- работа с файлами прямого доступа;
- возможность обращения к модулям, написанным на других языках программирования .
Кроме того, компилятор Pascal-2 является оптимизирующим, а в СП Pascal-2 имеются мощные средства интерактивной отладки программ на лексике языка высокого уровня и возможности профилирования выполнения программ. Поэтому СП Pascal-2 является реальным конкурентом СП Modula-2 в области создания больших мобильных пакетов программ 1Э-П].
Тем не менее в СП Pascal-2 нет средств, аналогичных механизму сопрограмм (процессов) в языке Modula-2, с помощью которых легко реализуются такие компоненты операционных систем, как, например, мониторы.
В данной статье предлагаются средства реализации механизма сопрограмм в среде СП Pascal-2.
2. Подпрограммы и сопрограммы
Основное различие между сопрограммами и подпрограммами заключается в том, что выполнение сопрограмм может быть
приостанов лено с сохранением контекста значений локальных переменных, пока процессор занят выполнением некоторой другой работы, а потом возобновлено с точки останова в старом контексте. При вызове подпрограммы ей передается управление на одну из точек входа. Контекст локальных переменных вызывающей подпрограммы сохраняется, а ее выполнение будет возобновлено со следующего за вызовом оператора после полного завершения работы вызванной подпрограммы, причем контекст вызванной сопрограммы не сохраняется. Повторное обращение к вызываемой подпрограмме вновь передаст управление на одну из точек входа в новом контексте.
Наглядно различие между со- и подпрограммами можно увидеть на примере совместной работы двух модулей, обращающихся друг к другу. В случае подпрограмм такие взаимные обращения приводят к бесконечной рекурсии (что, впрочем, может быть предусмотрено алгоритмом). В случае сопрограмм сохраняется последовательное выполнение. Схематически различие между со- и подпрограммами показано на рис. 1 и рис. 2.
вызов С2
Л h
х
J V_
вызов С 1
Модуль С1 Модуль С2
Рис. 1. Бесконечная рекурсия при взаимном вызове двух подпрограмм
вызов С2
вызов С2
/
Ч h
ч /—
—< А
_/
вызов С 1
вызов С 1
Модуль С1 Модуль С2
Рис. 2. Передача управления между сопрограммами
В языке Modula-2 работа с сопрограммами реализуется с помощью двух процедур, определенных в модуле SYSTEM (NewProcess и Transfer), и двух процедур и одной функции, определенных в модуле STORAGE (Allocate, Deallocate, Available). Кроме того, в модуле SYSTEM определяются типы данных Address и Process,
структура которых является системнозависимой .
Преобразование процедуры, не имеющей параметров, в сопрограмму (т.е. в Process) выполняется при вызове процедуры NewProcess, заголовок которой обычно имеет вид:
Procedure NewProcess (Р, ST A DDR, SIZE : Address;
var PROC : Process): external;
3, Реализация сопрограмм в СП PASCAL-2
Наличие в СП Pascal-2 средств раздельной компиляции внешних процедур и функций, связи с ассемблером и ряда средств нижнего уровня позволяет реализовать на Pascal-2 механизм сопрограмм, а возможность включения модулей исходного текста на этапе компиляции (директива ^include) позволяет записать определения необходимых структур данных и заголовков внешних процедур и функций в некоторый файл, который можно рассмат-
ривать как аналог модуля определений в языке Modula-2.
Как уже отмечалось, для реализации работы с сопрограммами в среде Pascal-2 в стиле языка Modula-2 необходимо смоделировать структуру данных Process, процедуры NewProcess, Transfer, Allocate и Deallocate, а также функции Available языка Modula-2.
Аналоги процедур Allocate и Deallocate, а также функции Available имеются в СП Pascal-2 (версии, начиная с 2.1): соответственно это pftinew, dispose и space. Для удобства их целесообразно привести к виду, совпадающему с видом в Modula-2:
Фрагмент 1 •
(»ftnomain») (■»finostacksheck*)
•function p9inew(SIZE : integer) integer; external ; procedure pSdispose (PTR, SIZE : integer); external; ■function space : integer; external;
procedure Allocate <var PTR : integer, SIZE : integer); external;
procedure Deallocate <P, SIZE : integer); external;
function Available : integer; external;
procedure Allocate;
begi n
PTR:=poi new(SIZE)
end;
procedure Deallocate; begi n
pSdispose (P, SIZE)
end;
•function Available; begi n
Aval 1able:=space
end;
В СП Pascal-2 версии 2.0 и ниже процедуры р $ inew и р jj dispose отсутствуют. Тем не менее их можно реализовать самостоятельно, используя пакет PASMAC [6, 7]:
фрагмент 2
.title poinew ■function pOinewiSIZE
tunc par am beg l n l nc bi с mnv jsr
. globi mov endpr
procedure pOdispose <P,
integer) integer; external;
pQinew,PTR,lnteger,check=0 51 ZE,i nteger
SIZF(sp) »1,SIZE(sp) SIZE(sp),-<sp) pc,Sb70 ЙЬ70
(sp)+,PTR(sp)
pr oc
param
par am
save
begi n
mov
l nc
bic
mov
jsr
.globi endpr end.
pOdispose,check=0 P,integer SIZE,lnteger
<rO>
SIZE(sp),rO rO
#1 ,rO
P(sp),—(sp) pc,fib72 ЙЬ72
IZE : integer); external;
Рассмотрим теперь реализацию процедур NewProcess и Transfer. При создании новой сопрограммы вызовом процедуры NewProcess в структуру данных Process необходимо поместить информацию о стартовом адресе соответствующей процедуры (не имеющей параметров), начальном значении стека (значение, возвращаемое процедурой Allocate, плюс размер рабочей области процесса, т.к. вершина стека при его заполнении смещается сверху вниз) и размере рабочей области (который обычно определяется опытным путем). При создании сопроцесса начальное содержи-
мое регистров г0-г5 для него несущественно. Получение адреса загрузки процедуры в СП Pascal-2 рассмотрено в [9] Тем не менее, в последующем значения регистров г0-г5 необходимо сохранять и восстанавливать. В [12] предлагается сохранять регистры в стеке, однако это сопряжено с необходимостью отслеживать в стеке как область сохранения сопрограммы, так и локальные переменные. Поэтому сохранять регистры г0-г5 удобнее в самой структуре данных Process. С учетом вышесказанного приводим алгоритм:
! фрагмент 3 !
(•Qnomaiп*) <*flnostасkshecк*) type
ADDRESS = О..65535;
Process = record
SAVEAREA : array CO..53 o+ ADDRESS;
SP,PC : ADDRESS
end;
procedure NewProcess« P,STADDR, SIZE : ADDRESS;
var PROS: Process ); external;
procedure NewProcess; begi n
with PROC do begin
PC:=P; <* стартовый адрес процедуры P *)
SP:=STADDR+SIZE-2 (* вершина стека рабочей области ♦)
end
end;
Компиляция с ключом Д nostacksheck шую проц
необходима для отмены проверки перепол- Transfer
нения стека, поскольку стек сопроцесса можна ли
берется из хипа программы. нием пак
При передаче управления сопрограмме при вход
процедура Transfer должна сохранить со- стека ук
держимое регистров г0-г5, убрать из сте- звавший
ка аргументы вызова процедуры Transfer второй и
и сохранить после этого значение вер- цедуры Т
хушки стека и адрес возврата в вызвав- Transfer
едуру- Реализация процедуры , с учетом вышесказанного, воз-шь на ассемблере с использова-ета PASMAC. Следует учесть, что е в процедуру Transfer вершина азывает на адрес возврата в вы-модуль, а над ней находятся
первый параметры вызова про-ransfer. Реализация процедуры может быть такой:
.titIP Transfer ; patlrv-u-ir? iineiiKM: WRI-: .wore
UlRk 1 : .word ; type
; Process = array CO..?] n-f .nti-ger: ; procedure Transterl vdr SQURC.E, DEST proc Transfer,checfc-O fioram SOURCE , ADDRESS DEST,ADDRESS
фрагмент 4
Process );
p '} r am Ijegi n roov itiov
сохранить в точ
rO,WRK
SOURCE <sp> ,гО SOURCE регистры rO-r5 WRK,(rO>♦
Г',(rO)4 rZ, lr( >»
сохранить текущее знамение rO адрес области сохранения SOURCE
.-».про-.,г 1 '.ПиГ:СР
¡ьэсрй г..
цл умвмги Transfer
б г 1
сохранить правильное значение? стека лля SnilRCF-mov r1,(rO)+
mov (sp),<r0>
mov DEST (rvp) , ru
вогстановить регистры rO-r5
адрес возврата адрес DFST
mov mov mov mov mov mnv mov mov
mov jmp endpr end.
(rO>+,WRK (rO)+,rt <r0)+,r2 (r0)+,r3 (rO)+,r4 IrO)+,r5 (r0) + , sp (rû)+,WRK1
WRK,r0 @WRK I
точка возобновления процесса DEST
восстановить rO возобновить процесг DEST
Проверку правильности реализации механизма сопрограмм можно проверить на контрольном примере из [12]:
const
MEMREQ
= 100;
фрагмент
MAINPR6, PI, Р2 : process; STACK1, STACK1 : integer; I, J : lnteger;
■/.include PROSEC; procedure TEST1; begi n
wr iteln('Первый вход в процедуру TFST1');
Trans-fer (PI ,MAINPRG) ;
J:=7;
wrlteln('Второй вход в процедуру TFST1 '); Trans-fer (Г1 ,MAI MPRCi) ;
writeln( Третий вхпл в процедуру TCST1 '); Transfer(PI,MAINPRG) ;
end;
procedure TEST2; var
X : integer; begin
writeln('Первый вход в процедуру TFST2 ' ); X:=l;
Transfer <P2,MAINPRG);
writelr. ( Второй вход в процедуру TEST?, х = Trans-fer (Р2,MAINPRG) ;
end; begi n
All ocate(STACK1,MEMREQ);
Allocate(STACK2,MEMREQ);
NewProcess(TEST1,STACK1,MEMREQ,PI)
NewProcess(TEST2,STACK2,MEMREQ,P2)
wr l teln ('Trans-fer к TEST1 ' ) ;
J: =5;
Tr ansf er(MAINPRG, MAINPRG);
J ) :
end.
Trans-fer (MAINPRG,PI ) ; Trans-fer (MAINPRG,PI ) ; Trans-fer (MAINPRG,PI ) ; Trans-fer (MAINPRG,PI ) ; Trans-fer (MAINPRG,PI) ;
wrlteln('Назад из TEST 1'); wri tel n ('Trans-fer к TEST2 ' > ; writeln('Назад из TEST2'); writeln('Назад из TEST 1 ); writeln('B ведущей программе')
Файл PROCES.PAS, включаемый во время компиляции, содержит следующие описа-
фрагмент ь
(»ftnostасkshecк*) type
PROCESS = record SAVEAREA SP PC
end;
procedure NewProcess( procedure PROC;
ADR, SIZE : integer; var P : Process ); external;
procedure Iransierl var PI, P2 : Process ); external; procedure Allocatei var P : integer; SIZE : integer ); external;
array CO..53 of integer; i nteger; lnteger;
Если в программах, ис процессы, применяется апп метика с плавающей точкой с набором команд РРР), то димо сохранять аккумулято арифметики. Поскольку это роны, тривиально, а с дру используется не часто, то этих аккумуляторов мы не
пользующих со-аратная ариф-(сопроцессор также необхо-ры плавающей , с одной сто-гой стороны,
сохранение рассматривали,
4, Реализация сопрограмм в СП Рабсаь-!
На малых микроЭВМ типа ДВК до настоящего времени активно используется
СП Pascal-1, которая отличается небольшой потребностью в дисковых ресурсах, хотя и упрощенной реализацией языка Pascal. Практически все вышеуказанные механизмы введения сопрограмм применимы для СП Pascal-1. Так, содержимое файла PR0SEC.PAS остается без изменений. Некоторые изменения должны быть внесены в программные модули, т.к. с СП Pascal-1 регистр г5 используется для указателя на область глобальных переменных и не должен изменяться в процессе работы:
! фрагмент 7 !
(* йе+, йа-, Bt-, йс .title NewProce«« ») type
ADDRESS = O..65535;
Process = record
SAVEAREA : array CO..5] of ADDRESS;
SP,PC : ADDRESS
end;
procedure NewProcessf P,STADDR, SIZE : ADDRESS;
var PROS: Process >; external;
procedure NewProcess; begi n
with PROC do begin
PC:=P; (* стартовый адрес процедуры P *)
SP:=STADDR+SIZE-2 (* вершина стека рабочей области »>
end
end;
<* йе+, йа-, fit-, йс .title Transfer *)
procedure Transfer( var SOURCE, DEST : Process ); type
Process = array CO..73 of integer; begi n (*йс
mov rO,WRK ; сохранить текущее значение гО
mov SOURCE(sp) ,rO ; адрес области сохранения SOURCE
; сохранить в SOURCE регистры r0-r4 mov WRK,(r0)+
mov г 1, (rO) +
mov r2,(rO)+
mov r3,(rO)+
mov r4,(rO)+
; в вершине стека адрес возврата - запомнить в rl
mov sp , г 1
; убрать из стека SOURCE аргументы Transfer add #6,rl
; сохранить пропит.ное значение? t'rw.'ii дпч ЯП1IRHF
mov г 1,< г О)f
mov < sp) , (г')) , члрес позоратл
mov DES1 < sp) , rO ; адрьч. DEST
; восстановить peiiicipbi r O-i 1
mov (rO)+,WRK
mov irO)+,rl
mov (r0)+,r2
mov ir0> +,r 3
mov (rO>+,rA
mov (rO)+,sp
mov <rO) + ,WRK3 $ ¡очка позобноиленим процесса
i CFST
mov WRK,rO ; иосстановить rO
jmp GWRK1 ; возобновить процесс DEST
; рабочие ячейки: WRK: .word
WRK]: .word *)
end;
<* ве+, Oa-, Ot-, fic .title MEMMAN *) ■function space : integer; external;
function psinewtSIZE : integer) integer; external; procedure psdispose (PTR, SIZE : integer); external; procedure Allocate (var PTR : integer, SIZE : integer); begin
PTR: =ры new iSIZE)
end;
procedure Deallocate (P, SIZE : integer); begin
psdi-spose (p, PI ZD
end;
function Avail'ihli? : integer; begin
Aval i at) 1 e: -- apace
end;
(* Oe+, <3a-, ot. - , .title psinew »)
function psi n!?w (ПТ 7Г: : integer) integer; var
PTR : lnteger; begin (♦dc
inc SIZEtsp)
bic #1,SIZE <sp)
mov SIZE<sp)<sp)
jsr pr,db7o
.glob I r>h 7Cf mov < <*p i + , PTR (sp )
»)
Pf? T NFW: "=P ГП'
end ;
procedure рчИ) «-.p. ip, flTZf : integer);
lieg i ii
\ »Or
■nov SI Zr < =>p > ,r-0
mc г О
tu с fl ,ri)
mov P< sp> , - i sp >
j'.-r pc,ob7"
.globi 0Ь7Г
* i
end.
Литература
1. Язык программирования АДА. ГОСТ 27S3I-SB (ИСО 8652-87J.
2.Керниган Б., Р и т ч и Д., Ф ь ю э р А. Язык программировании СИ. Задачи по языку СИ. f., Финансы и статистика, 19 8 5 .
J. В и р т Н. Программирование на языке Модула-2. М., Мир, 1987.
. В и р т Н., tf е н с е н К. Паскаль: руководство для пользователя. М., Финансы и статистика, 1989-
3. Языки программирования АДА, СИ, ПАСКАЛЬ. Сравнение и оценка (под ред. Днехани Н.). М., Радио и связь, 1989-
6. Pascal-2. Version 2.0 for RT-11, Oregon MiniSoftware Inc., 1961.
7. Pascal-2. Version 2.1 for RSX-11, Oregon MiniSoftware Inc., 1983.
8. S о u t e r J., D a v i e s M. British Standard Time, Pers. Comput. World, 1988, v. 11, N 6.
9. Брусиловский Л.И., Михайлов Ю.А. Организация взаимодействия межъязыковых модулей (Pascal-2 - Fortran-IV) в операционных системах RSX-11M и R Т — 1 1 . - В сб. "Компьютерная оптика", вып. к. М., МЦНТИ, 1989.
10. Брусиловский Л.И., Михайлов Ю.А. Разработка мобильного программного обеспечения для ЭВМ линии PDP-11 и VAX. - В сб. Компьютерная оптика", вып. 7- М., МЦНТИ, 1990.
11. Михайлов Ю.А. Программирование системных вызовов на Pascal-2 в операционных системах РАФОС и ДОС КП (краткое сообщение). Управляющие системы и машины, С 5. 1989.
12. Beer J., R о j а s R. Coroutinen in С und Pascal, mc: Die Mikrocomputer-Zeitschrift, 1987, N 7.