Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Информатика

.pdf
Скачиваний:
96
Добавлен:
11.05.2015
Размер:
1.73 Mб
Скачать

151

N Å старшая половина Address

да

нет

 

N=00

N Å N – 1

Address Å N00

Sector Å

сектор N

Вывод

Sector

N-номер текущего сектора

Рис. 45. Алгоритм процедуры Prev_sector

13.4.Лабораторная работа 11

Вы п о л н и т е отладку процедур, предназначенных для переписки сектора. Для этого в начале файла Disp_sec.asm временно поместите тестовую процедуру Imit:

Imit:

call

Init_sector

 

mov

ah,1

; Ожидание нажатия

int

21h

; клавиши

call N_sector

152

mov

ah,1

;

--//--

int

21h

 

 

call

Prev_sector

 

 

mov

ah,1

;

--//--

int

21h

 

 

call

N_sector

 

 

mov

ah,1

;

--//--

int

21h

 

 

call

Next_sector

 

 

mov

ah,1

;

--//--

int

21h

 

 

int

20h

 

 

Перевод строки

Вывод

приглашения

Ввод N

Address Å N00

Sector Å сектор N

Вывод

Sector

N – номер сектора (2-х значное шестнадцатеричное число)

Рис. 46. Алгоритм процедуры N_sector

153

Применение двойного вызова процедуры N_sector преследует цель создать требуемые условия для тестирования процедур Prev_sector и Next_sector, так как позволяет сделать текущим любой интересующий нас сектор. Особое внимание следует уделить граничным условиям – первому и последнему секторам.

14.ДИСПЕТЧЕР КОМАНД

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

14.1.Ввод команд

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

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

<F1> – вывести на экран начальный сектор (256 байт) ОП; <F2> – записать скорректированный сектор в память;

154

<F3> – вывести на экран следующий сектор ОП;

<F5> – вывести на экран предыдущий сектор ОП;

<F6> – вывести на экран сектор N, где 0<=N<=256; <F10> – закончить работу редактора.

Клавиша <F4> оставлена «в резерве» для реализации нами в будущем функции редактирования.

Как говорилось ранее, каждому выводимому на экран символу соответствует свой код ASCII. Но каждому из этих символов соответствует также свой скан–код BIOS. Добавление слова BIOS требуется потому, что, вообще то, говоря, существуют несколько скан-кодов. В данном случае речь идет о том скан-коде клавиши, который возвращает BIOS в вызвавшую его прикладную программу. Далее, говоря «скан-код», мы будем подразумевать скан-код BIOS.

Грубо говоря, скан-код – номер нажатой клавиши. Но любой пользователь знает, что большинству клавиш соответствуют не один, а два или более символов. Поэтому один и тот же скан-код может соответствовать нескольким символам. Например, скан-код 16h соответствует четырем символам: u, U, г, Г. Поэтому для идентификации алфавитно-цифровых символов в обрабатывающих программах скан-коды не используются. Другое дело – управляющие символы, так как каждому из них соответствует своя отдельная клавиша.

Для того чтобы получить одновременно и ASCII-код клавиши, и ее скан-код, следует использовать системный вызов BIOS – “int 16h”, функция 0, выполняющий ввод символа с клавиатуры. После выполнения данного вызова в регистре AL содержится ASCII-код нажатой клавиши, а в регистре AH – ее сканкод.

Что касается управляющих клавиш, то они используются не для отображения на экране, а для управления работой программ. Многим из этих клавиш, в том числе и для <Fi>, соответствует один и тот же ASCII-код – 00h. Поэтому различить такие клавиши между собой можно лишь по их скан-коду:

 

 

 

 

155

3Bh – <F1>,

3Ch - <F2>,

3Dh - <F3>,

3Eh - <F4>,

3Fh - <F5>,

40h

- <F6>,

41h - <F7>,

42h - <F8>,

43h - <F9>,

44h

- <F10>.

 

 

Ниже приведен

текст

процедуры

Read_byte,

выполняющей ввод с

клавиатуры любого символа – обычного или управляющего. При этом код ASCII символа возвращается в регистре AL, а в регистре АН возвращается соответствующий скан-код. Обратите внимание, что вывод “эха” символа не производится.

; Считывает код символа с клавиатуры

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

;Выход: AL – код ASCII символа (0 – управляющий символ)

;

АН – скан-код символа

 

;

 

 

 

Read_byte:

 

 

 

 

mov

ah,0

; Ввод символа

 

int

16h

; без эха

 

ret

 

 

П о м е с т и т е процедуру Read_byte в начало файла Kbd_io.asm, временно записав перед ней оператор “org 100h”, а затем выполните ее отладку, используя Debug. Для этого получите файл Kbd_io.com и наберите команду

DOS:

DEBUG Kbd_io.com

Для запуска программы используйте команду Debug: “G i” , где i – адрес в листинге команды ret. Нажимая различные клавиши, проверьте правильность заполнения процедурой регистра АХ.

14.2. Алгоритм диспетчера

На рис.47 приведена блок-схема главной подпрограммы (процедуры) Dispatcher, выполняющей совместно с рассматриваемой далее процедурой

156

Command функции диспетчера команд. Для того чтобы обеспечить структурность алгоритма, мы, как и в одном из предыдущих разделов, используем флаг переноса CF и операции над ним.

 

 

 

Очистка экрана

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Вывод

 

 

 

 

 

 

 

 

 

 

 

 

приглашения

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Перевод

строки

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Ввод символа

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

нет

 

 

 

 

 

да

 

 

 

 

 

 

 

Символ

 

 

 

 

 

 

 

 

 

управл-й

 

 

 

 

 

 

 

 

 

 

 

 

нет

<F10>

да

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Выполнение

 

 

 

 

 

 

CF Å 0

 

 

 

 

 

 

 

 

 

 

 

команды

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CF Å 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CF Å 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

нет

CF = 1

да

CF – признак завершения (0 – продолжить, 1 – окончить работу)

Рис.47. Алгоритм процедуры Dispatcher

157

Кодирование процедуры Dispatcher не представляет особого труда. Многие этапы ее алгоритма реализуются путем вызова ранее разработанных процедур. Этап «Вывод приглашения» реализуется путем вывода на экран строки символов или, даже, всего одного-двух символов, однозначно указывающих на то, что редактор ожидает команд пользователя. Рассмотрим реализацию этапа «Выполнение команды».

14.3. Выполнение команды

Этап “Выполнение команды” реализуется путем вызова процедуры Command. Данная процедура получает в регистре DL код ASCII, соответствующий команде, и в зависимости от этого кода вызывает процедуру, выполняющую заданное командой действие.

На рис.48 приведена блок-схема процедуры Command. Центральной особенностью ее алгоритма является использование таблицы переходов. В данной таблице для каждой разрешенной команды пользователя отводятся три байта. В первом байте находится скан-код, соответствующий команде, а в двух других байтах – начальный адрес (внутрисегментное смещение) соответствующей процедуры. В последнем байте таблицы находится 0ffh.

Процедура Command совместно с главной процедурой Dispatcher обеспечивают выполнение алгоритма диспетчера команд. Поэтому обе процедуры, а также таблицу переходов Table мы поместим в один и тот же файл Dispatch.asm. Заключительный фрагмент этого файла содержит модули

Command и Table: org 100h

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

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

Dispatcher:

. . . . . . . .

; Тело главной процедуры

158

int 20h

;

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

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

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

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

;

 

 

 

 

 

Command:

 

 

 

 

 

 

push

bx

 

 

 

 

mov

bx,Table

 

; ВХÅадрес таблицы

.M1:

cmp

byte[bx], 0ffh

; Конец таблицы ?

 

je

.Exit

 

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

 

cmp

dl,[bx]

 

; Это вход в таблицу?

 

je

.Dispatch

 

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

 

add

bx,3

 

; Нет, переход к

 

clc

 

 

;

следующему

 

jmp

.M2

 

;

элементу таблицы

.Dispatch:

inc

bx

 

; Адрес процедуры

 

call

[bx]

 

; Вызов процедуры

.Exit:

stc

 

 

;

CF Å 1

.M2:

jnc

.M1

;Повторение для нового элемента таблицы

 

pop

bx

 

 

 

 

ret

 

 

 

 

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

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

Table

db

3bh

; <F1>

 

dw

Init_sector

 

 

db

3ch

; <F2>

 

dw

Write_sector

 

db 3dh

; <F3>

159

dw

Next_sector

 

db

3fh

; <F5>

dw

Prev_sector

 

db

40h

; <F6>

dw

N_sector

 

db

0ffh

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

Выделение первого элемента таблицы

0ffh

 

DL

Код

Другое значение

 

 

 

 

 

 

 

 

элемента=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Выделение

 

 

 

 

Вызов

 

 

 

 

 

 

 

следующего

 

 

 

исполнителя

 

 

 

 

 

 

 

 

элемента

CF Å 1

 

 

команд

 

 

 

 

 

 

 

 

таблицы

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CF Å 1

 

 

 

 

 

 

 

 

 

 

 

 

 

CF Å 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CF = 1

нет

 

да

 

DL – код команды

CF – признак завершения (0 – продолжить, 1 – завершить работу)

Рис. 48. Алгоритм процедуры Command

Рассмотрим особенности этих модулей. Во-первых, сравним между собой два оператора: “cmp byte [bx], 0” и “cmp dl, [bx]”. Оба этих оператора

160

выполняют сравнение заданной величины (число 0 или содержимое регистра dl) с содержимым той ячейки памяти, адрес которой находится в регистре bx. В данном регистре находится адрес-смещение младшего байта ячейки памяти, но не задана длина этой ячейки. Об этой длине транслятор может узнать или из анализа второго операнда команды, или если задан дополнительный псевдооператор byte, word или dword. В первой из двух записанных выше команд псевдооператор byte сообщает транслятору, что сравниваются байты. Аналогично, команда “cmp word [bx], 0” будет сравнивать слова. Во второй из приведенных выше команд дополнительный псевдооператор излишен, так как о байтовой длине ячейки памяти сообщает другой операнд команды – регистр dl.

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

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

14.4.Лабораторная работа 12

За п и ш и т е файл Dispatch.asm на диск и выполните отладку программы. Отлаженная программа должна правильно реагировать на нажатие любой клавиши.