Разработка мобильного мультипрограммного обеспечения на базе СП PASCAL-2

Автор: Брусиловский Л.И., Михайлов Ю.А.

Журнал: Компьютерная оптика @computer-optics

Рубрика: Автоматизация проектирования

Статья в выпуске: 8, 1990 года.

Бесплатный доступ

Рассматривается метод реализации в системе программирования (СП) Pascal-2 сопрограмм, аналогичных введенным в язык программирования Modula-2. Описывается возможность разработки мобильного мультипрограммного обеспечения на базе СП Pascal-2, расширенного средствами сопрограмм.

Короткий адрес: https://sciup.org/14058231

IDR: 14058231

Текст научной статьи Разработка мобильного мультипрограммного обеспечения на базе СП PASCAL-2

  • 8    последнее время все большую популярность завоевывают языки высокого уровня, имеющие средства доступа к "нижнему уровню" и позволяющие создавать сложные пакеты программ, обладающих высокой степенью мобильности. В первую очередь это языки ADA [l]z С [2], Modula-2 [3] и диалекты языка Pascal [4]. Сравнение названных языков программирования со стороны разработки мобильного программного обеспечения (кроме Modula-2) приведено в [5].

Язык Modula-2 часто представляется как "Паскаль без недостатков". В то же время в различных реализациях языка Pascal предприняты попытки устранить ряд его "узких мест". В первую очередь это касается мобильной СП Pascal-2 [6,?], реализация которой имеется для таких операционных систем, как RT/11 /TSX-Plus/ SHAREplus, RSX-11M, 1AS, RSTS/E (линия ЭВМ PDP-11), VMS (линия ЭВМ VAX), MS-DOS/PC-DOS (линия ЭВМ IBM РС/ХТ/АТ), VersaDOS (линия ЭВМ на базе микропроцессоров фирмы Motorola) [6-8].

В СП Pascal-2 введены расширения стандартного языка Pascal, которые не только уравнивают его возможности с Modula-2, но в ряде случаев выгодно его отличают. Это, например:

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

  • -    константы с типом;

  • -    работа с файлами прямого доступа;

  • -    возможность обращения к модулям, написанным на других языках программирования .

  • 2.    Подпрограммы и сопрограммы

Кроме того, компилятор Pascal-2 является оптимизирующим, а в СП Pascal-2 имеются мощные средства интерактивной отладки программ на лексике языка высокого уровня и возможности профилирования выполнения программ. Поэтому СП Pascal-2 является реальным конкурентом СП Modula-2 в области создания больших мобильных пакетов программ |Э_11]•

Тем не менее в СП Pascal-2 нет средств, аналогичных механизму сопрограмм (процессов) в языке Modula-2, с помощью которых легко реализуются такие компоненты операционных систем, как, например, мониторы.

8 данной статье предлагаются средства реализации механизма сопрограмм в среде СП Pascal-2.

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

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

Модуль С1                         Модуль С2

Рис. 1. Бесконечная рекурсия при взаимном вызове двух подпрограмм

Модуль С 1

Модуль С2

Рис. 2. Передача управления между

сопрограммами

В языке Modula-2 работа с сопрограммами реализуется с помощью двух процедур, определенных в модуле SYSTEM (NewProcess и Transfer), и двух процедур и одной функции, определенных в модуле STORAGE (Allocate, Deallocate, Available). Кроме того, в модуле SYSTEM определяются типы данных Address и Process,

структура которых является системно-з а в и с имой .

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

Procedure NewProcess (Р, STADDR, 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): соответственно это pRinew, р^ dispose и space. Для удобства их целесообразно привести к виду, совпадающему с видом в Modula-2:

Фрагмент 1  •

<*Qnomain») (♦Bnostacksheck*) function pQinewtSIZE : integer) integer; external; procedure pddispose (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:=pdinew(SIZE) end;

procedure Deallocate;

begi n pQdispose

function Available;

begin

Aval 1able:=space end;

В СП Pascal-2 версии 2.0 и ниже процедуры р Ц inew и р й dispose отсутствуют. Тем не менее их можно реализовать самостоятельно, используя пакет PASMAC [6, 7] :

фрагмент

.title p.Qinew

; function pPinew(SIZE : integer) integer; external;

func    p9inew,PTR,integer,check=O param   SIZE,integer beg i n inc      SIZE(sp > bic     #l,SIZE(sp)

mov       SI ZE(sp) , — (sp>

Jsr     рс,ЯЬ70

.globi  0b70

mov       (sp)+,PTR(sp)

endpr

; procedure pSdispose (P, SIZE : integer); external;

proc pQdispose,check=O par am P,integer par am SI ZE,integer save '.rO> beg i n mov SI ZE J sr pc,ЯЬ72 .globi ЯЬ72 endpr end.

Рассмотрим теперь реализацию процедур NewProcess и Transfer. При создании новой сопрограммы вызовом процедуры NewProcess в структуру данных Process необходимо поместить информацию о стартовом адресе соответствующей процедуры (не имеющей параметров), начальном значении стека (значение, возвращаемое процедурой Allocate, плюс размер рабочей области процесса, т.к. вершина стека при его заполнении смещается сверху вниз) и размере рабочей области (который обычно определяется опытным путем). При создании сопроцесса начальное содержи

мое регистров г0-г5 для него несущественно. Получение адреса загрузки процедуры в СП Pascal-2 рассмотрено в [9]. Тем не менее, в последующем значения регистров г0-г5 необходимо сохранять и восстанавливать. В [12] предлагается сохранять регистры в стеке, однако это сопряжено с необходимостью отслеживать в стеке как область сохранения сопрограммы, так и локальные переменные. Поэтому сохранять регистры г0-г5 удобнее в самой структуре данных Process. С учетом вышесказанного приводим алгоритм:

' фрагмент 3  !

(*Qnomaiп»)

(•Onostacksheck*) type

ADDRESS     = О..65535;

Process     = record

SAVEAREA        : array CO..51 ot ADDRESS;

PC:=P; <* стартовый адрес процедуры P •)

SP:=STADDR+SIZE-2 <* вершина стека рабочей области •) end end;

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

При передаче управления сопрограмме процедура Transfer должна сохранить содержимое регистров г0-г5, убрать из стека аргументы вызова процедуры Transfer и сохранить после этого значение верхушки стека и адрес возврата в вызвав

шую процедуру. Реализация процедуры Transfer, с учетом вышесказанного, возможна лишь на ассемблере с использованием пакета PASMAC. Следует учесть, что при входе в процедуру Transfer вершина стека указывает на адрес возврата в вызвавший модуль, а над ней находятся второй и первый параметры вызова процедуры Transfer. Реализация процедуры Transfer может быть такой:

! фрагмент 4   1

.title Тгansfer ; рабочие* ячейки: WRi.:     .word

WRK1:     .нога

; type ; Process = array CO..7) of integer;

; procedure Transferl var SOURCE, DEST : Process ); proc    Transfer,check—0

param SOURCE,ADDRESS param DEST,ADDRESS beg i n mov     rO,WRK           ; сохранить текущее значение г О mov     SOURCE(sp),ги   ; адрес области сохранения SOURCE

; сохранить в SOURCE регистры г<>-г5 тех       WRK,(г О)*

**v        г !,(гО)4

OOV     г2, <гС> ♦

•, :,.. we "Т . _• . ДрС ООЗбрС: Т,^    . .ЗПОМНИТЬ Б Г1

■:   ' .OURCF «цл ументы Tr ansf er

сохранить правильное значение стека для SOIJRCF mov mov mov r1,(rO)+ (sp),(rO) DEST(sp), rv 5 адрес возврата адрес DFST восстановить mov mov mov mov mov mov mov регистры r0-r5 (rO)+,WRK (rO)+ ,rI (r0)+,r2 (r0)+,r3 (rO)+,r4 (rO)+,r5 (rO)+,sp mov (rO)+,WRK1 * точка возобновления DEST mov WRK,rO восстановить rO jmp endpr end. @WRK I возобновить процесс процесса

DEST

Проверку правильности реализации механизма сопрограмм можно проверить на контрольном примере из [12]:

  • 1    фрагмент 5  '

const MEMREQ = 100; var MAINPRG, Pl, P2 : process; STACK1, STACK1  : integer;

  • I,    J                 : 1nteger;

Xinclude PROSEC; procedure TESTI; begin wri tel n('Первый вход в процедуру TESTI'); Transfer(Pl,MAINPRG);

J:=7;

writeln<'Второй вход в процедуру TESTI ');

Transfer

writeln( Третий вход R процедуру TESTI ); Transfer(Pl,MAINPRG) ; end;

procedure TEST2; var

X : integer; begin writeln('Первый вход в процедуру TEST2');

  • X: = l;

Transfer(Р2,MAINPRG);

writelп( Второй вход в процедуру TEST2, Х= ', X, Л-Transfer(Р2,MAINPRG) ;

end; begi n Al 1ocate(STACK1,MEMREQ); Al 1ocate(STACK2,MEMREQ, ;

NewProcess(TESTI,STACK1,MEMREQ,Pl) NewProcess(TEST2,STACK2,MEMREQ,P2) writeln('Transfer к TESTI');

J: =5;

Transfer(MAINPRG, MAINPRG);

Transfer(MAINPRG,Pl); writeln('Назад из TESTI'); Transfer(MAINPRG,Pl); writeln('Transfer к TEST2 ' >; Transfer(MAINPRG,Pl); writeln('Назад из TEST2'>; Transfer(MAINPRG,Pl); writeln('Назад из TESTI);

Transfer(MAINPRG,p1); writein('В ведущей программе') end.

SAVEAREA    : array CO..5] of integer;

SP           : integer;

FC           : integer;

end;

procedure NewProcesst procedure PROC;

ADR, SIZE   : integer;

var p        : Process ); external;

procedure Transfer! var Pl, P2 : Process ); external;

procedure Al locate( var P : integer; SIZE : integer ); external ;

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

4, Реализация сопрограмм в СП Pascal-1

На малых микроЭВМ типа ДВК до настоящего времени активно используется

СП Pascal-1, которая отличается небольшой потребностью в дисковых ресурсах, хотя и упрощенной реализацией языка Pascal. Практически все вышеуказанные механизмы введения сопрограмм применимы для СП Pascal-1. Так, содержимое файла PROSEC.PAS остается без изменений. Некоторые изменения должны быть внесены в программные модули, т.к. с СП Pascal-1 регистр г5 используется для указателя на область глобальных переменных и не должен изменяться в процессе работы:

! фрагмент 7  !

(* йе+, йа-, fit-, йс .title NewProcee» *) type ADDRESS     = О..65535;

Process     = record

SAVEAREA         : array CO..51 of ADDRESS;

SP,PC            : ADDRESS end; procedure NewProcesst 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-, Sc    .title Transfer *)

procedure Transfer( var SOURCE, DEST : Process );

type

Process

= array CO..7] of integer;

beg i n

(*0c

mov

rO,WRK           ; сохранить текущее значение rO

mov

SOURCE,rO   ; адрес области сохранения SOURCE

; сохранить

в SOURCE регистры r0-r4

mov

WRK,trO) +

mov

г 1, (rO) +

mov

r2,(rO)+

mov

r3, (rO) +

mov

r4,(rO)+

; в вершине

стека адрес возврата — запомнить в rl

mov

sp,r 1

; убрать из

стека SOURCE аргументы Transfer

add

#6, г 1

; сохранить пр апит.ное значение r 1 , (rO)r ,rO i-rwa длм :ТП1 IRCF mov mov , -<дрес nooepara mov ; адрес DEST ; eoccганови! ь mov mov mov mov mov mov mov pei ис i ры r O-r 4 (rO) -►,WRK (rO)+,rl (rO)+,r2 irO)+,r3 (r0)+,r4 (rO)+, sp (rO)+,WRKl ; :очка визобновления процесс mov WRK,rO ; DEST ; носстановить rQ jmp swrk i ; воэпйновить процесс DEST ; рабочие ячейки: WRK: .word WRKJ: .word *) end;

(* det, da-, dt-, de .title MEMMAN ♦ > function space : integer; external;

function psinew(SIZE : integer) integer; external; procedure psdispose (PTR, SIZE : integer); external; procedure Allocate (var PTR : integer, SIZE : integer); begin

PTR:=psinewiSIZE)

end;

procedure Deallocate (P, SIZE s integer);

begi n psdi spose

function Available : integer;

begin

Aval Iables-space end;

  • <♦ Qe+, da-, dt.-, dr. .title psi new *) function pstnew(ST7E : integer) integer; var

PTR : integer;

begin (♦de inc     SIZE(sp)

bi c       * 1 ,SI ZE(sp)

mov      SI ZE(sp),-(sp> jsr     pc,db7O

.glnbl oh 70

mov       +,PTR(sp>

»)

PR! NEW: =PTE:

end; procedure psni^uu- IP, SIZE heg i n

'nteger);

  • -. • Or aw     SIZE! sp ) , rQ

inc     rO

Die      fl , rO mov       P(spf , - (sp)

Jsr      pc,cb?"

.globl  db72

» ) end.

Статья научная