Предыдущий раздел | ДИСПЕТЧЕР КОМАНД | Следующий раздел |
Этап “Выполнение команды” реализуется путем вызова процедуры Command. Данная процедура получает в регистре DL код ASCII, соответствующий команде, и в зависимости от этого кода вызывает процедуру, выполняющую заданное командой действие.
На рис.48 приведена блок-схема процедуры Command. Центральной особенностью ее алгоритма является использование таблицы переходов. В данной таблице для каждой разрешенной команды пользователя отводятся три байта. В первом байте находится скан-код, соответствующий команде, а в двух других байтах – начальный адрес (внутрисегментное смещение) соответствующей процедуры. В последнем байте таблицы находится 0ffh.
Процедура Command совместно с главной процедурой Dispatcher обеспечивают выполнение алгоритма диспетчера команд. Поэтому обе процедуры, а также таблицу переходов Table мы поместим в один и тот же файл Dispatch.asm. Заключительный фрагмент этого файла содержит модули Command и Table:
org 100h
; Координирует выполнение модулей редактора
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
Dispatcher:
. . . . . . . . ; Тело главной процедуры
int 20h
;
; Интерпретатор команд
; - - - - - - - - - - - - - - - - -
; Входы: DL – скан-код, соответствующий команде
; Чтение: Table – таблица переходов
;
Command:
push bx
mov bx,Table ; ВХßадрес таблицы
.M1: cmp byte[bx], 0ffh ; Конец таблицы ?
je .Exit ; Да, кода нет в таблице
cmp dl,[bx] ; Это вход в таблицу?
add bx,3 ; Нет, переход к
clc ; следующему
jmp .M2 ; элементу таблицы
.Dispatch: inc bx ; Адрес процедуры
call [bx] ; Вызов процедуры
.Exit: stc ; CF ß 1
.M2: jnc .M1 ;Повторение для нового элемента таблицы
pop bx
; Таблица содержит скан-коды управляющих клавиш и адреса процедур,
; выполняющих соответствующие команды
Table db 3bh ; <F1>
dw Init_sector
db 3ch ; <F2>
dw Write_sector
db 3dh ; <F3>
dw Next_sector
db 3fh ; <F5>
dw Prev_sector
db 40h ; <F6>
dw N_sector
db 0ffh ; Конец таблицы
DL – код команды
CF – признак завершения (0 – продолжить, 1 – завершить работу)
Рис. 48. Алгоритм процедуры Command
Рассмотрим особенности этих модулей. Во-первых, сравним между собой два оператора: “cmp byte [bx], 0” и “cmp dl, [bx]”. Оба этих оператора выполняют сравнение заданной величины (число 0 или содержимое регистра dl) с содержимым той ячейки памяти, адрес которой находится в регистре bx. В данном регистре находится адрес-смещение младшего байта ячейки памяти, но не задана длина этой ячейки. Об этой длине транслятор может узнать или из анализа второго операнда команды, или если задан дополнительный псевдооператор byte, wordили dword. В первой из двух записанных выше команд псевдооператор byte сообщает транслятору, что сравниваются байты. Аналогично, команда “cmp word [bx], 0” будет сравнивать слова. Во второй из приведенных выше команд дополнительный псевдооператор излишен, так как о байтовой длине ячейки памяти сообщает другой операнд команды – регистр dl.
Для того чтобы получить адреса процедур, вызываемых диспетчером и содержащихся в таблице, мы записали имя каждой процедуры в качестве операнда псевдооператора dw, выполняющего запрос к транслятору с просьбой выполнить резервирование слова памяти и поместить в это слово требуемое значение. В данном случае таким требуемым значением является адрес-смещение первого байта процедуры. Транслятор выполнит нашу просьбу правильно, так как имя процедуры записано без квадратных скобок, что и означает ее адрес.
Применение для реализации диспетчера команд таблицы переходов значительно увеличивает его гибкость, т.е. пригодность к модификации. В самом деле, мы легко можем добавить в нашу программу новые команды, набираемые на клавиатуре – достаточно записать процедуру, выполняющую новую команду, в подходящий файл, и поместить новую точку входа в Table.
Предыдущий раздел | В начало | Следующий раздел |