Предыдущий раздел УПРАВЛЕНИЕ ПАМЯТЬЮ И ЗАПУСК ПРОГРАММ Следующая глава

18.3.2. Многопрограммный редактор - программы

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

Одновременно с запуском дочерней программы программа Dispatcher передает ей на вход данные, предназначенные для обработки в запускаемой программе. В качестве таких данных используется совокупность глобальных переменных, примером которых является Sector. Несмотря на то, что эти глобальные переменные использовались нами и ранее для информационной взаимосвязи между модулями программы, механизм их передачи теперь будет другой. Дело в том, что в отличие от процедур, входящих в состав одной программы, программы не имеют общих областей (разделов) памяти. Поэтому передаваемые данные включаются или в состав «наследуемых» данных – в состав PSP и блока окружения, или передающая программа передает с помощью PSP адрес области ОП, которая содержит входные данные.

Второй из этих подходов и будет использоваться нами в многопрограммном редакторе с тем отличием, что каждая из взаимодействующих программ имеет дело со своим набором глобальных переменных. Сразу же после своего инициирования дочерняя программа копирует в свою собственную память набор глобальных переменных, принадлежащий программе Dispatcher. И, наоборот, перед своим завершением дочерняя программа выполняет обратное копирование глобальных переменных из своей области памяти в область памяти диспетчера. Такое копирование глобальных переменных приводит к повышенным затратам памяти (каждая программа имеет свой экземпляр глобальных переменных), но повышает надежность всей программной системы, так как сбой в работе одной из программ не приведет к нарушению правильности главной совокупности глобальных переменных.

Для выполнения самой операции копирования удобно использовать рассмотренный нами ранее оператор movsb с префиксом rep. Напомним, что перед применением данного оператора следует сбросить флаг DF (оператором cld) и записать в регистр CX число переписываемых байтов. Что касается начальных адресов области-источника и области-приемника, то каждый из них задается не одним, а двумя регистрами:

(DS:SI) – адрес области-источника;

(ES:DI) – адрес области-приемника.

Вспомним, что ранее для передачи адресов нами использовались лишь регистры SI и DI. Такое отличие от прежнего применения оператора movsb обусловлено тем, что области памяти, участвующие в копировании, находятся теперь не в одном, а в различных сегментах памяти. Поэтому регистры DS и ES используются для передачи адресов этих сегментов.

Естественно, что при инициировании дочерней программы диспетчер должен передать ей начальный адрес своей области, содержащей глобальные переменные, в виде пары двухбайтовых чисел – (DS, SI). Для передачи этих двух чисел может быть использовано, например, поле PSP, предназначенное для устаревших блоков управления файлами и расположенное по относительному адресу 5ch. Допустим, что первым в это поле записывается требуемое содержимое DS, а затем SI

Ниже приводится сокращенная запись модифицированной программы Dispatcher, предназначенной для многопрограммного редактора:

 

org  100h

;

;           Координирует выполнение модулей редактора

;          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

;

Dispatcher:

cr                equ    0dh

lf                 equ    0ah  

         jmp    Begin                   ; Переход через данные

;        Глобальные переменные

Sector         times  256   db     0       ; Буфер для редактируемого сектора

Address      dw     0                          ; Адрес-смещение сектора

N               db     0                          ; Номер сектора в сегменте памяти

Lognum      db     0                          ; Логический номер открытого файла

Lf               dw     0                          ; Длина файла в секторах

Lsec           dw     0                          ; Фактическая длина сектора

Prf             db     0                          ; Признак редактирования файла

;        Другие данные программы

 .     .     .     .     .     .     .     .           

Blocpar      times  6       db     0       ; Первые 6 байт блока параметров

Param        times  8       db     0       ; Последние 8 байт блока параметров

;        Освобождение лишней памяти

Begin:

.     .     .     .     .     .     .     .            

;        Вопрос о желании редактировать файл

.     .     .     .     .     .     .     .            

;        Запрос имени файла

.     .     .     .     .     .     .     .            

;        Открытие файла

.     .     .     .     .     .     .     .            

;        Определение длины файла

.     .     .     .     .     .     .     .            

;        Сообщение о длине файла

.     .     .     .     .     .     .     .            

;        Прежний диспетчер

.     .     .     .     .     .     .     .            

int     20h

;

;              Интерпретатор команд

;              - - - - - - - - - - - - - - - - -

;     Входы:   DL – скан-код, соответствующий команде

;    Чтение:  Table – таблица переходов

;

Command:

push ax

push  bx

mov   bx,Table                        ; ВХßадрес таблицы

.M1: 

cmp     byte[bx], 0ffh               ; Конец таблицы?

je       .Exit                             ; Да, кода  нет в таблице    

cmp   dl,[bx]                          ; Это вход в таблицу?

je       .Dispatch                      ; Да, выполнить команду

add   bx,18                             ; Нет, переход к

clc                                         ;    следующему

jmp    .M2                              ;     элементу таблицы

;        Обработчик команды выполняет запуск соответствующей

;                  дочерней программы

.Dispatch:

inc    bx                                 ; В BX адрес имени файла

mov   dx, bx                            ; DX ßBX

mov   [Param], ds                  ; Адрес-сегмент передаваемых  данных

mov   [Param+2], Sector        ; Адрес-смещение данных

mov   bx, Blocpar

mov   ax, 4b00h                     

int     21h                               ; Запуск программы

;

.Exit:                     stc                        ; CF ß 1

.M2:                      jnc     .M1             ; Повторение для нового элемента таблицы

pop   bx

pop   ax

ret

;        Таблица переходов содержит скан-коды управляющих клавиш и

;      имена программ, выполняющих соответствующие команды

Table                     db     3bh                                                            ; <F1>

db     ‘Init_sector.com’, 0, 0

db     3ch                                                            ; <F2>        

db     ‘Write_sector.com’, 0

db     3dh                                                            ; <F3>

db     ‘Next_sector.com’, 0, 0

db     3eh                                                           ; <F4>

db     ‘Edit_sector.com’, 0, 0

db     3fh                                                            ; <F5>

db     ‘Prev_sector.com’, 0, 0

db     40h                                                           ; <F6>

db     ‘N_sector.com’, 0, 0, 0, 0, 0

db     0ffh                                                 ; Конец таблицы

%include    ‘Video_io.asm’

%include    ‘Cursor_io.asm’

%include    ‘Kbd_io.asm’

 

В приведенной выше программе глобальные переменные программы собраны вместе в единый блок, начинающийся с метки Sector. Напомним, что глобальные переменные образуют ту информацию, которой модули программной системы обмениваются между собой. Начальные адрес-сегмент и адрес-смещение этого блока записываются в поле Param, содержимое которого копируется в PSP дочерней программы во время выполнения системного вызова EXEC.

Обратим внимание, что все поля таблицы переходов, содержащие имена файлов, имеют одинаковую длину 17 байт. Это обеспечивается путем записи справа дополнительных нулей. Кроме того, следует заметить, что в конце программы не подсоединен файл Disp_sec.asm, но зато подсоединены файлы Video_io.asm, Cursor.asm и Kbd_io.asm. Эти файлы подсоединялись к программе и раньше, но через файл Disp_sec.asm, который теперь в главной программе не нужен.

Дочерние программы удобнее реализовать в виде com-программ. Это удобство заключается в том, что все сегментные регистры содержат одно и то же, указывая на начало сегмента памяти, выделенного программе. Что касается исходных текстов дочерних программ, то они мало отличаются от текстов соответствующих процедур. Эти отличия находятся лишь в начале и в конце программ. Причем во всех дочерних программах отличия одинаковы:

 

;        Программа выполняет одну из команд пользователя

;         -------------------------------------------------------------------

;

absolute     5ch    ; Следующий байт имеет адрес-смещение 5ch

Param        resb   4                 ; Поле входных параметров

;

segment      code                              ; Виртуальный сегмент кода

            org    100h

            jmp    Begin                   ; Переход через данные

;        Глобальные переменные (экземпляр программы)

Sector          times  256   db     0       ; Буфер для редактируемого сектора

Address       dw     0                          ; Адрес-смещение сектора

N                db     0                          ; Номер сектора в сегменте памяти

Lognum      db     0                          ; Логический номер открытого файла

Lf               dw     0                          ; Длина файла в секторах

Lsec           dw     0                          ; Фактическая длина сектора

Prf             db     0                          ; Признак редактирования файла

;        Другие данные программы

 .     .     .     .     .     .     .     .           

Begin:

mov   cx, 265

cld

mov   ds, [Param]

mov   si, [Param+2]

mov   di, Sector   

rep    movsb

.     .     .     .     .     .     .     .            

mov   cx, 265

cld

mov   si, Sector    

mov   es, [Param]

mov   di, [Param+2]

rep    movsb

;        Подсоединение файлов операторами %include

.     .     .     .     .     .     .     .

 


Предыдущий раздел В начало Следующая глава