Нужно было реализовать передачу управления из одной процедуры в другую без отношения вложенности.
corutine.pasunit Corutine;
Interface
uses DOS;
type
Myproc = procedure;
Artype = array [0 ..999] of word;
Procdesc = record
ssreg,
spreg: word;
end;
procedure NewProcess (body: Myproc; var proc: Procdesc; var ar: Artype);
procedure Transfer (var OldProc, NewProc: Procdesc);
Implementation
{СОЗДАТЬ_СОПРОГРАММУ}
procedure NewProcess (body: Myproc; var proc: Procdesc; var ar: Artype);
begin
with proc do begin
//ВЫДЕЛИТЬ ПАМЯТЬ ПОД СТЕК;
//ВЫДЕЛИТЬ ПАМЯТЬ ПОД ДЕСКРИПТОР;
//ВЫЧИСЛИТЬ АДРЕС "ДНА" СТЕКА И ЗАПИСАТЬ ЕГО В ДЕСКРИПТОР;
//ПО АДРЕСУ "ДНА" СТЕКА ЗАПИСАТЬ ТОЧКУ ВХОДА В ПРОЦЕДУРУ;
ssreg := seg (ar);
spreg := ofs(ar) + 1998 - 12;
memw[ssreg:spreg+2] := ofs(body);
{Стек - 1000 слов}
memw[ssreg:spreg+4] := seg (body)
end {with}
end {NewProcess};
{ПЕРЕДАТЬ_УПРАВЛЕНИЕ}
procedure Transfer (var OldProc, NewProc: Procdesc);
Assembler;
Asm
//СЧИТАТЬ АДРЕС ДЕСКРИПТОРА ПРИОСТАНАВЛИВАЕМОЙ СОПРОГРАММЫ;
//ЗАПИСАТЬ В ЭТОТ ДЕСКРИПТОР СОСТОЯНИЕ СТЕКА;
//СЧИТАТЬ АДРЕС ДЕСКРИПТОРА ВОЗОБНОВЛЯЕМОЙ СОПРОГРАММЫ;
//ВОССТАНОВИТЬ СОСТОЯНИЕ СТЕКА ИЗ ЭТОГО ДЕСКРИПТОРА;
cli
les di, OldProc
mov es:[di], ss { OldProc.ssreg:= ss}
mov es:[di+2], sp { OldProc.spreg:= sp }
les di, NewProc
mov ss, es:[di] { sp:= NewProc.ssreg }
mov sp, es:[di+2] { sp:= NewProc.spreg }
sti
end {Transfer};
begin
end {Corutine}.
Модуль написал (сверху). Всё это должно было выполняться примерно в таком коде:
Procedure User_N;
Begin
while true do begin
...
if УСЛОВИЕ then {завершение выполнения}
ПЕРЕДАТЬ_УПРАВЛЕНИЕ {в главную программу}
else
ПЕРЕДАТЬ_УПРАВЛЕНИЕ; {в другую сопрограмму}
end;
End;
Begin
СОЗДАТЬ_СОПРОГРАММУ; {User_1}
...
СОЗДАТЬ_СОПРОГРАММУ; {User_N}
ПЕРЕДАТЬ_УПРАВЛЕНИЕ; {в одну из сопрограмм}
End.
Программа не работает. Грешу на процедуру Transfer, но понятия не имею, что не так.
Можете подсказать в чём проблема?