Поиск по сайту:
Программа выводит на экран в виде четырёх 16-теричных чисел скан-код и ASCII-кода произвольной клавиши клавиатуры на основе использования функции BIOS 10h, Int 16h (101/102-key).
Вызов: AH = 10h, Int 21h.
Возврат: AL = ASCII-код символа, изображённый на клавише/Код признака расширения (00h/0Ah/0Dh или E0h);
AH = скан-код/расширенный ASCII-код клавиши.
При выводе на экран старшая пара цифр отделяется от младшей пробелом и сопровождается сообщением "Скан-код (расширенный ASCII-код)/ASCII-код (00h/0Ah/0Dh или E0h)".
Ideal
Model small
Stack 256
macro out_str mes
mov ah,09h
lea dx,[mes]
int 21h
Endm out_str
Dataseg
table_hex db '0123456789ABCDEF'
buf_hex db 5 DUP(?)
mes1 db 10,13,'Скан-код (расш. ASCII-код)/ASCII-код (00h/0Ah/0Dh или E0h): $'
Codeseg
Start: mov ax,@data ;Установка в ds адреса
mov ds,ax ;сегмента данных
again: mov ah,10h
int 16h ;АХ<- информ-код клавиши после её нажатия
cmp al,1Bh ;Нажата клавиша <Exc>?
je Exit ;Да, выходим из программы
mov dx,ax ;Нет, продолжаем работу. Сохраним АХ
mov al,dh ;Возьмём старший байт информ-кода для преобразования.
call conv_hex ;Процедура преобразования двоичного кода из AL
;в пару 16-теричных ASCII- цифр в регистре АХ
mov [word buf_hex],ax ;Запомним старшую пару ASCII- чисел в младших
;байтах буфера. При этом в AH должна располагаться младшая цифра. Это связано с особен-
;ностью записи информации из регистра в буфер памяти – старшая часть регистра записыва-
;ется по старшему адресу.
mov [byte buf_hex+2],' ' ;Запись пробела
mov al,dl ;Возьмём младший байт информ-кода для преобразования.
call conv_hex
mov [word buf_hex+3],ax ;Запомним младшую пару ASCII- чисел в старших
;байтах буфера
out_str mes1 ;Вывод сообщения mes1
;Вывод информационного кода
mov ah,40h
mov bx,1
mov cx,5
lea dx,[buf_hex]
int 21h
jmp again ;Обработка следующей клавиши
Exit: mov ax,4C00h ;Функция DOS 4Сh: выход из программы
int 21h ;Вызов DOS. Останов
Proc conv_hex
;Процедура преобразования двоичного кода из регистра AL в пару 16-теричных ASCII-цифр
;в регистре АХ на основе использования команды XLAT
push dx ;Сохраним DX
mov bx,offset table_hex
mov ah,0
mov cl,4
shl ax,cl ;AH <- старшая двоичная тетрада
shr al,cl ;AL <- младшая двоичная тетрада
xlatb ;AL <- младшая 16-теричная ASCII- цифра
mov dh,al ;Сохраним в старшей части DX
mov al,ah
xlatb ;AL <- старшая 16-теричная ASCII- цифра
mov dl,al ;Сохраним
mov ax,dx
pop dx ;Восстановим DX
ret
Endp conv_hex
END Start ;Конец программы/точка входа
Программа демонстрирует применение функций BIOS при работе с экраном и клавиатурой. Внимательный анализ программы окажет Вам значительную помощь при выполнении собственных программ. Другой особенностью программы является широкое использование макросов. Макросы – эффективное языковое средство ассемблера, облегчающее разработку, модификацию и чтение программ. Приведённые ниже примеры макросов на основе функций BIOS, следует рассматривать лишь как один из возможных вариантов, так как структура макросов и реализуемые ими функции зависят как от целевого назначения программы, так и от стиля программирования.
Comment /* Программа инициализирует экран и вводит 2 локальных окна. Командой <F1> устанавливается режим перетаскивания данных, контролируемых курсором, с одного окна в другое. Меню управления курсором, считыванием и записью символов в позиции курсора, содержится в служебном сообщении на экране. В качестве исходных данных предлагаются символы таблицы ASCII, которые выводятся в левое окно опцией <F2>. Командой <F4> для окна_2 вводится режим блокнота для набора произвольного текста с клавиатуры с возможностью редактирования клавишей <Backspace>. Из режима блокнота можно снова перейти в режим перетаскивания данных, нажав клавишу <F1>. */
Ideal
P386N
MODEL small
Stack 256
;Макросы
;Макрос инициализации окна с цветом (N=0) или его скроллинг вверх на N-строк
;Входные значения: N- параметр, определяющий назначение макроса,
; attrib- атрибут цвета,
; y1,x1- текстовые координаты левого верхнего угла окна,
; y2,x2- текстовые координаты правого нижнего угла окна.
;Выход отсутствует.
MACRO window N,attrib,y1,x1,y2,x2
mov ah,06h ;Функция инициализация окна или его скроллинг вверх
mov al,N
mov bh,attrib ;Атрибут цвета
mov ch,y1 ;Координаты левого верхнего угла (у1,х1)
mov cl,x1
mov dh,y2 ;Координаты правого нижнего угла (у2,х2)
mov dl,x2
int 10h
ENDM window
;Макроопределение locate позиционирования курсора в произвольную точку экрана (y,x) с
;запоминанием координат переменными row_k,col_k (k- номер локального окна на экране).
;Входные значения: определены в описании макроса.
;Выход: row_k= dh= y, col_k= dl= x.
MACRO locate y,x,k
mov ah,02h ;Функция позиционирования курсора
mov bh,0 ;Номер страницы
mov dh,y
mov dl,x
mov [row_&k],dh
mov [col_&k],dl
int 10h
ENDM locate
;Макрос вывода сообщения mes, длиной leng, атрибутом цвета attrib и с позиции (row_k,
;col_k), здесь k -номер окна. После вывода сообщения курсор перемещается в его конец.
;Если сообщение не укладывается в одну строку можно применить управляющие коды 10h
;(перевод строки) и 13h (возврат каретки).
;Входные значения: определены в описании макроса. Выход: отсутствует.
MACRO out_str mes,leng,attrib,k
mov ah,13h
mov al,1 ;Признак смещения курсора в конец строки
mov bh,0 ;Номер видеостраницы
mov bl,attrib
mov cx,leng
mov dh,[row_&k]
mov dl,[col_&k]
mov bp,offset mes ;Адрес строки ES:BP
int 10h
ENDM out_str
;Запись символа с текущим атрибутом на экран в позицию курсора
;Входные значения: AL= ASCII- код символа, BH,CX= номер видеостраницы и число пов-
;торений символа. Выход отсутствует.
Macro write
mov ah,0Ah ;Функция записи символа с текущим атрибутом
mov al,[ASCIIchar] ;ASCII- код символа
mov bh,0
mov cx,1 ;Число повторений символа
int 10h
Endm write
;Чтение символа и атрибута в позиции курсора и запись их в память для хранения.
;Входные значения: BH= номер страницы.
;Выход: AX= AH:AL= "атрибут: ASCII-код символа" этих параметров (дополнительно, эти
;параметры сохраняются переменными attrib и ASCIIchar).
Macro read
push bx
mov ah,08h ;Функция чтение символа и атрибута
mov bh,0
int 10h
mov [attrib],ah ;Сохраним атрибут и
mov [ASCIIchar],al ;символ
pop bx
Endm read
;Копирование символа в позиции курсора с его удалением. Удаление осуществляется
;записью пробела с сохранением в данной позиции текущего атрибута.
;Входные значения: отсутствуют.
;Выход: AX= AH:AL= "атрибут: ASCII-код символа" (дополнительно, эти параметры
;сохраняются переменными attrib и ASCIIchar).
Macro read_del
Read ;Сохраним атрибут и символ
mov ah,09h ;Функция записи символа с заданными атрибутами на экран
mov al,20h ;Поместим ASCII- код пробела и текущий атрибут
mov bl,[attrib]
mov cx,1
int 10h
Endm read_del
crlf equ 13,10,5 DUP(20h)
crlf2 equ 13,10,42 DUP(20h)
Dataseg
ExCode DB 0
mes0 DB '<F1>- режим переноса данных, контролируемых курсором, с одного'
DB crlf,'места экрана в другое. Опции режима: <F2>- вывод таблицы символов'
DB crlf,'ASCII в окно_1, <F3>- Очистка локального окна_2, <Ctrl-ins>-'
DB crlf,'копирование символа, <Ctrl-del>-копирование с удалением, <Ins>-'
DB crlf,'запись, "¬,,¯,® " – навигация курсора по экрану. '
DB crlf,'<F4>- режим набора текста в окне_2. <F10>-выход из программы.'
DB crlf2,' '
DB crlf2,' При наборе текста используем '
DB crlf2,' клавиши <Backspace> и <Enter> '
DB crlf2,' '
leng_mes0 = $-mes0
mes1 DB '0 1 2 3 4 5 6 7 8 9 A B C D E F'
leng_mes1 = $-mes1
Label mes2 byte
Line = 30h
Rept 10
DB 4 DUP(20h),line,13,10
Line = line+1
endm
line = 41h
rept 6
DB 4 DUP(20h),line,13,10
Line = line+1
endm
leng_mes2 = $-mes2
ASCIIchar DB ?
Attrib DB ?
Backspace DB 08h,20h,08h
row_0 DB ?
col_0 DB ?
row_1 DB ?
col_1 DB ?
row_2 DB ?
col_2 DB ?
CODESEG
Start: mov ax,@data ;Установка в ds адреса
mov ds,ax ;сегмента данных
mov es,ax ;es=ds
mov ax,1003h ;Вызов функции повышенной яркости экрана
mov bl,0 ;Повышенная яркость
int 10h
;Инициализация экрана с атрибутом 0B0h (чёрные символы по бирюзовому фону)
;с координатами: (0,0)- левый верхний угол, (24,79)- правый нижний
window 0,0B0h,0,0,24,79
locate 1,5,0 ;row_0=1, col_0=5
out_str mes0,leng_mes0,0B0h,0 ;Вывод сообщения mes0
;Инициализация локального окна_1 с атрибутом 0C1h (синий по розовому)
;с координатами: (8,6)- левый верхний угол, (23,38)- правый нижний
window 0,0C1h,8,6,23,38
locate 7,7,0 ;row_0=7, col_0=7
out_str mes1,leng_mes1,0B0h,0 ;Вывод сообщения mes1
locate 8,0,0
out_str mes2,leng_mes2,0B0h,0 ;Вывод сообщения mes2
;Инициализация локального окна_2 с атрибутом 0E4h (красный по жёлтому)
;с координатами: (10,42)- левый верхний угол, (23,76)- правый нижний
window 0,0E4h,11,42,23,76
mov ax,0C00h ;Очистка буфера клавиатуры
int 21h
;Выбор режима работы
mode: mov ah,10h ;Чтение символа с клавиатуры с ожиданием
int 16h
cmp al,00h ;Управляющая клавиша c мл. байтом 00h
jne mode
cmp ah,3Bh ;Нажата <F1>?
je F1 ;Да
cmp ah,3Eh ;нажата <F4>?
je F4 ;Да
jmp mode ;Цикл ввода режима
F3: window 0,0E4h,11,42,23,76 ;Очистка окна_2
;Блок управления программой в режиме <F1>
F1: mov ah,10h ;Функция чтения символа с клавиатуры
;(101/105 key). При нажатии клавиши, соответствующей расширенному ASCII-коду
;в АН засылается расширенный ASCII- код, в AL-значение 00h или 0E0h
int 16h
cmp al,00h ;Управляющая клавиша c мл. байтом 00h
je @@1 ;Да
cmp al,0E0h ;Управляющая клавиша c мл. байтом E0h
je @@1 ;Да
jmp F1 ;Нет, повторить ввод
@@1: cmp ah,3Ch ;Нажата <F2>?
je F2 ;Да
cmp ah,3Dh ;нажата <F3>?
je F3 ;Да
cmp ah,3Eh ;нажата <F4>?
je F4 ;Да
cmp ah,44h ;Нажата <F10>?
je F10 ;Да
cmp ah,92h ;Нажата <ctrl-ins>?
je ctrl_ins ;Да
cmp ah,93h ;Нажата <ctrl-del>?
je ctrl_del ;Да
cmp ah,52h ;Нажата <ins>?
je insert ;Да
;Считывание текущих координат курсора
push ax
mov ah,03h
mov bh,0
int 10h ;D= номер строки, DL= номер столбца
pop ax
;Продолжение опроса
cmp ah,48h ;Нажата
je up ;Да
cmp ah,50h ;Нажата ¯
je down ;Да
cmp ah,4Bh ;Нажата ¬
je left ;Да
cmp ah,4Dh ;Нажата ®
je right ;Да
jmp F1 ;Нажата не запланированная
;Навигация курсора, копирование, запись, считывание
ctrl_ins: mov di,1 ;Разрешить запись
read
jmp F1
ctrl_del: mov di,1 ;Разрешить запись
read_del
jmp F1
insert: cmp di,1 ;Чтение выполнялось?
jne @@1 ;Нет, запись выполнять нельзя
write ;Да, выполним запись
@@1: jmp F1
up: cmp dh,0 ;На строку вверх
je L3
sub dh,1
jmp L3
down: cmp dh,25 ;На строку вниз
je L3
add dh,1
jmp L3
left: cmp dl,0 ;На столбец влево
je L3
sub dl,1
jmp L3
right: cmp dl,80 ;На столбец вправо
je L3
add dl,1
L3: mov ah,02h ;Установить новую позицию курсора
mov bh,0
int 10h
jmp F1
;Вывод изображения всех символов таблицы ASCII, включая управляющие, в окно_1 в фор-
;мате "16 x16". Символы в строке разделяются пробелами.
F2: locate 8,7,1 ;row_1=8, col_1=7
mov al,0 ;Первый символ ASCII с кодом 00h
mov cx,256 ;Счётчик циклов вывода
;Вывод символа любого кода ASCII, (включая управляющие) из AL в позицию курсора с
;координатами row_1, col_1 в окно_1 c последующим увеличением координаты курсора в
;строке на 2 позиции вправо
cycle: push cx
mov ah,0Ah ;Функция вывода символа с текущим атрибутом из al
mov bh,0 ;Номер страницы
mov cx,1 ;Число повторений символа
int 10h ;Вывести символ в текущую позицию
inc al ;Следующий символ
test al,0Fh ;Если al не кратен 16
jnz L1 ;продолжить вывод в строке,
add [row_1],1 ;иначе увеличить номер строки на 2
mov [col_1],7 ;Столбец = 7
jmp L2
L1: add [col_1],2 ;Увеличить номер столбца на 2
L2: mov dh,[row_1]
mov dl,[col_1]
mov ah,2 ;Функция установки курсора
int 10h ;Переместить курсор в позицию row_1, col_1
pop cx
loop cycle
jmp F1
;Режим <F4>- вывод текста в окно_2 (блокнот). Переход на новую строку осуществляется
;кл. <Enter> с ASCII- кодом 0Dh, допускается редактирование текста клавишей <Backspace>
F4: locate 11,44,2
repet: mov ah,08h ;Функция ввода ASCII- символа в AL без эха
int 21h ;ASCII- код в AL
cmp al,00h ;Расширенный ASCII?
je ex_ascii ;Да
cmp al,08h ;Управляющий код "назад"
je erase ;Да, сотрём предыдущий символ
cmp al,0Dh ;ASCII- код равен 0Dh?
jne out_symb ;Нет, выводим символ на экран
mov ah,03h ;Да, переходим на новую строку. Для этого
;вызовем функцию считывания текущей позиции курсора
mov bh,0 ;Номер страницы
int 10h ;Номер строки в DH, столбца в DL
add dh,1 ;Формирование координаты новой строки
mov dl,44 ;в окне_2
cmp dh,23 ;Номер следующей строки равен 23?
je scroll ;Да, надо произвести прокрутку окна
position: mov ah,02h ;Функция установки позиции курсора
int 10h ;Курсор установлен
jmp repet ;Продолжим вывод текста
scroll: push dx
Window 4,0E4h,11,42,23,76 ;Прокрутка на 4 строки вверх
pop dx
sub dh,4 ;Декремент строки на параметр прокрутки
mov bh,0 ;Номер страницы
jmp position
out_symb: mov ah,0Eh ;Функция вывода символа с текущим атрибутом
mov bh,0 ;в режиме телетайпа
int 10h ;Символ выведен
jmp repet
;Стирание предыдущего символа путём вывода последовательности 08h, 20h, 08h
erase: mov cx,3
mov si,0
@@1: mov al,[backspace+si]
inc si
mov ah,0Eh ;Функция вывода символа с текущим атрибутом в
mov bh,0 ;в режиме телетайпа
int 10h ;Символ выведен
loop @@1
jmp repet
;Проверка запроса о выходе из режима набора текста в режим перетаскивания символов<F1>
ex_ascii: mov ah,08h ;Введём старший байт ASCII- кода
int 21h
cmp al,3Bh ;Скан-код клавиши <F1>?
je F1 ;Да, переходим в режим <F1>
cmp al,44h ;Скан-код клавиши <F10>?
je F10 ;Да, выходим из программы
jmp repet ;Нет, остаёмся в данном режиме
;Выход из программы с восстановлением режима обычной яркости
F10: mov ax,1003h ;Вызов функции
mov bl,1 ;Мерцание символа
int 10h
Exit: mov ax,4C00h ;Функция DOS 4Сh:выход из программы
int 21h ;Вызов DOS. Останов
END Start ;Конец программы/точка входа