5.10.4. Видеоадаптеры VGA

VGA-совместимые видеоадаптеры управляются при помощи портов ввода-вы­вода ОЗСОЬ - 03CFh, 03B4h, 03B5h, 03D4h, 03D5h, 03DAh, причем реальное чис­ло внутренних регистров видеоадаптера, к которым можно обращаться через это окно, превышает 50. Так как BIOS предоставляет хорошую поддержку для боль­шинства стандартных функций, мы не будем подробно говорить о программиро­вании видеоадаптера на уровне портов, а только рассмотрим основные действия,

для которых принято обращаться к видеоадаптеру напрямую.

Внешние регистры контроллера VGA (03C2h - 03CFh)

Доступ к этим регистрам осуществляется прямым обращением к соответству­ющим портам ввода-вывода.

Регистр состояния ввода О (ISRO) - доступен для чтения из порта ОЗС2

бит 7: произошло прерывание обратного хода луча IRQ2

бит 6: дополнительное устройство 1 (линия FEAT1)

бит 5: дополнительное устройство 0 (линия FEATO)

бит 4: монитор присутствует Регистр вывода (MOR) - доступен для чтения из порта ЗССЪ и для записи как 3C2h

биты 7-6: полярность сигналов развертки: (01, 10, 11) = (400, 350, 480) линий бит 5: 1/0: нечетная/четная страница видеопамяти биты 3-2: частота: (00, 01) = (25,175 МГц, 28,322 МГц) бит 1: 1/0: доступ CPU к видеопамяти разрешен/запрещен бит 0: 1/0: адрес порта контроллера CRT = Регистр состояния ввода 1 (ISR1) - доступен для чтения из порта 03DAh

бит 3: происходит вертикальный обратный ход луча бит 0: происходит любой обратный ход луча

Лучшим моментом для вывода данных в видеопамять является тот, когда элек­тронный луч двигается от конца экрана к началу и экран не обновляется, то есть вертикальный обратный ход луча. Перед копированием в видеопамять полезно вызывать, например, следующую процедуру:

:  Процедура wait_retrace.

;  Возвращает управление в начале обратного вертикального хода луча. :

wait_retrace       proc near push ax

Программирование на уровне портов .'ШЯН

push

dx

 

mov

dx,03DAh

;   Порт регистра ISR1.

wait retrace

end:

 

in "

al, dx

 

test

al,1000b

;   Проверить бит З.

 

 

;  Если не ноль -

jnz

wait_retrace_

end  ;   подождать конца текущего обратного хода,

wait_retrace_

start:

 

in

' al,dx

 

test

al,1000b

;   а теперь подождать начала следующего.

jz

wait_retrace.

.start

pop

dx

 

pop

ax

 

ret

 

 

wait_retrace

endp

 

Регистры контроллера атрибутов (ОЗСОЬ - 03C1h)

Контроллер атрибутов преобразовывает значения байта атрибута символа в цвета символа и фона. Надо записать в порт ОЗСОЬ номер регистра, а затем (вто­рой командой out) - данные для этого регистра. Чтобы убедиться, что ОЗСОЬ на­ходится в состоянии приема номера, а не данных, надо выполнить чтение из ISR1 (порт 03DAh). Порт 03Clh можно использовать для чтения последнего записан­ного индекса или данных.

OOh - OFh; Регистры палитры EGA

биты 5-0: номер регистра в текущей странице VGA DAC, соответствующего данному EGA-цвету Регистр управления режимом бит 7: разбиение регистров VGA DAC для 16-цветных режимов: 1 = 16 страниц по 16 регистров, 0 = 4 страницы по 64 регистра бит 6: 1 = 8-битный цвет, 0 = 4-битный цвет бит 5: горизонтальное панорамирование разрешено бит 3: 1/0: бит 7 атрибута управляет миганием символа/цветом фона

бит 2: девятый пиксел в каждой строке повторяет восьмой

бит 1: 1/0: генерация атрибутов для монохромных/цветных режимов бит 0: 1/0: генерация атрибутов для текстовых/графических режимов lih: Регистр цвета бордюра экрана (по умолчанию OOh)

биты 7-0: номер регистра VGA DAC

12h: Регистр разрешения использования цветовых плоскостей

бит 3: разрешить плоскость 3

бит 2: разрешить плоскость 2

бит 1: разрешить плоскость 1

бит 0: разрешить плоскость О 13h: Регистр горизонтального панорамирования

биты 3-0: величина сдвига по горизонтали в пикселах (деленная на 2 для ре­жима 13h)

14h: Регистр выбора цвета (по умолчанию OOh)

Функции INT 10h AX = lOOOh - 1009h позволяют использовать большинство из этих регистров, но кое-что, например панорамирование, оказывается возмож­ным только при программировании на уровне портов.

Регистры графического контроллера (ОЗСЕп - 03CFh)

Для обращения к регистрам графического контроллера следует записать ин­декс нужного регистра в порт ОЗСЕп, после чего можно будет читать и писать данные для выбранного регистра в порт 03CFh. Если требуется только запись в регистры, можно просто поместить индекс в AL, посылаемый байт - в АН и вы­полнить команду вывода слова в порт ОЗСЕп. Этот контроллер, в первую очередь, предназначен для обеспечения передачи данных между процессором и видеопа­мятью в режимах, использующих цветовые плоскости, как, например, режим 12h (640x480x16).

00h: Регистр установки/сброса

биты 3-0: записывать FFh в цветовую плоскость 3-0 соответственно Olh: Регистр разрешения установки/сброса

биты 3-0: включить режим установки/сброса для цветовой плоскости 3-0

В этом режиме данные для одних цветовых слоев получают от CPU,

а для других - из регистра установки/сброса. Режим действует

только в нулевом режиме работы (см. регистр 05h).

02h: Регистр сравнения цвета

биты 3-0: искомые биты для цветовых плоскостей 3-0

Используется для поиска пиксела заданного цвета, чтобы не обра­щаться по очереди во все цветовые слои.

03h: Регистр циклического сдвига данных

биты 4-3: выбор логической операции:

00 - данные от CPU записываются без изменений

01 - операция AND над CPU и регистром-защелкой

10 - операция OR над CPU и регистром-защелкой

11 - операция XOR над CPU и регистром-защелкой

биты 2-0: на сколько битов выполнять вправо циклический сдвиг данных пе­ред записью в видеопамять

04h: Регистр выбора читаемой плоскости биты 1-0: номер плоскости (0-3)

. Запись сюда изменяет номер цветовой плоскости, данные из которой получа­ет CPU при чтении из видеопамяти.

05h: Регистр выбора режима работы

бит 6: 1/0: 256/16 цветов

бит 4: четные адреса соответствуют плоскостям 0, 2; нечетные - 1, 3 бит 3: 1 режим сравнения цветов

биты 1-0: режим:

00: данные из CPU (бит на пиксел) + установка/сброс + циклический сдвиг + логические функции

!

01: данные в/из регистра-защелки (прочитать в него и записать в дру­гую область памяти быстрее, чем через CPU)

10: данные из CPU, байт на пиксел, младшие 4 бита записываются в соот­ветствующие плоскости то же самое + режим битовой маски 06h: Многоцелевой регистр графического контроллера биты видеопамять:

00: OAOOOOh - OBFFFFh (128 Кб)

01: OAOOOOh - OAFFFFh (64 Кб)

10: OBOOOOh - 0B7FFFh (32 Кб)

11: 0B8000h - OBFFFFh (32 Кб)

бит 0: 1/0: графический/текстовый режим

07h: Регистр игнорирования цветовых плоскостей биты 3-0: игнорировать цветовую плоскость

08h: Регистр битовой маски

Если бит этого регистра 0, то соответствующий бит будет браться из регистра-

защелки, а не из CPU. (Чтобы занести данные в регистр-защелку, надо вы­полнить одну операцию чтения из видеопамяти, при этом в каждый из четы­рех регистров-защелок будет помещено по одному байту из соответствующей

цветовой плоскости.)

Графический контроллер предоставляет весьма богатые возможности по управ­лению режимами, использующими цветовые плоскости. В качестве примера на­пишем процедуру, выводящую точку на экран в режиме 12h (640x480x16) с при­менением механизма установки/сброса.

; Процедура putpixel12h.

; Выводит на экран точку с заданным цветом в режиме 12h (640x480x16).

; Вход:      DX = строка

СХ = столбец

; BP = цвет

; ES = OAOOOh

proc near

pusha

, Вычислить номер байта в видеопамяти.

xor

bx,bx

 

mov

ax, dx

; АХ = строка.

lea

eax, [eax+eax*4]

; АХ = АХ х 5.

shl

ax, 4

; АХ = АХ х 16.

 

 

; АХ = строка х байт в строке

 

 

;   (строка х 80).

push

cx

 

shr

cx,3

; СХ = номер байта в строке.

add

ax,

; АХ = номер байта в видеопамяти.

mov

di, ax

; Сохранить его в БІ.

 

 

; Вычислить номер бита в байте.

pop

cx

 

Сложные приемы программирования

and

cx,07h

; Остаток от деления на 8 - номер ; бита в байте,   считая справа налево.

mov

bx,0080П

 

shr

bx,

;  В ВЬ теперь нужный бит установлен в 1. ;  Программирование портов.

mov

dx,03CEh

; Индексный порт

-.  графического контроллера.

mov

ax,0F01h

;  Регистр 01п: разрешение ; установки/сброса.

out

dx, ax

;  Разрешить установку/сброс для :  всех плоскостей   (эту часть лучше

сделать однажды в программе, например сразу после установки видеорежима,   и не повторять   каждый раз при вызове процедуры).

mov

ах, bp

 

shl

ах, 8

Регистр регистр

 

 

; установки/сброса.

out

dx, ах

; АН = цвет.

mov

al,08

; Порт 08п:   битовая маска.

mov

ah, Ы

; Записать в битовую маску нули

 

 

: всюду, кроме

out

dx, ах

; бита,   соответствующего выводимому

mov

ah, byte

еБ:№]        ; Заполнить

,

mov

es: fdi J. аґп

,

бит

регистры-защелки.

Вывод на экран: ;   выводится единственный ;   в соответствии с содержимым регистра битовой маски, осталвные ;   биты берутся из защелки,  то еств не изменяются.   Цвет выводимого ;   бита полноствю определяется значением регистра установки/сброса, рора ret

putpixel12h endp

Регистры контроллера CRT (03D4h - 03D5h)

Контроллер CRT управляет разверткой и формированием кадров на дисплее. Как и для графического контроллера, чтобы обратиться к регистрам контроллера CRT, следует записать индекс нужного регистра в порт 03D4h, после чего можно будет читать и писать данные для выбранного регистра в порт 03D5h. Если тре­буется только запись в регистры, можно просто поместить индекс в AL, посылае­мый байт — в АН и выполнить команду вывода слова в порт 03D4h.

OOh: общая длина горизонтальной развертки

Olh: длина отображаемой части горизонтальной развертки минус один 02h: начало гашения луча горизонтальной развертки 03h: конец гашения луча горизонтальной развертки

биты 6—5: горизонтальное смещение в текстовых режимах . .

биты 4-0: конец импульса 04h: начало горизонтального обратного хода луча

05п: конец горизонтального обратного хода луча

биты 7, 4-0: конец импульса

биты 6-5: горизонтальное смещение импульса 06Ь: число вертикальных линий растра без двух старших битов 07Ь: дополнительный регистр .

бит 7: бит 9 регистра 10Ь ■

бит 6: бит 9 регистра 12п

бит 5: бит 9 регистра 061т

бит 4: бит 8 регистра 18Ь

бит 3: бит 8 регистра 15Ь

бит 2: бит 8 регистра 10Ь

бит 1: бит 8 регистра 12п

бит 0: бит 8 регистра 06п 08Ь: предварительная горизонтальная развертка

биты 6-5: биты 5 и 4 регистра горизонтального панорамирования

биты 4-0: номер линии в верхней строке, с которой начинается изображение 09Ь: высота символов

бит 7: двойное сканирование (400 линий вместо 200)

бит 6: бит 9 регистра 18Ь

бит 5: бит 9 регистра 15Ь

биты 4-0: высота символов минус один (от 0 до 31) ОАЬ: начальная линия курсора (бит 5: гашение курсора) ОВЬ: конечная линия курсора (биты 6-5: отклонение курсора вправо) ОСЬ: старший байт начального адреса

СЮЬ: младший байт начального адреса (это адрес в видеопамяти, начиная с кото­рого выводится изображение)

ОЕЬ: старший байт позиции курсора ОРЬ: младший байт позиции курсора

10Ь: начало вертикального обратного хода луча без старшего бита конец вертикального обратного хода луча без старшего бита бит 7: защита от записи в регистры 00-07 (кроме бита 4 в 07Ь) бит 6: 1/0: 5/3 цикла регенерации за время обратного хода луча бит 5: 1/0: выключить/включить прерывание по обратному ходу луча бит 4: запись нуля сюда заканчивает обработку прерывания биты 3-0: конец вертикального обратного хода луча

12Ь: число горизонтальных линий минус один без двух старших битов

13Ь: логическая ширина экрана (в словах/двойных словах на строку)

14Ь: положение символа подчеркивания

бит 6: 1/0: адресация словами/двойными словами бит 5: увеличение счетчика адреса регенерации на 4 биты 4-0: положение подчеркивания

15Ь: начало импульса гашения луча вертикальной развертки без двух старших битов

16Ь: конец импульса гашения вертикальной развертки

17Ь: регистр управления режимом

бит 7: горизонтальный и вертикальный ходы луча отключены бит 6: 1/0 - адресация байтами/словами бит 4: 1 - контроллер выключен

бит 3: 1/0 - счетчик адреса регенерации растет на 2/1 на каждый символ бит 2: увеличение в 2 раза разрешения по вертикали 18h: регистр сравнения линий без двух старших битов

(от начала экрана до линии с номером из этого регистра отображается нача­ло видеопамяти, а от этой линии до конца - видеопамять, начиная с адреса, указанного в регистрах      и ODh) 22h: регистр-защелка (только для чтения) 23h: состояние контроллера атрибутов

биты 7-3: текущее значение индекса контроллера атрибутов бит 2: источник адреса палитры

бит 0: состояние порта контроллера атрибутов: 0/1 = индекс/данные

BIOS заполняет регистры этого контроллера соответствующими значениями при переключении видеорежимов. Поскольку одного контроллера CRT мало для полного переключения в новый видеорежим, мы вернемся к этому чуть позже,

а пока посмотрим, как внести небольшие изменения в действующий режим, на­пример: как превратить текстовый режим 80x25 в 80x30:

; 80x30.asm

; Переводит экран в текстовый режим 80x30  (размер символов 8x16)

; (Norton Commander 5.0 в отличие от, .например, FAR восстанавливает режим по .

; окончании программы, но его можно обмануть, если предварительно нажать Alt-F9).

'start:

tiny

 

. code

 

 

.186

 

Для команды outsw.

org

lOOh

СОМ-программа.

mov

ax,3

Установить режим 03h (80X25),

int

10h

только внести небольшие изменения.

mov

dx,3CCh

Порт          регистр вывода          на чтение.

in

al.dx

 

mov

dl,0C2h

Порт 03C2h:  регистр вывода  (MOR) на запись.

or

al.OCOh

Установить полярности І; І - для 480 строк.

out

dx, al

 

mov

dx,03D4h

DX = порт 03D4h: индекс CRT.

mov

si .offset crt480

DS:SI = адрес таблицы данных для CRT.

mov

cx,crt480_l

СХ = ее размер.

rep

outsw

Послать все устанавливаемые параметры в порты

03D4h и 03D5h.

Нельзя забывать сообщать BIOS об изменениях в видеорежиме.

push 0040h

pop       es ;   ES = 0040h.

mov       byte ptr es:[84h],29        ;   0040h:0084h  -  число строк, ret

; Данные-для контроллера CRT в формате индекс в младшем байте, данные ;  в старшем - для записи при помощи команды outsw.

crt480 dw        OC11h     ;   Регистр 11h всегда надо записывать первым,

;  так как его бит 7 разрешает запись в другие

dw OB06h,.3E07h,0EA1Oh,0DF12h,0E715h,0416h        ; регистры.

crt480_l = ($-crt480)/2

end start

Еще одна интересная возможность, которую предоставляет контроллер CRT, -плавная прокрутка экрана при помощи регистра 08h:

; vscroll.asm

;  Плавная прокрутка экрана по вертикали.  Выход - клавиша Esc.

.model

tiny

 

.code

 

 

.186

 

Для push OB400h.

orglOOh

 

СОМ-программа.

start:

 

 

push

OB800h

 

pop

es

 

xor

si,si

; ES:SI - начало видеопамяти.

mov

di,80*25*2

; ES:DI - начало второй страницы видеопамяти.

mov

cx, di

 

rep movs

es:any_label,es:any_label   ;  Скопировать первую страницу во вторую.

mov

dx,G3D4h

;   Порт G3D4h:   индекс CRT.

screen_loop:

 

Цикл по экранам.

mov

cx,80*12*2

CX = начальный адрес - адрес середины экрана.

line_lpop:

 

Цикл по строкам.

mov

al.OCh

Регистр ОСЬ - старший байт начального адреса.

mov

ah, ch

Байт данных - СН.

out

dx, ax

Вывод в порты G3D4, G3D5.

inc

ax

Регистр ODh - младший байт начального адреса.

mov

ah, cl

Байт данных - CL.

out

dx, ax

Вывод в порты G3D4, G3D5.

mov

bx,15

Счетчик линий в строке.

sub

cx, 8G

Переместить начальный адрес на начало

 

 

предыдущей строки (так как это движение вниз).

pel_loop:

 

Цикл по линиям в строке. '

call

wait_retrace

Подождать обратного хода луча.

mov

al,8

Регистр     - выбор номера линии в первой

 

 

строке, с которой начинается вывод изображения

mov

ah.bl

(номер линии из BL).

out

dx,ax

 

dec jge

wait_retrace

any_label

end

bx

pel_loop

Уменьшить число линий.

Если больше или равно нулю -

прокрутилась до конца и цикл

продолжается.

строка еще по линиям

 

in

al,60h

Прочитать скан-код последнего символа.

 

cmp

al,8lh

Если это 81 h (отпускание клавиши Esc),

 

jz

done

выйти из программы.

 

cmp

cx,0

Если еще не прокрутился целый экран,

 

jge

line_loop

продолжить цикл по строкам.

 

jmp

short screen_loop

Иначе: продолжить цикл по экранам.

done:

 

 

Выход из программы.

 

mov

ax, 8

Записать в регистр CRT 08h

 

out

dx, ax

байт 00 (никакого сдвига по вертикали),

 

add

ax, 4

а также 00 в регистр

 

out

ax

 

 

inc

ax

и ODh (начальный адрес

 

out

dx, ax

с началом

 

ret

 

 

wait_retrace

proc near

 

 

push

dx

 

 

mov

dx,03DAh

 

VRTL1:

in

dx

Порт 03DAh  -   регистр ISR1.

 

test

al,8

 

 

j.nz

VRTL1

Подождать конца текущего обратного хода

VRTL2:

in

al, dx

 

 

test

al,8

 

 

U

VRTL2

а теперь начала следующего.

 

pop

dx

 

 

ret

 

 

endp

label byte start

Метка для переопределения сегмента в

Горизонтальная прокрутка осуществляется аналогично, только с использова­нием регистра горизонтального панорамирования Ш из контроллера атрибутов.

Регистры синхронизатора (03С4п - ОЗСБЬ)

Для обращения к регистрам синхронизатора следует записать индекс нужного регистра в порт 03C4h, после чего можно будет читать и писать данные для вы­бранного регистра в порт 03C5h. Точно так же, если требуется только запись в ре­гистры, можно просто поместить индекс в AL, посылаемый байт - в АН и выпол­нить команду вывода слова в порт

ООЬ: регистр сброса синхронизации

бит 1: запись нуля сюда вызывает синхронный сброс бит 0: запись нуля сюда вызывает асинхронный сброс

Olh: регистр режима синхронизации

бит 5: 1; обмен данными между видеопамятью и дисплеем выключен

бит 3: 1: частота обновления для символов уменьшена в два раза

бит 0: 1/0: ширина символа 8/9 точек 02h: регистр маски записи

бит 3: разрешена запись CPU в цветовую плоскость 3

бит 2: разрешена запись CPU в цветовую плоскость 2

бит 1: разрешена запись CPU в цветовую плоскость 1

бит 0: разрешена запись CPU в цветовую плоскость О 03h: регистр выбора шрифта

бит 5: если бит 3 атрибута символа = 1, символ берется из шрифта 2

бит 4: если бит 3 атрибута символа = 0, символ берется из шрифта 2

биты 3-2: номер таблицы для шрифта 2 биты 1-0: номер таблицы для шрифта 1

(00, 01, 10, 11) = (О Кб, 16 Кб, 32 Кб, 48 Кб от начала памяти шрифтов VGA) 04h: регистр организации видеопамяти

бит 3: 1: режим CHAIN-4 (используется только в видеорежиме 13К) бит 2: 0: четные адреса обращаются к плоскостям 0, 2, нечетные - к 1, 3 бит 1: объем видеопамяти больше 64 Кб

Даже несмотря на то, что BIOS позволяет использовать некоторые возможно­сти этих регистров, в частности работу со шрифтами (INT 10h АН = llh) и вы­ключение обмена данными между видеопамятью и дисплеем (INT 10h, АН = 12h, 32h), прямое программирование регистров синхронизатора вместе с регист­рами контроллера CRT разрешает изменять характеристики видеорежимов VGA, вплоть до установки нестандартных видеорежимов. Наиболее популярными режи­мами являются так называемые режимы X с 256 цветами и с разрешением 320 или 360 пикселов по горизонтали и 200, 240, 400 или 480 пикселов по вертикали. Поскольку такие режимы не поддерживаются BIOS, для их реализации нужно на­писать все необходимые процедуры - установку видеорежима, вывод пиксела, чтение пиксела, переключение страниц, изменение палитры, загрузку шрифтов. При этом для всех режимов из этой серии, кроме 320x240x256, приходится также учитывать измененное соотношение размеров экрана по вертикали и горизонта­ли, чтобы круг, выведенный на экран, не выглядел как эллипс, а квадрат - как пря­моугольник.

Установка нового режима выполняется почти точно так же, как и в предыду­щем примере, - путем модификации существующего. Кроме того, нам придется изменять частоту кадров (биты 3-2 регистра а это приведет к сбою синх-

ронизации, если мы не выключим синхронизатор на время изменения частоты (записью в регистр 00h):

; Процедура setjnodex.

; Переводит видеоадаптер VGA в один из режимов X с 256 цветами.

; Вход: 01 = номер режима

; 0:   320x200,   соотношение сторон 1,2:1

; 1:  320x400,   соотношение сторон 2,4:1

360x200, соотношение сторон 1,35:1

360x400, соотношение сторон 2,7:1

320x240, соотношение сторон 1:1

320x480, соотношение сторон 2:1

360x240,   соотношение сторон 1,125:1

360x480, соотношение сторон 2,25:1 = С8

Для вывода информации на экран в этих режимах см.  процедуру ри!р1хе!_х

2: 3: 4:

5: 6: 7:

DS

setmode х

mov 4nt mov int

cmp

ja

shl

mov mov

out

mov

out

mov mov

out

mov

mov rep

mov rep

proc near ax,12h 10h

ax,13h 10h

di,7

exitjnodex di,1

ptr

Очистить все четыре цветовые плоскости видеопамяти. Установить режим 13І1, который будем модифицировать.

Если нас вызвали с БІ > 7, выйти из процедуры (оставшись в режиме 131т). Умножить на 2, так как х_тогіез -таблица слов. х_шос^[(И]     ; Прочитать

адрес таблицы настроек для выбранного режима.

dx,03C4h ;

ах,OlOOh ;

dx.ax ;

ах,0604h ;

ax

dl,0C2h ;

al.byte ptr [di] ;

dx.al ;

dl,0D4h

si,word ptr offset

cx,a

outsw si,word ptr offset

cx, 7

outsw

Порт 03C4h - индекс синхронизатора.

Регистр OOh, значение 01. Асинхронный сброс. Регистр 04h,  значение 06h. Отключить режим CHAIN4.

Порт 03С2П - регистр M0R на запись. Записать в него значение частоты кадров и полярности развертки для выбранного режима.

Порт 03D4h - индекс контроллера CRT. [di+2J

Адрес строки с настройками

для выбранной ширины в DS:SI. Длина строки настроек в СХ. Вывод строки слов в порты 03D4/03D5. [di+4] ; Настройки для выбранной высоты в DS:SI.

строки настроек в СХ/

mov

mov rep

mov mov

mov mov out

exit_modex:

ret ptr offset        • Настройки

; для включения/выключения удвоения

; по вертикали (200/400 и 240/480 строк).

сх,3

outsw

ах, word ptr offset [di+8] word ptr x_width,ax

• Число байтов в

Сохранитв в переменной x.width.

dl,OC4h ax,0300h dx, ax

Порт 03С4п - индекс синхронизатора.

Регистр ООП, значение 03. Выйти из состояния сброса.

; Таблица адресов таблиц с настройками режимов, xjrodes dw        offset mode_0,offset mode_1

dw        offset mode_2,offset mode 3

dw        offset mode 4,offset mode_5

dw        offset mode_6,offset mode_7

; Таблица настроек режимов: значение регистра MOR, адрес строки ; настроек ширины, адрес строки настроек высоты, адрес строки ; настроек удвоения по вертикали, число байтов в строке.

63h,offset mode_320w,offset mode_200h,offset mode.double,320/4 63h,offset mode_320w,offset mode_400h,offset mode_single,320/4 67h,offset mode_360w,offset mode_200h,offset mode_double,360/4 67h,offset mode„360w,offset mode_400h,offset mode_single,360/4 0E3h,offset mode J320w,offset mode_240h,offset mode_double,320/4 0E3h,offset mode_320w,offset mode_480h,offset mode_single,320/4 0E7h,offset mode_360w,offset mode_240h,offset

mode_0

dw

mode 1

dw

mode_2

dw

mode_3

dw

mode_4

dw

mode_5

dw

mode_6

dw

mode 7

dw

• Настройки

; старший -mode_320w: •

0E7h,offset mode_360w,offset

В каждом слове младший байт

mode_double,360/4 mode_480h,offset mode_single,360/4

- номер регистра, в этот регистр заносится. ;  Настройка ширины 320. Первый регистр обязательно 11п, хотя он и не относится к ширине, но разрешает запись в остальные регистры, если она была запрещена

CRT.

значение,

которое

(!)■

dw

mode_360w:

dw

mode_200h:

mode_400h:

dw

mode_240h: mode_480h:

dw

mode_single:

dw

mode_double:

dw

setmode_x 0Е11П, 5Р00п, 4Р01И, 5002г1,8203г1,5404п,8005п,2813г1

;  Настройка ширины 360. ОЕНЬ, 6В00Г1, 5901П, 5А02г., ЗЕОЗг., 5Е04И, 8А05И, 2013И

;  Настройка высоты 200/400. ОВРОбГ!, 1Р07п, 9010(1, 0Е11п, 8Р12г>, 9615И, 08916)1

;  Настройка высоты 240/480. ОРОбП, ЗЕ07И, ОЕАЮИ, 0С11Г1, 00Е12Ь, 0Е715И, 0616п

;  Настройка режимов без удвоения. 4009п,0014п,ОЕ317п

; Настройка режимов с удвоением. 410911, 0014П, 0Е317П

епбр

 ;   Число байтов в строке.

;  Эту переменную инициализирует зет.тос1е_х, а использует риср1хе1_х.

Процедура

Выводит точку с заданным цветом

в текущем режиме X.

;   Вход:   DX =

строка

 

;            СХ =

столбец

 

;            ВР =

цвет

 

;           ES =

OAOOOh

 

;            DS =

сегмент, в

котором находится переменная

putpixel_x

proc

near

pusha

 

 

mov

ax, dx

 

шиї

word ptr

x_width ; AX = строка х число байтов в строке.

mov

di,cx

; ' DI = столбец.

shr

di,2

; DI = столбец/4 (номер байта в строке).

add

di, ax

;  01 = номер байта в видеопамяти/

mov

ax,0102h

; AL = 02h   (номер регистра).

 

 

; АН = 01   (битовая маска).

and

cl,03h

CL = остаток от деления столбца на 4 =

 

 

номер цветовой плоскости.

shl

ah, cl

Теперь в АН выставлен в 1 бит,

 

 

соответствующий нужной цветовой плоскости.

mov

dx,03C4h

Порт            -  индекс синхронизатора.

out

dx, ax

Разрешить запись только

 

 

в нужную плоскость.

mov

ax, bp

Цвет в AL.

stosb

 

Вывод байта в видеопамять.

рора

 

 

ret

 

 

putpixel_x

endp

 

Регистры VGA DAC (3C6h - 3C9h)

Таблица цветов VGA на самом деле представляет собой 256 регистров, в каж­дом из которых записаны три 6-битных числа, соответствующих уровням красно­го, зеленого и синего цвета. Подфункции INT lOhAX = 1010b. - 101Bh позволяют

удобно работать с этими регистрами, но, если требуется максимальная скорость,

программировать их на уровне портов ввода-вывода не намного сложнее.

03C6h для чтения/записи: регистр маскирования пикселов (по умолчанию OFFh) При обращении к регистру DAC выполняется операция AND над его номе­ром и содержимым этого регистра.

03C7h для записи: регистр индекса DAC для режима чтения

Запись байта сюда переводит DAC в режим чтения, так что следующее чте­ние из        вернет значение регистра палитры с этим индексом.

03С7п для чтения: регистр состояния DAC

биты 1-0: ООЬ/ИЬ - DAC в режиме записи/чтения

03С8п для чтения/записи: регистр индекса DAC для режима записи

Запись байта сюда переводит DAC в режим записи, поэтому дальнейший вывод в 03C9h будет приводить к записи новых значений в регистры палит­ры, начиная с этого индекса.

03C9h для чтения/записи: регистр данных DAC

Чтение отсюда считывает значение регистра палитры с индексом, помещен­ным предварительно в 03C8h, запись - записывает новое значение в регистр палитры с индексом, находящимся в 03C8h. На каждый регистр требуются три операции чтения/записи, передающие три 6-битных значения уровня цвета: красный, зеленый, синий. После третьей операции чтения/записи ин­декс текущего регистра палитры увеличивается на 1, так что можно считы­вать/записывать сразу несколько регистров

Команды insb/outsb серьезно облегчают работу с регистрами DAC в тех случа­ях, когда требуется считывать или загружать значительные участки палитры или всю палитру целиком, - такие процедуры оказываются и быстрее, и меньше ана­логичных, написанных с использованием прерывания INT 10h. Посмотрим, как это реализуется на примере программы плавного гашения экрана.

; fadeout.asm

;  Выполняет плавное гашение экрана.

.model tiny

start:

. code .186

org

eld mov

call

mov call

mov

main_loop:

push

call

mov mov call

call

mov

call

pop 100h

di, offset palettes read_palette

di, offset palettes+256*3 read_palette

CX, 64

cx

wait_retrace

di,offset palettes+256-

si, di

dec_palette

wait_retrace

si,offset palettes+256*

write_palette

cx

Для команд шзЬ/оибзЬ. СОМ-программа.

Для команд строковой обработки.

Сохранить текущую палитру, чтобы восстановить в самом конце программы,

а также записать еще одну копию текущей палитры, которую будем модифицировать.

Счетчик цикла изменения палитры.

Подождать начала обратного хода луча.

Уменьшить яркость всех цветов. Подождать начала следующего

обратного хода луча.

Записать новую палитру.

loop

ШОУ

саіі

гес

main_loop

palettes

write_palette

Цикл выполняется 64 раза - достаточно для обнуления самого яркого цвета (максимальное значение 6-битной компоненты - 63).

Восстановить первоначальную палитру. Конец программы.

чтения.

; 'Процедура

read_palette.

 

; Помещает палитру УОА в строку

по адресу ЕЭ:01.

read_palette

proc near

 

mov

dx,03C7h

; Порт 03С7п - индекс БАС/режим

mov

al,0

; Начинать с нулевого цвета.

out

dx, al

 

mov

dl,0C9h

; Порт ОЗСЭИ - данные БАС.

mov

cx,256*3

; Прочитать 256 х 3 байт

rep

insb

; в строку по адресу ЕБ:01.

ret

 

 

read_palette

endp

 

; Процедура write_palette.

 

Загружает в

DAC VGA палитру из

строки по адресу 08:81.

write_palette

proc near

 

mov

dx,03C8h

; Порт 03С8І1 - индекс БАС/режим

mov

al,0

Начинать с нулевого цвета.

out

dx,al

 

mov

dl,0C9h

; Порт ОЗСЭп - данные БАС.

mov

cx,256*3

; Записать 256 х 3 байт

rep

outsb

; из строки в 05:51.

записи.

гес

ягіве_раМве

endp

Процедура аес_ра1еббе.

Уменьшает значение каждого байта на 1 с насыщением (то есть, после того как байт становится равен нулю,  он больше не уменьшается) из строки в 08:81 и записывает результат в строку в Б8:81.

dec_paiette

. mov

dec_ioop:

• lodsb test

jz

dec

already_zero:

stosb

loop ret

dec_palette

proc near cx,256*3

al.al

already_zero ax

dec^loop

Длина строки 256 х 3 байт.

Прочитать байт. Если он ноль,

пропустить следующую команду. Уменьшить байт на 1.

Записать его обратно. Повторить 256 х 3 раз.

endp

; Процедура w-ait_r.etr.ace. '

; Ожидание начала следующего обратного хода луча.

wait_retrace push

proc

dx near

mov in

dx,03DAh

VRTL1:

al, dx

al,8

VRTL1

al.dx al,8

VRTL2 dx

Порт

регистр ISR1.

test

jnz in

Подождать конца текущего обратного хода луча.

VRTL2:

test

pop ret

А теперь начала следующего.

wait_retrace

endp

palettes:

За концом программы мы храним две копии палитры - всего 1,5 Кб.

end start