Поиск по сайту:


«Assembler IBM PC Приложения к работе № 3. Примеры реализаций типовых заданий»

Файл: 4 КБ
Поделиться:

П.3.1. ЛИСТИНГ 3.4. ПРОГРАММА ПОЛУЧЕНИЯ СКАН-КОДОВ 
КЛАВИШ КЛАВИАТУРЫ

 

Программа выводит на экран в виде четырёх 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                      ;Конец программы/точка входа

П.3.2. ЛИСТИНГ 3.5. ДЕМОНСТРАЦИОННАЯ ПРОГРАММА ИСПОЛЬЗОВАНИЯ
 ФУНКЦИЙ BIOS ДЛЯ РАБОТЫ С ЭКРАНОМ И КЛАВИАТУРОЙ

Программа демонстрирует применение функций 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                          ;Конец программы/точка входа