Ассемблер. Учебное пособие
..pdfа в конце ее восстановить сохраненный вектор (функция 35h прерывания Int 21h).
Метод, основанный на применении прерывания Int 1Сh, позволяет управлять устройствами в реальном времени циклично с периодом, кратным 1/18 с. Если же необходимо обеспечить управление в произвольные моменты времени в течение суток, то можно применить другой метод, при котором используется прерывание Int 4Аh (прерывание будильника). Рассмотрим применение этого метода.
Для установки будильника надо воспользоваться функцией 06h прерывания Int 1Ah. После этого нужно заменить вектор обработчика Int 4Ah собственным вектором прикладного обработчика. После установки будильника РТС будет генерировать прерывание Int 4Аh каждые сутки в заданное время до тех пор, пока будильник не будет выключен с помощью функции 07h того же прерывания Int 1Ah. Фрагмент программы установки будильника на срабатывание в конкретный момент времени выглядит следующим образом:
; сохраним вектор 4Ah в 2-байтовой ячейке old_4Ah mov ax, 354Ah
int 21h
; установим собственный обработчик прерывания Int 4Ah mov ax, 254Ah
mov dx, offset new_4Ah int 21h
;установим будильник:
;ch=часы, cl=минуты, dh=секунды (BCD-формат)
mov ah, 06Ah int 1Ah
43
3.5. Генерация звука
Создавать простые звуки с помощью системных средств ПК можно двумя способами:
1. Использование канала 2 системного таймера i8254. (рис.3.4)
|
19318Мгц |
|
|
|
|
|
CLK |
OUT2 |
|
|
Бит 0 |
GATE2 |
|
& |
|
|
|
|
|
Порт 61h |
Бит 1 |
|
|
|
|
|
|
K2 |
динамик |
|
|
|
|
Рис. 3.4. Генерация звука с использованием канала 2 системного таймера i8254
Метод состоит в следующем. Два сигнала: выход OUT канала 2 таймера и бит 1 порта 61h объединяются по схеме логическое "И" и поступают на вход звукогенератора. Поэтому простейший способ генерации звука состоит в программировании канала 2 таймера так, чтобы он выдавал прямоугольный импульс заданной частоты, находящейся в звуковом диапазоне (20 Гц–20 КГц). Для этого следует использовать режим 3 таймера с начальным значением счетчика. Если затем установить биты 0 и 1 порта 61h, то импульс начнет поступать на вход звукогенератора (бит 0 определяет разрешение работы канала 2 GATE=1, а бит 1 – разрешение выдачи прямоугольного сигнала с выхода OUT. Для выключения звука надо сбросить биты 0 - 1 в порте 61h. Преимущество этого метода состоит в том, что, запустив генерацию звука, центральный процессор может выполнять другие действия. Значение счетчика канала 2 вычисляется по формуле:
n=1193181/f,
где 1193181 Гц – тактовая частота таймера, f – требуемая частота звука.
Пример:
;подпрограмма генерации звука
;Вход: АX= частота звука в Гц
Sound proc near
44
push |
ax |
;сохранить регистры |
push |
bx |
|
push |
dx |
|
mov |
bx, ax |
;частота |
mov |
ax,34DDh |
|
mov |
dx,12h |
;(dx,ax)=1193181=1234DDh |
cmp |
dx, bx |
;если bx < 18 Гц, то выход, |
jnb |
Done |
;чтобы избежать переполнения |
div |
bx |
;ax=(dx,ax)/bx |
mov |
bx, ax |
;счетчик таймера |
in |
al, 61h |
; в порте 61h |
or |
al, 3 |
;установить биты 0,1 |
out |
61h, al |
|
;управляющий байт таймера: канал 2, режим 3, двоичный счет
mov |
al, 0b6h |
|
mov |
dx, 43h |
|
out |
dx, al |
;вывод в регистр режима |
dec |
dx |
|
mov |
al, bl |
|
out |
dx, al |
;младший байт счетчика |
mov |
al, bh |
|
out |
dx, al |
;старший байт счетчика |
Done: |
|
|
pop |
dx |
;восстановить регистры |
pop |
bx |
|
pop |
ax |
|
ret |
|
|
Sound endp |
|
|
; подпрограмма выключения генерации звука |
||
No_Sound proc near |
|
|
push ax |
|
|
in |
al, 61h ;в порте 61h |
|
and |
al, not 3 |
;сбросить биты 0,1 |
out |
61h, al |
|
pop |
ax |
|
ret |
|
|
No_Sound endp
45
Для генерации музыки можно использовать следующий алгоритм.
Пусть octave – номер октавы (1, 2, ...); note – номер ноты в октаве (до=1, до#=2, ..., си=12). Тогда:
f := 32.625;
for i := 1 to oktave do f := 2*f;
for i := 1 to note do f := 1.059463094*f; Sound (round(f));
2. Прямое управление динамиком. Второй способ генерации звука состоит в том, чтобы генерировать звуковые импульсы не с помощью выходного сигнала канала 2 таймера, а непосредственной установкой и сбросом бита 1 в порте 61h. При этом, если на вход GATE канала 2 таймера подать запрет (бит 0 в порте 61h должен быть сброшен), то динамик выдаст характерные звуковые щелчки с частотой, определяемой изменением состояния бита 1 порта 61h. Для
формирования |
задержек |
при моделировании меандра |
можно |
использовать программный цикл, например: |
|
||
; Программа генерации звука |
|
||
; Вход: N=количество импульсов |
|
||
;FREQ=длительность импульса |
|
||
in |
al, 61h |
; запрет работы канала 2 |
|
and |
al, not 1 |
; таймера |
|
mov |
dx, N |
|
|
Repeat: |
|
|
|
or |
al, 2 |
; включить динамик |
|
out |
61h, al |
|
|
mov |
cx, FREQ |
|
|
Wait_On: |
|
; длительность |
|
loop |
Wait_On ; звучания |
|
|
and |
al,not 2 |
; выключить динамик |
|
out |
61h,al |
|
|
mov |
cx,FREQ |
|
|
Wait_Off: |
|
; длительность |
|
loop |
Wait_Off |
; паузы |
|
dec |
dx |
|
|
jnz |
Repeat |
|
|
46
Программирование этого способа основано на следующих формулах:
N=T*f, |
FREQ=t/(34*f); |
где Т – длительность звучания в сек, f – частота звука в Гц, t – |
тактовая частота центрального процессора в Гц.
Константа 34 объясняется тем, что длительность каждого из циклов Wait_on и Wait_off приблизительно равна (17*cx) машинных тактов.
Недостаток этого метода заключается в том, что центральный процессор полностью занят генерацией звука – любое прерывание испортит временную диаграмму звукового сигнала. Однако он обеспечивает точную подстройку частоты и позволяет создавать несимметричные импульсы варьированием задержек в циклах
Wait_on и Wait_off.
47
4. Ввод информации с клавиатуры ПК
Клавиатуры соединяются с ПК посредством шифратора, микросхемы, которая преобразует каждый удар по клавише в 8- битовый ASCII-код.
Система ASCII представляет собой набор числовых кодов, используемых в ЭВМ для обмена данными. Стандартный набор символов ASCII (табл. 4.1) состоит из 128 символов от 00H до 7FH, который кроме символов букв, цифр и специальных знаков содержит еще и управляющие символы, необходимые для управления периферийными устройствами ПК.
Все генерируемые клавиатурой коды символов могут быть представлены лишь с помощью так называемой расширенной системы ASCII (256 кодов), в расширении этой системы находятся коды символов псевдографики, букв греческого алфавита или национального алфавита страны пользователя.
Всякий раз, когда Вы нажимаете или отпускаете клавишу, встроенное в клавиатуру устройство запоминает в своей внутренней памяти код нажатия или отпускания (соответственно 1 или 0) в седьмом бите и идентификатор клавиши (scan-код) в остальных битах. После этого устройство посылает системе BIOS прерывание типа 9, сообщающее, что у него есть данные для передачи.
Память клавиатуры способна хранить до 10 операций нажатия и отпускания (ударов), ее переполнение вызывает генерацию звукового сигнала. Система BIOS считывает байты из памяти клавиатуры и преобразует их в коды символов. В процессе преобразования scanкода проверяются, не были ли нажаты некоторые клавиши (без отпускания), что позволяет формировать коды символов, отражающие комбинации клавиш с Ctrl, Shift, Alt. По завершении работы процедура обработки прерывания типа 9 запоминает scan-код и код символа в буфере клавиатуры, находящемся в памяти ПК.
Любой символ из таблицы ASCII можно получить набором кода в десятичном формате на дополнительной клавиатуре при нажатой клавише Alt. Например, ввод символа { осуществляется комбинацией
Alt+123.
48
|
|
Стандартный набор символов ASCII |
|
Таблица 4.1 |
|||||
|
|
|
|
|
|||||
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
|
7 |
|
|
|
|
|
|
|
|
|
|
0 |
NULL |
DLE |
SP |
0 |
@ |
P |
` |
|
p |
|
|
|
|
|
|
|
|
|
|
1 |
SOH |
DC1 |
! |
1 |
A |
Q |
a |
|
q |
|
|
|
|
|
|
|
|
|
|
2 |
STX |
DC2 |
« |
2 |
B |
R |
b |
|
r |
|
|
|
|
|
|
|
|
|
|
3 |
ETX |
DC3 |
# |
3 |
C |
S |
c |
|
s |
|
|
|
|
|
|
|
|
|
|
4 |
EOT |
DC4 |
$ |
4 |
D |
T |
d |
|
t |
|
|
|
|
|
|
|
|
|
|
5 |
ENQ |
NAK |
% |
5 |
E |
U |
e |
|
u |
|
|
|
|
|
|
|
|
|
|
6 |
ACK |
SYN |
& |
6 |
F |
V |
f |
|
v |
|
|
|
|
|
|
|
|
|
|
7 |
BEL |
ETB |
‘ |
7 |
G |
W |
g |
|
w |
|
|
|
|
|
|
|
|
|
|
8 |
BS |
CAN |
( |
8 |
H |
X |
h |
|
x |
|
|
|
|
|
|
|
|
|
|
9 |
HT |
EM |
) |
9 |
I |
Y |
i |
|
y |
|
|
|
|
|
|
|
|
|
|
A |
LF |
SUB |
* |
: |
J |
Z |
j |
|
z |
|
|
|
|
|
|
|
|
|
|
B |
VT |
ESC |
+ |
; |
K |
[ |
k |
|
{ |
|
|
|
|
|
|
|
|
|
|
C |
FF |
FS |
, |
< |
L |
\ |
l |
|
| |
|
|
|
|
|
|
|
|
|
|
D |
CR |
GS |
- |
= |
M |
] |
m |
|
} |
|
|
|
|
|
|
|
|
|
|
E |
SO |
RS |
. |
> |
N |
^ |
n |
|
~ |
|
|
|
|
|
|
|
|
|
|
F |
SI |
US |
/ |
? |
O |
_ |
o |
|
DEL |
|
|
|
|
|
|
|
|
|
|
49
Таблица 4.2
|
Расширенные коды клавиш |
|
Расширенный |
Функция |
|
Код(HEX) |
||
|
||
3 |
Ctrl @ |
|
F |
BACKSPACE(←) |
|
10-19 |
Alt Q W E R T Y U I O P(второй ряд) |
|
1E-26 |
Alt A S D F G H J K L |
|
2C-32 |
Alt Z X C V B N M |
|
3B-44 |
F1-F10 |
|
47 |
Home |
|
48 |
↑ |
|
49 |
PgUp |
|
4B |
← |
|
4D |
→ |
|
4F |
End |
|
50 |
↓ |
|
51 |
PgDn |
|
52 |
Ins |
|
53 |
Del |
|
54-5D |
Shift F1-F10 |
|
5E-67 |
Ctrl F1-F10 |
|
68-71 |
Alt F1-F10 |
Когда программа запрашивает введенный символ, BIOS возвращает ASCII-код этого символа и его scan-код в регистрах AL и AH соответственно. Другие клавиши, не представленные в кодах ASCII, возвращают 0 в регистре AL и расширенный код в регистре AH, т.е. для определения кода нажатой клавиши необходимо дважды произвести ввод символа с клавиатуры.
Для работы с клавиатурой ПК программист может использовать функции прерывания 16h BIOS и функции прерывания 21h DOS.
Прерывание 16h предусматривает весьма примитивные операции обмена данными с клавиатурой, которые полезны, когда программа исполняется независимо от DOS.
В зависимости от значения, записываемого в регистр AH, прерывание Int 16h позволяет выполнить следующие операции.
Int 16h, функция 00h, чтение символа с клавиатуры Вызов: АН = 00Н
Возврат: АН = scan-код клавиши,
50
AL = код символа.
Одновременно с чтением продвигается указатель буфера. Если буфер пуст, то программа обработки прерывания ожидает нажатия клавиши и затем продолжает его обработку.
Int 16h, функция 01h, получить состояние клавиатуры Вызов: АН = 01h
Возврат: если флаг нуля сброшен, т.е. ZF=0, то АН = scan-код клавиши,
AL = код символа.
Если ZF=1, то буфер клавиатуры пуст.
При вызове данной функции прерывания буфер клавиатуры не очищается, т.е. при последующем вызове функции 0 прерывания 16h будет считан тот же самый символ.
Int 16h, функция 03h, устанавливает скорость повтора Вызов: АН = 03h
АL = 05h
BH = задержка повторения ( 0-3 от 250мс до 1000мс) BL = скорость повторения (00-1Fh от 30 до 2
символов в секунду). Возврат: ничего не возвращает
Данная функция позволяет настроить клавиатуру под скорость ввода информации пользователем.
Int 16h, функция 10h, прочитать символ с расширенной клавиатуры
Вызов: АН = 10h
Возврат: АН = scan-код клавиши
AL = символ ASCII
Эта функция позволяет получать скан-коды дополнительных клавиш F11 и F12, а также клавиш управления курсором, не используя дважды функцию 00h этого же прерывания.
Более гибкие возможности для программистов предоставляют функции прерывания 21h операционной системы. Рассмотрим наиболее встречающиеся в программах функции.
Int 21H, функция 01H, ввод символа с эхо Вызов: AH = 01h
Возврат: AL = код символа
51
Вводит символ с клавиатуры, а затем отображает его на экране дисплея. Если символ не готов, то ждет его появления. Для чтения расширенных ASCII-кодов функцию необходимо вызвать дважды.
Int 21H, функция 06H, непосредственный ввод-вывод через консоль
Вызов: AH = 06h
DL = запрашиваемая функция
00h – FEh, если запрашивается вывод 0FFh – если запрашивается ввод
Возврат: если DL = 00h – FEh, то ничего не возвращается если DL = 0FFh и ZF=0, то
AL = код символа
ZF = 1 символ не готов
Int 21H, функция 07H, нефильтрованный ввод без эхо Вызов: AH = 07h
Возврат: AL = код символа
Выполняет операцию чтения символа с клавиатуры без отображения его на экране дисплея. Если символа нет, то ждет его появления. Для расширенных кодов клавиатуры функцию следует использовать дважды.
Int 21H, функция 08H, ввод без эхо Вызов: AH = 08h
Возврат: AL = код символа
Те же самые операции, что и функция 07Н, только с проверкой на нажатие Ctrl+Break, т.е. реализована возможность прервать программу.
Int 21H, функция 0AH, нефильтрованный ввод без эхо Вызов: AH = 0Ah
DS:DX = сегмент : адрес буфера
Возврат: возврата нет, так как символ помещается в буфер, созданный пользователем.
Буфер клавиатуры, используемый данной функцией, имеет следующий формат:
•1-й байт – максимальное число вводимых символов, установленное программой;
•2-й байт – фактическое число прочитанных символов (счетчик числа символов в буфере);
52