Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Уроки ассемблеру. Быстро и просто. Урок 22


Сегодня, друзья, мы попытаемся рисовать линии. В качестве примера я выбрал горизонтальную линию в графическом режиме 80х25 (такой работает на моём ноутбуке). Причём мы нарисуем не просто линию, а линию путём ввода с клавиатуры (клавиша "вправо"). Вот текст программы:

CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h

begin:
mov ax,03h
int 10h ;графический режим 80х25.
mov bl,03h ;цвет линии.
mov cx,1
mov dx,0 ;начальные координаты точки.

mainloop:
mov ah,7 ;ждём символ с клавиатуры.
int 21h

cmp al,27 ;...это ESC?
je quit ;да - на выход!

cmp al,4dh ;сравнение со стрелкой "вправо".
je key_right ;переход в обработчик.
jmp mainloop ;если да, не выходим, а ждём другую клавишу.

draw: ;рисование линии.
mov ah,09h
mov al,0C4h ;горизонтальная линия (0B3h - вертикальная).
mov bh,00 ;страница 0
int 10h
jmp mainloop ;продолжаем ждать символ.

key_right: ;обработчик клавиши "вправо".
inc cx ;рисуем ещё точку
jmp draw

quit: ;обработчик клавиши ESC.
int 20h

CSEG ends
end begin

Прерывание INT 10H обеспечивает управление всем экраном. В регистре AH устанавливается код, определяющий функцию прерывания. Команда cохраняет содержимое регистров BX, CX, DX, SI и BP. Ниже описываются все возможные функции.

AH=00: Установка режима. Данная функция позволяет переключать цветной монитор в текстовый или графический режим. Установка pежима для выполняемой в текущий момент программы осуществляется c помощью INT 10H. При установке происходит очистка экрана. Содержимое регистра AL может быть следующим:

00 40 х 25 чёрно-белый текстовый режим
01 40 х 25 стандартный 16-цветовой текстовый режим
02 80 х 25 чёрно-белый текстовый режим
03 80 х 25 стандартный 16-цветовой текстовый режим
04 320 х 200 стандартный 4-цветовой графический режим
05 320 х 200 чёрно-белый графический режим
06 640 х 200 чёрно-белый графический режим
07 80 х 25 чёрно-белый стандартный монохромный
08 - 0A форматы для модели PCjr
0D 320 х 200 16-цветовой графический режим (EGA)
0E 640 х 200 16-цветовой графический режим (EGA)
0F 640 х 350 чёрно-белый графический режим (EGA)
10 640 х 350 64-цветовой графический режим (EGA)

EGA (Enhanced Graphics Adapter) - обозначает усовершенствованный графический адаптер. Следующий пример показывает установку стандартного 16-цветового текстового режима:

MOV AH,00 ;Функция установки режима
MOV AL,03 ;Стандартный цветной текст 80 х 25
INT 10H ;Вызвать BIOS

Для определения типа адаптера, установленного в системе, служит прерывание BIOS INT 11H. Данная команда возвращает в регистре AX значение, в котором биты 5 и 4 указывают на видеорежим:

01 40 х 25 чёрно-белый режим в цветном адаптере
10 80 х 25 чёрно-белый режим в цветном адаптере
11 80 х 25 чёрно-белый режим в чёрно-белом адаптере

Программа, работающая с неизвестным типом монитора, может провеpить тип по регистру AX после INT 11H и затем установить необходимый режим.

AH=01: Установка размера курсора. Курсор не является символом из набора ASCII-кодов. Компьютер имеет собственное аппаратное обеспечение для управления видом курсора. Для этого имеется специальная обработка по INT прерыванию. Обычно символ курсоpа похож на символ подчеркивания. Используя INT 10H, можно управлять вертикальным размером курсора: биты 4-0 в регистре CH для верхней линии
сканирования, а биты 4-0 в регистре CL - для нижней. Можно установить любой pазмер курсора по вертикали: от 0 до 13 для монохромных и EGA монитоpов и от 0 до 7 для большинства цветных мониторов. Приведем пример для увеличения размера курсора от его верхней до нижней линии сканирования:

MOV AH,01 ;Установить размер курсора
MOV CH,00 ;Верхняя линия сканирования
MOV CL,13 ;Нижняя линия сканирования
INT 10H ;Вызвать BIOS

В результате выполнения этих команд курсор превратится в сплошной мигающий прямоугольник. Можно установить любой размер курсора между верхней и нижней границами, например, 04/08, 03/10 и т.д. Курсор сохраняет свой вид, пока программа не изменит его. Использование размеров 12/13 (для моно) и 6/7 (для цвета) переводит курсор в его нормальный вид.

AH=02: Установка позиции курсора. Эта функция устанавлива ет курcор в любую позицию на экране в соответствии с коорди натами cтроки и столбца. Номер страницы обычно равен 0, но может иметь значение от 0 до 3 при 80 столбцах на экране. Для установки позиции курсора необходимо занести в регистр AH значение 02, в регистр BH номер страницы и в регистр DX координаты строки и столбца:

MOV AH,02 ;Установить положение курсора
MOV BH,00 ;Страница 0
MOV DH,строка ;Строка
MOV DL,столбец ;Столбец
INT 10H ;Вызвать BIOS

AH=03: Чтение текущего положения курсора. Программа может определить положение курсора на экране (строку и столбец), а также pазмер курсора, следующим образом:

MOV AH,03 ;Определить положение курсора
MOV BH,00 ;Установить страницу 0
INT 10H ;Вызвать BIOS

После возврата регистр DH будет содержать номер строки, а регистр DL - номер столбца. В регистре CH будет верхняя линия cканирования, а в регистре CL - нижняя.

AH=04: Чтение положения светового пера. Данная функция используeтся в графическом режиме для определения положения светового пеpа.

AH=05: Выбор активной страницы. Новая страница устанавли вается для цветных текстовых режимов от 0 до 3. Для режима 40 х 25 возможно устанавливать до 8 страниц (от 0 до 7), а для режима 80 х 25 - до 4 страниц (от 0 до 3).
MOV AH,05 ;Установить активную страницу
MOV AL,страница ;Номер страницы
INT 10H ;Вызвать BIOS

AH=06: Прокрутка экрана вверх. Когда программа пытается выдать текст на строку ниже последней на экране, то происхо дит переход на верхнюю строку. Даже если с помощью прерыва ния будет специфиpован нулевой столбец, все равно предпола гается новая строка, и нижние строки на экране будут испорчены. Для решения этой проблемы используется прокрутка экрана.
Ранее код 06 использовался для очистки экрана. В тексто вом режиме установка в регистре AL значения 00 приводит к полной прокрутке вверх всего экрана, очищая его пробелами. Установка ненулевого значения в регистре AL определяет количество строк прокрутки экрана вверх. Верхние строки уходят с экрана, а чистые строки вводятся снизу. Следующие команды выполняют прокрутку всего экрана на одну строку:

MOV AX,0601H ;Прокрутить на одну строку вверх
MOV BH,07 ;Атрибут: нормальный, черно-белый
MOV CX,0000 ;Координаты от 00,00
MOV DX,184FH ; до 24,79 (полный экран)
INT 10H ;Вызвать BIOS

Для прокрутки любого количества строк необходимо устано вить соответствующее значение в регистре AL. Регистр BH содержит атрибут для нормального или инвертированного отобра жения, мигания, установки цвета и т.д. Значения в регистрах CX и DX позволяют прокручивать любую часть экрана. Ниже объясняется стандартный подход к прокрутке:

1. Определить в элементе ROW (строка) значение 0 для
установки строки положения курсора.
2. Выдать текст и продвинуть курсор на следующую строку.
3. Проверить, находится ли курсор на последней строке
(CMP ROW,22).
4. Если да, то увеличить элемент ROW (INC ROW) и выйти.
5. Если нет, то прокрутить экран на одну строку и, исполь
зуя ROW переустановить курсор.

AH=07: Прокрутка экрана вниз. Для текстового режима прокрутка экрана вниз обозначает удаление нижних строк и вставка чистых строк сверху. Регистр AH должен содержать 07, значения остальных регистpов аналогичны функции 06 для прокрутки вверх.

AH=08: Чтение атрибута/символа в текущей позиции курсора. Для чтения символа и байта атрибута из дисплейного буфера, как в текстовом, так и в графическом режиме используются следующие команды:
MOV AH,08 ;Запрос на чтение атр./симв.
MOV BH,00 ;Страница 0 (для текстового реж.)
INT 10H ;Вызвать BIOS
Данная функция возвращает в регистре AL значение символа, а в AH - его атрибут. В графическом режиме функция возвращает шест. 00 для не ASCII-кодов. Так как эта функция читает только один cимвол, то для символьной строки необходима организация цикла.

AH=09: Вывод атрибута/символа в текущую позицию курсора. Для вывода на экран символов в текстовом или графическом режиме с установкой мигания, инвертирования и т.д. можно воспользоваться следующими командами:

MOV AH,09 ;Функция вывода
MOV AL,символ ;Выводимый символ
MOV BH,страница ;Номер страницы (текст.реж.)
MOV BL,атрибут ;Атрибут или цвет
MOV CX,повторение ;Число повторений символа
INT 10H ;Вызвать BIOS

В регистр AL должен быть помещен выводимый на экран символ. Значение в регистре CX определяет число повторений символа на экране. Вывод на экран последовательности различных симво лов требует организации цикла. Данная функция не перемещает курсор. В следующем примере на экран выводится пять мигающих "сердечек" в инвертированном виде:

MOV AH,09 ;Функция вывода
MOV AL,03H ;Черви (карточная масть)
MOV BH,00 ;Страница 0 (текст. режим)
MOV BL,0F0H ;Мигание, инверсия
MOV CX,05 ;Пять раз
INT 10H ;Вызвать BIOS

В текстовом (но не в графическом) режиме символы автомати чески выводятся на экран и переходят с одной строки на другую. Для вывода на экран текста запроса или сообщения необходимо составить программу, которая устанавливает в регистре CX значение 01 и в цикле загружает в регистр AL из памяти выводимые символы текста. Так как регистр CX в данном случае занят, то нельзя использовать команду LOOP. Кроме того, при выводе каждого символа необходимо дополнительно продвигать курсор в следующий столбец (функция 02).
В графическом режиме регистр BL используется для определе ния цвета графики. Если бит 7 равен 0, то заданный цвет заме няет текущий цвет точки, если бит 7 равен 1, то происходит комбинация цветов с помощью команды XOR.

AH=0A: Вывод символа в текущую позицию курсора. Единствен ная разница между функциями 0A и 09 состоит в том, что функция 0A не устанавливает атрибут:
MOV AH,0AH ;Функция вывода
MOV AL,символ ;Выводимый символ
MOV BH,страница ;Номер страницы (для текста)
MOV CX,повторение ;Число повторений символа
INT 10H ;Вызвать BIOS

Для большинства применений команда прерывания DOS INT 21H более удобна.

AH=0E: Вывод в режиме телетайпа. Данная функция позволяет использовать монитор, как простой терминал. Для выполнения этой функции необходимо установить в регистре AH шест. значение 0E, в pегистр AL поместить выводимый символ, цвет текста (в графическом режиме) занести в регистр BL и номер страницы для текстового режима - в регистр BH. Звуковой сигнал (код 07H), возврат на одну позицию (08H), конец строки (0AH) и возврат каретки (0DH) действуют, как команды для форматизации экрана. Данная функция автоматически продви гает курсор, переводит символы на следующую cтроку, выполня ет прокрутку экрана и сохраняет текущие атрибуты экрана.

AH=0F: Получение текущего видео режима. Данная функция возвращает в регистре AL текущий видео режим (см.функцию AH=00), в pегистре AH - число символов в строке (20, 40 или 80), в регистре BH - номер страницы.

AH=13: Вывод символьной строки (только для AT). Данная функция позволяет на компьютерах типа AT выводить на экран символьные строки с установкой атрибутов и перемещением курсора:

MOV AH,13H ;Функция вывода на экран
MOV AL,сервис ;0, 1, 2 или 3
MOV BH,страница ;
LEA BP,адрес ;Адрес строки в ES:BP
MOV CX,длина ;Длина строки
MOV DX,экран ;Координаты на экране
INT 10H ;Вызвать BIOS

Возможен следующий дополнительный сервис:
0 - использовать атрибут и не перемещать курсор;
1 - использовать атрибут и переместить курсор;
2 - вывести символ, затем атрибут и не перемещать курсор;
3 - вывести символ, затем атрибут и переместить курсор.

А теперь рисуем прямоугольник. Конечно, не самый оптимизированный текст: предлагаю оптимизировать самостоятельно. Текст снабжён комментариями. Кодировка 866.

ml test.asm /AT

CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h

begin:
mov ax,03h
int 10h ;графический режим 80х25.
mov bl,03h ;цвет линии.
mov cx,1 ;начальная длина линии.
mov dx,0 ;начальные координаты точки (dh=0, dl=0).


mov si,40 ;начало цикла -
draw: ;рисование линии.
mov ah,09h
mov al,0C4h ;горизонтальная линия (0B3h - вертикальная).
mov bh,00 ;страница 0.
int 10h
inc cx ;длина линии увеличивается на 1.

dec si ;работа с циклом - уменьшаем на 1
cmp si,0 ;и проверяем, отработал ли он 40 раз.
jne draw

mov ah,7 ;ждём символ с клавиатуры (пауза).
int 21h

mov cx,1

mov ah,02 ;установить положение курсора.
mov bh,00 ;cтраница 0.
mov dh,0 ;cтрока.
mov dl,40 ;cтолбец.
int 10h ;вызвать BIOS.


mov si,20
draw1: ;рисование линии.
mov ah,09h
mov al,0B3h ;вертикальная линия.
mov bh,00 ;страница 0
int 10h

call Down ;вызов подпрограммы.

dec si ;работа с циклом - уменьшаем на 1 и т.д.
cmp si,0
jne draw1

mov ah,7 ;ждём символ с клавиатуры.
int 21h

mov ah,02 ;установить положение курсора.
mov bh,00 ;cтраница 0.
mov dh,20
mov dl,0 ;cтолбец.
int 10h ;вызвать BIOS.

mov si,40 ;начало цикла -
draw2: ;рисование линии.
mov ah,09h
mov al,0C4h ;горизонтальная линия (0B3h - вертикальная).
mov bh,00 ;страница 0.
int 10h
inc cx ;длина линии увеличивается на 1.

dec si ;работа с циклом - уменьшаем на 1
cmp si,0 ;и проверяем, отработал ли он 40 раз.
jne draw2

mov ah,7 ;ждём символ с клавиатуры (пауза).
int 21h

mov cx,1

mov ah,02 ;установить положение курсора.
mov bh,00 ;cтраница 0.
mov dh,0 ;cтрока.
mov dl,0 ;cтолбец.
int 10h ;вызвать BIOS.

mov si,20
draw3: ;рисование линии.
mov ah,09h
mov al,0B3h ;вертикальная линия.
mov bh,00 ;страница 0
int 10h

call Down ;вызов подпрограммы.

dec si ;работа с циклом - уменьшаем на 1 и т.д.
cmp si,0
jne draw3

mov ah,7 ;ждём символ с клавиатуры.
int 21h

quit: ;обработчик клавиши ESC.
int 20h

Down proc
mov ah,02 ;установить положение курсора
mov bh,00 ;страница 0.
inc dh ;следующая строка.
int 10h ;вызвать BIOS
ret
Down endp

CSEG ends
end begin

 


В избранное