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

Информатика

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

261

если RR = 1, то нажатие клавиши относится к текущей работе редактора, и никаких особых действий со стороны резидентной части выполнять не следует.

нет

RR=0

 

 

 

да

 

 

 

 

 

 

Извлечение из

 

 

стека старого

 

 

адреса возврата

 

 

 

 

 

 

 

 

 

Переход на

Запись в стек

 

системный

нового адреса

 

обработчик

возврата

 

 

 

 

 

 

 

 

Переход на

 

 

системный

 

 

обработчик

 

 

 

 

 

 

Возврат из

 

 

системного

 

 

обработчика

 

 

 

 

 

 

 

 

 

 

 

Копирование

 

 

 

 

 

символа из

 

 

 

 

системного буфера

 

 

 

 

 

 

 

 

 

 

да

 

нет

 

 

 

<Fi>

RR ← 1

 

 

 

 

 

 

 

 

 

 

 

Выборка символа

 

 

 

 

из системного

 

 

 

 

 

Переход на старый

буфера

 

 

 

 

 

 

адрес возврата

 

 

 

Выполнение

 

 

 

 

команды

 

 

 

 

 

 

 

 

 

 

 

RR

← 0

 

 

 

 

 

 

 

 

 

 

 

RR – режим редактирования (0 – нет редактирования, 1 – есть)

Рис. 67. Алгоритм резидентной части редактора

262

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

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

Так как наш резидентный редактор, являясь одновременно и обработчиком прерываний клавиатуры, никаких операций ни с системным буфером клавиатуры, ни тем более с контроллером клавиатуры, выполнять «не желает», ему приходится достаточно тесно взаимодействовать с системным обработчиком, который выполняет эти операции.

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

Процесс получения кода символа начинается с извлечения из стека старого адреса возврата. Вспомним, что в момент прерывания ЦП помещает в стек прерванной программы (этот стек наследуется обработчиком прерываний) три слова – (FLAGS), (CS), (IP). С помощью операторов pop эти слова извлекаются из стека, а затем сохраняются в трех словах ОП. Далее на следующем этапе в стек помещается новый адрес возврата из трех слов: 1) текущее содержимое

263

FLAGS, 2) текущее содержимое CS; 3) адрес-смещение того байта программы, который расположен в памяти сразу же за командой перехода на системный обработчик прерываний клавиатуры.

Например, допустим, что переход на системный обработчик выполняет оператор:

jmp far [Old]

.M:

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

push .M

Интересно отметить, что для перехода на системный обработчик можно использовать не только оператор jmp, но и оператор call:

call far [Old],

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

В результате записи в стек своего адреса возврата наша программа делает системный обработчик прерываний «ручным». Это означает, что после своего выполнения системный обработчик возвратит управление в резидентную часть на метку .M. Напомним, что во время этого выполнения системный обработчик выполнил перенос кода нажатой клавиши из контроллера клавиатуры в системный буфер.

Для того чтобы выполнить анализ введенного кода, наша программа обращается за помощью к BIOS, используя системный вызов “int 16h”, функция 01h. Особенностью данного системного вызова является то, что, выполняя чтение из системного буфера кода символа, он этот код из буфера не извлекает.

Кроме этого, данный системный вызов отличается от ранее рассмотренного “int 16h”, функция 00h, тем, что он не дожидается появления в системном

264

буфере кода символа, а при его отсутствии возвращает управление в вызывающую программу, установив флаг ZF = 1. Если символ в системном буфере есть, то в результате выполнения данного системного вызова флаг ZF = 0, а в регистрах: AH – скан-код символа, AL ASCII-код символа.

На следующем этапе алгоритма проверяется, не является ли код символа, скопированный на предыдущем шаге из системного буфера, кодом функциональной клавиши <Fi>. Для этого сначала проверяется на равенство нулю ASCII-код символа, и если это выполняется, то проверяется принадлежность скан-кода символа к диапазону от 3Bh до 44h. В случае успеха в переменную RR записывется 1 (редактор начинает выполнять свою команду), а затем производится выборка символа из системного буфера (для этого используется вызов “int 16h”, функция 00h).

Дальнейшее выполнение процедуры Dispatcher (и всего редактора) по выполнению команды не отличается от нерезидентного варианта. Единственное отличие – после завершения выполнения команды не делается переход на начало процедуры Dispatcher (для получения следующей команды), а делается запись RR=0, после чего обработчик прерываний, то есть весь резидентный редактор, завершается восстановлением содержимого регистров и завершающей командой iret.

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

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

265

алгоритма является невозможность одновременного выполнения более чем одного этапа алгоритма. Для резидентного редактора это свойство не выполняется, так как одновременно могут выполняться этапы «выполнение команды» и «переход на системный обработчик» (при RR=1). Причиной такой непоследовательности является то, что одна и та же программа одновременно предназначена и для выполнения высокоуровневых функций по редактированию информации, и для выполнения низкоуровневых функций в качестве обработчика прерываний клавиатуры.

19.4. Лабораторная работа 17

Требуется реализовать описанный выше резидентный редактор. Примечание. Резидентный редактор должен правильно выполнять свои

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

ЗАДАНИЯ ДЛЯ ПРОГРАММИРОВАНИЯ

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

Первые 20 заданий предназначены для закрепления знаний по начальным разделам второй части пособия (разделы 9 – 11). Остальные 20 заданий позволяют закрепить знания по остальным разделам второй части.

Задание 1. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит на экран сумму этих чисел, представленную в десятичной и шестнадцатеричной системах счисления.

266

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

Задание 3. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит наибольшее число из введенных, представленное в десятичной и двоичной системах счисления.

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

Задание 5. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит наименьшее число из введенных, представленное в десятичной и шестнадцатеричной системах счисления.

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

Задание 7. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит последовательность этих же чисел, но записанных в обратном порядке и в шестнадцатеричной системе счисления.

267

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

Задание 9. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит эти же числа на экран в порядке возрастания величины числа, причем в шестнадцатеричной системе счисления.

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

Задание 11. По запросу программы пользователь вводит с клавиатуры последовательность целых трехзначных положительных десятичных чисел, разделенных пробелами. Ввод последовательности заканчивается нажатием <Enter>. Программа выводит эти же числа на экран в порядке убывания величины числа, причем в двоичной системе счисления.

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

Задание 13. По запросу программы пользователь вводит с клавиатуры сообщение на русском языке, заканчивающееся символом “.” или “!”. Программа выводит на экран это же сообщение, записанное только заглавными буквами.

268

Задание 14. По запросу программы пользователь вводит с клавиатуры сообщение на русском языке, заканчивающееся символом “.” или “?”. Программа выводит на экран это же сообщение, записанное только строчными (малыми) буквами.

Задание 15. По запросу программы пользователь вводит с клавиатуры сообщение на английском языке, заканчивающееся символом “.” или “?”. Программа выводит на экран это же сообщение, записанное только заглавными буквами.

Задание 16. По запросу программы пользователь вводит с клавиатуры сообщение на английском языке, заканчивающееся символом “.” или “!”. Программа выводит на экран это же сообщение, записанное только строчными (малыми) буквами.

Задание 17. По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделенных знаком операции “+” или “-“. Программа выводит на экран результат операции в двух системах счисления – в десятичной и в двоичной (в дополнительном коде).

Задание 18. По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделенных знаком операции “ * ”. Программа выводит на экран результат операции умножения .

Задание 19. По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделенных знаком операции “ / ”. Программа выводит на экран результат операции деления (частное и остаток).

Задание 20. По запросу программы пользователь вводит с клавиатуры два целых трехзначных положительных десятичных числа. Программа выводит на экран сообщение о том, делится ли первое число на второе без остатка, а затем сообщение – делится ли без остатка второе число на первое.

Задание 21. Резидентная программа инициируется нажатием клавиши <F1> и выводит на экран ваши имя и фамилию, записанные английскими буквами. При нажатии клавиши <F2> программа уничтожается.

269

Задание 22. Резидентная программа инициируется нажатием клавиши <F2> и выводит на экран ваши имя и фамилию, записанные русскими буквами. При нажатии клавиши <F1> программа уничтожается.

Задание 23. Разработать простейший отладчик программ, который получает имя загрузочного модуля прикладной программы в качестве своего параметра, и выполняет эту программу покомандно, выдавая после завершения каждой ее команды на экран содержимое регистров AX и BX в шестнадцатеричной системе счисления. (Некоторый аналог команды T Debug.)

Примечание. Работа программы основана на запуске трассируемой программы и обработке исключения «Трассировка».

Задание 24. Разработать простейший отладчик программ, который вводит с клавиатуры имя загрузочного модуля прикладной программы, и выполняет эту программу покомандно, выдавая после завершения каждой ее команды на экран содержимое регистров CX и DX в двоичной системе счисления. (Некоторый аналог команды T Debug.)

Примечание. Работа программы основана на запуске трассируемой

программы и обработке исключения «Трассировка».

 

 

Задание 25. Разработать

простейший

интерпретатор

команд,

выполняющий обработку командных файлов (bat-файлов). Имя командного файла вводится с клавиатуры. Имя запускаемой программы (строка bat-файла) не имеет параметров. После завершения запуска очередной программы на экран

выводится сообщение об успешности запуска.

 

 

Задание 26. Разработать

простейший

интерпретатор

команд,

выполняющий обработку командных файлов (bat-файлов). Имя командного файла интерпретатор команд получает при своем запуске (в качестве параметра команды). Имя запускаемой программы (строка bat-файла) не имеет параметров. После завершения запуска очередной программы на экран выводится сообщение об успешности запуска.

Задание 27. Прикладная программа выполняет запуск другой (дочерней) прикладной программы, получив предварительно ее имя с клавиатуры. При

270

своем запуске дочерняя программа получает на входе (в PSP) строку символов, которую она выводит на экран.

Задание 28. Прикладная программа выполняет запуск другой (дочерней) прикладной программы, получив ее имя в качестве своего параметра (хвоста команды). При своем запуске дочерняя программа получает на входе (в PSP) строку символов, которую она выводит на экран.

Задание 29. Прикладная программа выводит на экран содержимое своего блока окружения.

Задание 30. Прикладная программа выполняет уничтожение файла. Имя уничтожаемого файла вводится с клавиатуры.

Задание 31. Прикладная программа вводит с клавиатуры имя нового текстового файла, записывает в него содержимое своего блока окружения, а также «хвоста», а затем выводит содержимое этого файла на экран.

Задание 32. Прикладная программа вводит с клавиатуры имя существующего текстового файла, «дописывает» в него содержимое своего блока окружения, а также «хвоста», а затем выводит содержимое этого файла на экран.

Задание 33. Резидентная программа инициируется из прикладной программы, выполняя вывод на экран блока окружения и «хвоста» прикладной программы.

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

Задание 34. Прикладная программа вводит с клавиатуры имена двух существующих текстовых файлов, а затем инициирует резидентную программу (передав ей на вход через PSP имена файлов), которая «расширяет» первый файл, добавив в него содержимое второго файла.

Задание 35. Прикладная программа вводит с клавиатуры имя существующего текстового файла, а затем выводит его содержимое на экран.