Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Программные прерывания и системные вызовы
Операционная система MS-DOS предоставляет программисту, работающему на языке ассемблера, большой набор подпрограмм, выполняющих различные полезные действия. Все эти подпрограммы оформлены как подпрограммы обработки прерываний, и для каждой подпрограммы в руководстве по MS-DOS указан номер соответствующего ей прерывания. Для вызова системной подпрограммы следует использовать команду программного прерывания int. Сокращенно принято сами системные подпрограммы называть «прерываниями», хотя это не очень правильно. Некоторые прерывания относятся к ROM BIOS (подсистеме управления вводом/выводом, находящейся в ПЗУ), другие прерывания обслуживаются подпрограммами MS-DOS, загружаемыми в ОЗУ. Особую роль играет прерывание с номером 21h. В зависимости от значения, содержащегося при вызове прерывания в регистре AH, MS-DOS выполняет при этом одну из нескольких десятков подпрограмм, которые принято называть функциями DOS. Для каждого прерывания и каждой функции DOS в руководстве описан набор входных и выходных параметров, передаваемых через регистры, а также перечень возможных ошибок. В данной работе будут описаны прерывания и функции DOS, относящиеся к работе с клавиатурой и экраном ПЭВМ. Функции DOS для ввода с клавиатуры Функция 01h (т.е. прерывание 21h при значении AH=01h) выполняет ввод с клавиатуры одного символа. Если в момент вызова функции в буфере клавиатуры были символы (т.е. были нажатия клавиш до этого), то берется символ из буфера, в противном случае система ждет, пока не будет нажата клавиша. Код введенного символа помещается в регистр AL. Введенный символ отображается на экране (как говорят, выполняется эхо-отображение). Например, пусть на клавиатуре была нажата клавиша «F». Тогда после вызова: mov ah, 01h в регистре AL будет содержаться число 46h, которое является кодом буквы F в коде ASCII. Функция 01h проверяет также, не нажимал ли пользователь в ходе работы программы комбинацию клавиш Ctrl+C (или Ctrl+Break). В этом случае управление передается на подпрограмму обработки Ctrl+C, которая обычно прекращает выполнение программы пользователя. Если на клавиатуре была нажата одна из клавиш, которым не соответствует никакой код ASCII (будем называть такие клавиши несимвольными; к ним относятся, например, Home, Ins, Page Up, F1, F10, стрелка) или комбинация из клавиши Alt, Ctrl, Shift с другой клавишей, то функция 01h возвращает в регистре AL значение 0. В этих случаях следует еще раз вызвать ту же функцию, тогда будет выдан так называемый расширенный код данной клавиши или комбинации, согласно специальной таблице расширенных кодов. Функция 08h работает аналогично 01h, за исключением того, что не выполняется эхо-отображение введенного символа. Функция 07h работает аналогично 01h, за исключением того, что не выполняется эхо-отображение и не проверяется нажатие Ctrl+C. Функция 06h может выполнять как ввод с клавиатуры, так и вывод на экран. Если в момент вызова регистр DL содержит значение 0FFh, то данная функция выполняет ввод без ожидания. Это означает следующее. Если буфер клавиатуры содержит какие-либо символы (т.е. клавиши ранее нажимались), то флаг нуля ZF сбрасывается в 0, а символ из буфера заносится в AL. Если же буфер пуст (нажатий не было), то устанавливается ZF=1, при этом значение в AL не играет роли. Таким образом, эта функция не ждет, пока будет нажата клавиша, а сразу выдает какой-то результат. Функция 06h не выполняет эхо-отображения и не проверяет нажатие Ctrl+C. Функция 0Bh не выполняет ввод символа, а только проверяет, есть ли символы в буфере. Если есть, то устанавливается AL=0ffh, если нет, то – AL=00h. Выполняется также проверка на Ctrl+C. Функция 0Ah выполняет буферизованный ввод строки с клавиатуры. При этом символы вводятся один за другим, как при многократном применении функции 01h до тех пор, пока не будет введен код 0Dh (код клавиши Enter), завершающий строку. В ходе ввода строки пользователь может редактировать строку и, в частности, использовать забой. При вводе выполняется также проверка на Ctrl+C. При вызове функции 0Ah требуется, чтобы в регистре DX содержался адрес (в сегменте данных) области памяти (буфера), в которую система поместит введенную строку. В первом байте этого буфера должна быть записана его длина, т.е. максимальное число символов (включая 0Dh), которое можно записать в буфер. Эта длина должна быть, по крайней мере, на 2 меньше, чем число зарезервированных байтов. После окончания ввода строки функция помещает во второй байт буфера действительное число введенных символов (не считая 0Dh), а начиная с третьего байта буфера, размещаются введенные символы. Последним всегда будет код 0Dh. Например. Пусть требуется ввести строку длиной не более 10 символов. При этом в сегменте данных можно описать буфер, например таким образом: BUFFER db 11; Первый байт буфера Сам же ввод выполняется командами: lea DX, BUFFER; Адрес буфера - в DX Пусть при этом пользователь набрал 6 символов: «Hallo! » и нажал клавишу Enter. После вызова функции в байте entered будет число 6, в первых 6 байтах массива STRING будут коды введенных символов, в седьмом байте – код 0Dh, а оставшиеся 4 байта будут иметь неопределенные значения. Функция 0Ch вначале очищает буфер клавиатуры (т.е. «забывает» предыдущие нажатия клавиш), а потом выполняет любую из функций 01h, 06h, 07h, 08h или 0Ah. Номер этой функции задается в регистре AL. Если задано иное число, то выполняется только очистка буфера. Кроме того, всегда выполняется проверка на Ctrl+C. Функции DOS для вывода на экран Имеются две функции для вывода на экран: одна функция для вывода одного символа, а другая – для вывода строки символов. Функция 02h выдает в текущую позицию экрана символ, код которого содержится в регистре DL. Известно, что для машин типа IBM PC почти каждому из 256 возможных кодов соответствует какое-то графическое изображение, однако при выводе по функции 02h некоторые коды не выдаются на экран, а служат управляющими. В частности: · 0Dh (CR) – перевод курсора в начало текущей строки; · 0Ah (LF) – перевод курсора вниз на 1 строку; · 08h (BS) – перевод курсора влево на 1 позицию; · 07h (BEL) – звонок. Функция 09h выдает, начиная с текущей позиции экрана, строку символов, адрес начала которой (в сегменте данных) содержится в регистре DX. Строка может содержать управляющие символы (CR, LF и т.п.) и, таким образом, на экране занимать несколько строк. Концом выдаваемой строки служит символ «$» (код 24h). Например. Чтобы вывести на экран с новой строки текст: «Привет! Вот как надо выдавать текст на экран! » – и затем перевести курсор в следующую строку, следует в сегменте данных описать строку: PRIVET db 0Dh, 0Ah а в сегменте команд записать команды: lea DX, PRIVET; Адрес строки - в DX ПРИМЕР ВЫПОЛНЕНИЯ РАБОТЫ Ввести строку с клавиатуры, посчитать количества всех десятичных цифр во введенной строке, посчитанные значения вывести на терминал. Текст программы:
model SMALL stack 100h
dataseg AskCont db 0Ah, 0Dh db 'Завершить работу - Esc, продолжить - ЛЮБАЯ Ê Ë À Â È Ø À ' db '$' Ask db 0Ah, 0Dh, 'Введите строку: ', '$' COUNT db 10 dup(? ); счетчики количества цифр CIFR db '0123456789ABCDEF'; таблица преобразования ; шестн.цифр для вывода INPSTR db 80, ?, 82 dup(? ); буфер ввода OUTSTR db 0Dh, 0Ah, ?, ' ', ?, ?, '$'; буфер вывода
codeseg startupcode
BEGIN: ; Ввод строки lea DX, Ask mov AH, 09h int 21h lea DX, INPSTR mov AH, 0Ah int 21h
; Обработка xor AX, AX lea BX, INPSTR+2; адрес начала введенной строки xor CX, CX mov CL, INPSTR+1; кол-во введенных символов строки BB: mov AL, [BX]; очередной символ строки cmp AL, '0'; код символа меньше, чем код нуля? jb NC; да, т.е. не цифра cmp AL, '9'; код символа больше, чем код девятки? ja NC; да, т.е. не цифра ; символ - десятичная цифра sub AL, '0'; получаем дв. значение цифры, т.е. mov SI, AX; индекс в массиве счетчиков COUNT inc COUNT[SI]; увеличиваем соответств. счетчик NC: inc BX; получить очередной символ строки loop BB
; Вывод результатов lea DX, OUTSTR xor SI, SI; Счетчик цифр OO: xor AX, AX mov AL, '0' add AX, SI; ASCII-код очередной цифры в SI mov OUTSTR+2, AL; в буфер вывода mov AL, COUNT[SI]; AL< -значение счетчика ; очередной цифры mov CL, 4; получаем shr AL, CL; в DI mov DI, AX; значение старшей шестн. цифры mov AL, CIFR[DI]; счетчика преобразуем в ASCII-код mov OUTSTR+4, AL; пересылаем в буфер вывода mov AL, COUNT[SI]; AL< -знач. счетчика очередн. цифры and AL, 0Fh; Получаем в DI значение mov DI, AX; младшей шестн. цифры счетчика mov AL, CIFR[DI]; преобразуем ASCII-код mov OUTSTR+5, AL; пересылаем в буфер вывода mov AH, 09h; Вывод сформированной в буфере int 21h; строки inc SI; Счетчик очередной цифры cmp SI, 10 jl OO
; Запрос на продолжение работы lea DX, AskCont mov AH, 09h int 21h mov AH, 08h int 21h cmp AL, 27 je QUIT jmp BEGIN
; Конец работы QUIT: exitcode 0 end ВАРИАНТЫ ЗАДАНИЙ 1. Ввести с клавиатуры строку. Сжать строку, т.е. удалить пробелы и табуляции. Вывести результаты на экран. 2. Ввести с клавиатуры строку. Преобразовать все малые буквы в большие. Вывести результаты на экран. 3. Ввести с клавиатуры строку. Посчитать количество слов в строке. Подумать, что является разделителем слов. Вывести результаты на экран. 4. Ввести с клавиатуры строку. Ввести с клавиатуры коротенькую строку – шаблон. Найти шаблон во введенной строке. Вывести на экран " ДА", если шаблон есть, и " НЕТ", если его нет. 5. Ввести с клавиатуры две строки. Сравнить их. Вывести на экран номер позиции, в которой строки различаются. 6. Ввести с клавиатуры строку. Если она длиннее некоторой величины, то обрезать, если короче – растянуть, вставив нужное число пробелов между словами. Вывести результаты на экран. 7. Ввести с клавиатуры строку, состоящую из нескольких слов. Вывести каждое слово на экран в отдельной строке, т.е. выдать слова в столбик. 8. Ввести с клавиатуры строку. Переставить в ней символы, поменяв местами первый с последним, второй с предпоследним и т.д. Вывести результаты на экран. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Что такое программное прерывание? 2. Какие возможности работы с клавиатурой имеются у программиста? 3. Чем отличаются друг от друга различные функции DOS, выполняющие ввод с клавиатуры? 4. Что такое расширенный код клавиатуры? 5. Можно ли выдать на экран текст «$1.00 = 25.00 rub.», используя функцию DOS 09h? 6. Какие режимы адресации удобно использовать при работе с одномерными массивами? 7. Что означают выражения в поле операндов в строках примера: 8. Как выделить младшую тетраду байта? 9. Как выделить старшую тетраду байта? 10. В чем отличие команд
ЦЕЛЬ РАБОТЫ Цель настоящей работы – знакомство с форматами представления десятичных чисел, упакованным и неупакованным BCD-форматами, освоение команд десятичной коррекции. ОСНОВНЫЕ СВЕДЕНИЯ Популярное:
|
Последнее изменение этой страницы: 2016-03-25; Просмотров: 1148; Нарушение авторского права страницы