Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование видеоадаптеров.

© Александр Фролов, Григорий Фролов
Том 21, М.: Диалог-МИФИ, 1993.

[Назад] [Содеожание] [Дальше]

Регистры контроллера ЭЛТ

Регистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране и форму курсора. Для видеоадаптеров CGA и EGA регистры контроллера ЭЛТ также управляют световым пером.

Большинство из регистров ЭЛТ не представляют интереса. Более того, их неправильное использование может послужить причиной физического разрушения монитора. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера. Назначение и формат ряда регистров контроллера ЭЛТ различаются для видеоадаптеров EGA, VGA, SVGA и для видеоадаптеров MDA, Hercules, CGA.

При программировании регистров контроллера ЭЛТ используется понятие одного знакоместа (characters) и времени необходимого для отображения одного символа (character clock). При вычислении значений регистров следует учесть, что ширина одного символа составляет 8 пикселов.

Растр состоит из совокупности строк развертки, следующих одна за другой. Электронный луч включается в начале каждой строки и выключается в конце. Включение и выключение электронного луча выполняется сигналом разрешения отображения (Display Enable), вырабатываемым контроллером ЭЛТ.

Когда электронный луч включен (разрешено отображение) видеоадаптер читает данные из видеопамяти и соответствующим образом модулирует интенсивность и цвет электронного луча.

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

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

Контроллер ЭЛТ позволяет оставить электронный луч включенным во время перемещения по не отражаемой области. При этом вокруг изображения образуется цветная рамка. Размер и цвет рамки вы можете задавать сами.

После того как электронный луч прочертит все горизонтальные линии растра, контроллер ЭЛТ отключает сигнал разрешения отображения (электронный луч гаснет) и вырабатывает сигнал вертикального обратного хода луча. Электронный луч перемещается с нижней части экрана в верхний левый угол. Продолжительность вертикального обратного хода луча меньше, чем период вертикального неотображаемого интервала. В результате в нижней и верхней части экрана возникают неотображаемые области.

Одной из основополагающих величин, определяющих разрешающую способность режимов видеоадаптера, является частота вывода пикселов на экран монитора. Эта частота определяется генератором синхросигналов видеоадаптера. Чем выше частота вывода, тем больше пикселов может уместиться на экране при известной частоте кадров и частоте строчной развертки.

Генераторы синхросигналов видеоадаптеров MDA, CGA и Hercules работают только на одной частоте. Для видеоадаптеров EGA, VGA и SVGA доступно несколько различных частот.

Старые модели мониторов могут работать только с фиксированными значениями частоты горизонтальной и вертикальной развертки. Практически все современные мониторы могут работать в некотором диапазоне частот. Поэтому они называются мультичастотными.

Видеоадаптер

Режим

Частота вывода пикселов, Мгц

Частота горизонтальной развертки, Кгц

Частота вертикальной развертки, Гц

MDA

720х350

16257

18430

50

CGA

640х200

14318

15750

60

EGA

640х200

14318

15750

60

640х350

16257

21850

60

720х350

16257

18430

50

VGA

640х400

25175

31500

70

720х400

28322

31500

70

640х480

25175

31500

60

640х350

25175

31500

70

SVGA

640х480

31500

37861

72,809

800х600

40000

37879

60,317

800х600

50000

48077

72,187

1024х768

65000

48363

60,000

1024х768

75000

56476

70,069

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

Если вы самостоятельно программируете регистры ЭЛТ видеоадаптеров VGA или SVGA вы должны отнять от полученной величины число 5 (для адаптера EGA следует отнять 2) и записать результат в регистр общей длинны линии горизонтальной развертки (Horizontal Total Register - HTR).

Во время выполнения горизонтальной развертки отображаются только пикселы в рабочей области экрана. Например, для режима VGA 640х480 пикселов, на одной линии горизонтальной развертки отображается только 640 пикселов. Разделите количество пикселов отображаемых в одной строке на 8 и вы узнаете, сколько символов выводится в каждой строке. Полученное значение записывается при выборе режима работы адаптера в регистр длины отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER).

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

Регистры начала импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) и конца импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) определяют размер нерабочей области горизонтальной развертки.

Регистры начала горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) и конца импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) определяют момент начала и окончания горизонтального обратного хода луча.

При вычислении значений регистров SHRR и EHRR следует учитывать, что для большинства мониторов, совместимых с видеоадаптерами VGA требуется отвести на горизонтальный обратный ход луча 2-4 микросекунды. Значения регистров SHRR и EHRR, как и других регистров контроллера ЭЛТ, необходимо записать в символах. Вычислим промежуток времени, в течение которого отображается один символ. Для этого следует разделить 1 на частоту вывода точек и умножить полученное число на 8 (горизонтальный размер символа в пикселах). Если частота вывода точек составляет 25,175 Мгц, тогда на отображение одного символа затрачивается 8/25175 = 0,318 микросекунд. Отсюда вычисляем, что для горизонтального обратного хода луча достаточно времени затрачиваемого на отображение 7 (2/0,318) символов.

Выберите значение для регистра начала горизонтального обратного хода луча (SHRR) таким образом, чтобы растр был отцентрован на экране. Участки нерабочей области до и после горизонтального обратного хода луча должны иметь одинаковый размер.

Всего в строке развертки 100 символов. Из них 80 символов отводится для видимой области строки растра и 12 символов для горизонтального обратного хода луча. Остаток - 8 символов (100-80-12) относится к нерабочей области строки развертки. Значит горизонтальный обратный ход луча должен начинаться по прошествии времени, необходимого для отображения 80+8/2=84 символов.

Регистры контроллера ЭЛТ составляют самую многочисленную группу регистров видеоадаптеров. Для видеоадаптеров EGA и VGA группа содержит 24 регистра. В следующей таблице приведен список всех регистров контроллера ЭЛТ и их индексы, используемые для доступа к ним.

Индекс

Регистр контроллера ЭЛТ

0

Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR)

1

Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER)

2

Начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR)

3

Конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR)

4

Начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR)

5

Конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR)

6

Количество горизонтальных линий растра (Vertical Total Register - VTR)

7

Дополнительный регистр (Overflow Register - OVR)

8

Предварительная установка горизонтальной развертки (Preset Row Scan Register - PRSR)

9

Высота символов текста (Max Scan Line Register - MSLR)

0Ah

Начальная линия курсора (Cursor Start Register - CSR)

0Bh

Конечная линия курсора (Cursor End Register - CER)

0Ch

Старший байт начального адреса (Start Address Register - SAR, high byte)

0Dh

Младший байт начального адреса (Start address Register - SAR, low byte)

0Eh

Старший байт позиции курсора (Cursor Location Register - CLR, high byte)

0Fh

Младший байт позиции курсора (Cursor Location Register - CLR, low byte)

10h

Начало обратного вертикального хода луча (Vertical Retrace Start Register - VRSR)

11h

Конец обратного вертикального хода луча (Vertical Retrace End Register - VRER)

10h

Старший байт адреса светового пера (Light Pen Address Register - LPAR, high byte)

11h

Младший байт адреса светового пера (Light Pen Address Register - LPAR, low byte)

12h

Начало гашения вертикальной развертки (Vertical Display End Register - VDER)

13h

Логическая ширина экрана (Offset Register - OFR)

14h

Положение подчеркивания символа (Underline Location Register - ULR)

15h

Начало импульса гашения вертикальной развертки (Start Vertical Blank Register - SVBR)

16h

Конец импульса гашения вертикальной развертки (End Vertical Blank Register - EVBR)

17h

Управление режимом (Mode Control Register - MCR)

18h

Регистр сравнения линий (Line Compare Register - LCR)

В отличие от внешних регистров, адресация к регистрам контроллера ЭЛТ происходит через два порта. В первый порт (индексный) записывается индекс регистра, к которому осуществляется доступ, а через второй порт (порт данных) можно выполнять обмен данными (запись или чтение).

.   Большинство регистров контроллера ЭЛТ видеоадаптера EGA доступны только для записи. Прочитать значение этих регистров нельзя

У видеоадаптеров MDA и Hercules индексный порт имеет адрес 3B4h, а порт данных - адрес 3B5h. Для CGA адреса портов другие. Индексный порт имеет адрес 3D4h, а порт данных - адрес 3D5h. Адреса портов контроллера ЭЛТ для видеоадаптеров EGA и VGA зависят от режима работы видеоадаптера (монохромный или цветной). В монохромном режиме адрес порта индексного регистра равен 3B4h, а регистра данных - 3B5h. В цветном режиме адреса соответственно равны 3D4h и 3D5h:

Видеоадаптер

Адрес порта индексного регистра

Адрес порта регистра данных

CGA

3D4h

3D5h

EGA, VGA, SVGA

(монохромный режим)

3B4h

3B5h

EGA, VGA, SVGA

(цветной режим)

3D4h

3D5h

MDA, Hercules

3B4h

3B5h

Так как в монохромных и цветных режимах регистры адресуются через различные порты ввода/вывода, то к компьютеру можно одновременно подключить два видеоадаптера.

Адрес порта индексного регистра записан в области переменных BIOS, по адресу 0000:0463h. Приведем фрагмент программы, определяющей адрес индексного порта контроллера ЭЛТ:


; Устанавливаем регистр ES на нулевой сегмент памяти
xor	ax,ax
mov	es,ax

; Записываем в регистр DX адрес порта индексного 
; регистра контроллера ЭЛТ
mov	dx,es:[463]

Так как адреса портов индексного регистра и регистра данных контроллера ЭЛТ является смежными, то адрес порта регистра данных можно легко получить, прибавив единицу к адресу порта индексного регистра.

Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) (индекс 0)

Регистр HTR относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов монитора. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптера.

Кроме регистров, контроллер ЭЛТ использует при генерации синхросигналов два внутренних счетчика. Счетчик числа горизонтальных знакомест экрана увеличивается при выводе очередного символа на экран (регенерация экрана) и сбрасывается, когда его значение становится равным регистру общей длины линии горизонтальной развертки. Счетчик числа горизонтальных линий развертки увеличивается после окончания обратного горизонтального хода луча и сбрасывается, когда достигает величины, хранящейся в регистре числа горизонтальных линий растра.

Регистр HTR определяет число знакомест в одной строке развертки, включая обратный ход луча и нерабочую область развертки (рамку экрана). Для видеоадаптера EGA число знакомест по горизонтали на два, а для адаптеров VGA и SVGA на пять больше, чем значение, хранящееся в регистре.

При установке режима работы видеоадаптера, BIOS загружает в регистр HTR следующие значения:

Режим

0,1,4,5,D

2,3,6,E

7,

F

10

Содержимое регистра

37h

70h

60h

5Bh

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

2Dh

5Bh

Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) (индекс 1)

Регистр задает длину отображаемого участка горизонтальной развертки. Величина, записанная в регистр должна быть единицу меньше, чем количество символов в строке экрана.

При установке режима работы видеоадаптера, BIOS загружает в регистр HDER следующие значения:

Режим

0,1,4,5,D

2,3,6,7,E,F,10

Содержимое регистра

27h

4Fh

Начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) (индекс 2)

Регистр используется видеоадаптерами EGA, VGA и SVGA для определения начала импульса гашения луча горизонтальной развертки.

При установке режима работы видеоадаптера, BIOS загружает в регистр SHBR следующие значения:

Режим

0,1,4,5,D

2,3

6,E

7,F

10

Содержимое регистра

2Dh

5Ch

59h

56h

53h

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

2Bh

53h

Конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) (индекс 3)

D4-D0 Конец импульса гашения луча горизонтальной развертки. Гашение луча горизонтальной развертки происходит, когда биты D4-D0 равны счетчику длины отображаемой части горизонтальной развертки.

D6-D5 Биты смещения используются в текстовых режимах, чтобы разрешить отображение символов до разрешения вывода. Если величина битов смещения слишком маленькая, то символы на левой стороне экрана могут быть потеряны, а если она слишком большая, то символы на левой стороне экрана могут дублироваться по несколько раз.
D6 D5
0 0 - нет смещения
0 1 - смещение на один символ
1 0 - смещение на два символа
1 1 - смещение на три символа

D7 Бит D7 равен единице для видеоадаптера VGA и нулю для EGA.

При установке режима работы видеоадаптера, BIOS загружает в регистр EHBR следующие значения:

Режим

0,1,4,5,D

2,3

6,E

7

F

10

Содержимое регистра

37h

2Fh

2Dh

3Ah

1Fh

17h

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

2Dh

37h

Начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) (индекс 4)

Для видеоадаптеров EGA, VGA и SVGA регистр задает момент начала импульса горизонтального обратного хода луча.

При установке режима работы видеоадаптера, BIOS загружает в регистр SHRR следующие значения:

Режим

0,1

4,5,D

2,3

6,E

7

F,10

Содержимое регистра

31h

30h

5Fh

5Eh

51h

50h

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

28h

51h

Конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) (индекс 5)

D4-D0 Конец импульса горизонтального обратного хода луча. Обратный горизонтальный хода луча завершается, когда значение счетчика символов в строке становится равным битам D4-D0.

D6-D5 Смещение импульса горизонтального обратного хода луча относительно отображаемого участка горизонтальной развертки. Биты используются видеоадаптером EGA.
D6 D5
0 0 - нет смещения
0 1 - смещение на один символ
1 0 - смещение на два символа
1 1 - смещение на три символа

D7 Для адаптера EGA с объемом видеопамяти меньшим 256 Кбайт, бит D7 используется для управления горизонтальной сверткой экрана (горизонтальным панорамированием), когда слои видеопамяти сцеплены. Если бит D7 равен нулю, то после обратного хода луча первый адрес видеопамяти для обновления экрана будет четным.

Для видеоадаптеров VGA и SVGA бит D7 является пятым битом регистра конца импульса гашения луча горизонтальной развертки (EHBR).

Число горизонтальных линий растра (Vertical Total Register - VTR) (индекс 6)

Регистр определяет общее число линий горизонтальной развертки в кадре вертикальной развертки, включая гашение вертикального хода луча и обратный вертикальный ход луча.

Для видеоадаптера EGA, регистр VTR содержит девять битов. Девятый бит находится в дополнительном регистре (OVR). Регистр VTR видеоадаптеров VGA и SVGA содержит десять битов. Десятый бит, также как и девятый, расположен в дополнительном регистре (OVR).

Дополнительный регистр (Overflow Register - OVR) (индекс 7)

Многие регистры контроллера ЭЛТ, видеоадаптера EGA, имеют по девять, а для адаптеров VGA и SVGA по десять битов. Дополнительный регистр содержит биты, которые не помещаются в восьмиразрядную сетку основных регистров видеоадаптера.

D0 Бит 8 регистра числа горизонтальных линий растра (VTR).

D1 Бит 8 регистра начала гашения вертикальной развертки (VDER).

D2 Бит 8 регистра начала обратного вертикального хода луча (VRSR).

D3 Бит 8 регистра начала импульса гашения вертикальной развертки (SVBR).

D4 Бит 8 регистра сравнения линий (LCR).

D5 Бит 9 регистра количества горизонтальных линий в растре (VTR).

D6 Бит 9 регистра начала гашения вертикальной развертки (VDER).

D7 Бит 9 регистра начала обратного вертикального хода луча (VRSR).

Предварительная установка горизонтальной развертки
(Preset Row Scan Register - PRSR) (индекс 8)

Регистр позволяет в текстовых режимах выполнить плавную вертикальную свертку текста на экране монитора. В графических режимах регистр должен содержать нулевое значение.

D4-D0 Биты предварительной установки строчной развертки. Эти биты определяют номер линии развертки, начиная с которой начинают отображаться символы (рис. 8.1). Как видно из рисунка самая верхняя строка текста отображается только частично. Вы можете плавно перемешать изображение на экране увеличивая или уменьшая значение этих битов.

D6-D5 Биты управления побайтовой сверткой. Используются видеоадаптерами VGA и SVGA. Биты D6 D5 являются двумя дополнительными битами регистра горизонтального панорамирования контроллера атрибутов и позволяют сдвигать изображение на экране более чем на 8 пикселов.

D7 Не используется.

Рисунок 4.1 иллюстрирует использование регистра предварительной установки горизонтальной развертки для вертикальной свертки содержимого экрана. В левой части рисунка показано начальное состояние экрана монитора, когда биты D0-D4 регистра PRSR содержит нулевые значения. Справа представлен экран монитора после увеличения значения регистра PRSR до трех. Изображение на экране сдвигается на три пиксела вверх, в результате чего часть верхней строки пропадает.

Рисунок 4.1 Плавная свертка экрана

После установки режима работы видеоадаптера регистр PRSR содержит нулевое значение.

Высота символов текста
(Max Scan Line Register - MSLR) (индекс 9)

Регистр MSLR определяет высоту символов в пикселах. Значение регистра на единицу меньше, чем высота символов отображаемых на экране. Регистр MSLR используется только в текстовых режимах работы видеоадаптеров.

D4-D0 Биты задают высоту символа в пикселах (рис. 8.2 и 8.3).

D5 Бит 9 регистра начала импульса гашения вертикальной развертки (SVBR - индекс 15h). Используется только для видеоадаптеров VGA и SVGA.

D6 Бит 9 регистра сравнения линий (LCR индекс 18h). Используется только для видеоадаптеров VGA и SVGA.

D7 Бит управления двойным сканированием. Поддерживается только адаптерами VGA и SVGA. Если бит D7 равен единице, то в режимах, имеющих разрешение по вертикали 200 пикселов используется двойное сканирование. Это увеличивает разрешающую способность по вертикали до 400 пикселов.

Рисунок 4.2 демонстрирует использование регистра высоты символов текста. На левой половине рисунка символы шрифта имеют размер 8х8 пикселов, а регистр высоты символов содержит число семь. На правой половине рисунка, символы шрифта имеют размер 8х14, а значение регистра высоты символов текста равно тринадцати.

Рисунок 4.2 Высота символов текста 8 пикселов

Начальная линия курсора
(Cursor Start Register - CSR) (индекс 0Ah)

Регистр CSR является доступным как для чтения, так и для записи. Регистр определяет линию сканирования символа, в которой начинается курсор. Вместе с регистром конечной линии курсора (CER) регистр CSR определяет размер и форму курсора.

D4-D0 Начальная линия курсора. (Рис. 4.3).

D5 Бит гашения курсора. Реализован только для видеоадаптеров VGA и SVGA. Если бит D5 содержит единицу, тогда текстовый курсор гаснет.

D7-D6 Не используются.

При установке режима работы видеоадаптера, BIOS загружает в регистр CSR следующие значения:

Режим

0,1,2,3

4,5,6,D,E,F,10

7

Содержимое регистра

06

00

0Bh

Конечная линия курсора
(Cursor End Register - CER) (индекс 0Bh)

Этот регистр, также как и регистр CSR, является доступным для чтения и для записи. Регистр задает линию сканирования символа, в которой кончается курсор.

D4-D0 Соответствует номеру последней линии курсора для видеоадаптеров VGA и SVGA (рис. 4.3). Для видеоадаптера EGA - номеру следующей линии.

D6-D5 Отклонение курсора. Задает смещение курсора относительно позиции, определенной регистром CLR.

00 - нет отклонения
01 - отклонение вправо на один символ
10 - отклонение вправо на два символа
11 - отклонение вправо на три символа

D7 Не используется.

При установке режима работы видеоадаптера BIOS загружает в регистр конечной линии курсора следующие значения:

Режим

0,1,2,3

4,5,6,D,E,F,10

7

Содержимое регистра

07

00

0Ch

Изменяя значение регистров начальной и конечной линии курсора, можно менять его положение и размер (рис. 4.3). На левой части рисунка, приведенного ниже, регистр начальной линии курсора равен 0Ah, регистр конечной линии курсора равен 0Bh. На правой части рисунка значение регистров изменено. Регистр начальной линии равен 4, а регистр конечной линии - 5.

Рисунок 4.3 Изменение положения курсора

Следующая программа позволяет прочитать значение регистров начальной и конечной линии курсора:

Листинг 4.4. Файл GETCURS.C


#include <stdio.h>
#include <conio.h>
#include "sysp.h"			// см. листинг 3.2
#include "sysgraph.h"	// см. листинг 3.3

// Описания функций
void	main(void);
void	WriteReg(unsigned reg, unsigned char data);
unsigned char	ReadReg(unsigned reg);

// Главная функция
void main(void) {

	char           top = 0, bottom = 0;
	unsigned       crt_address;
	BIOS_VAR _far  *bios_var_ptr;

	// Получаем указатель на область переменных BIOS
	bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);

	// Определяем адрес индексного регистра контроллера ЭЛТ
	crt_address = bios_var_ptr->wAddrCRT;

	// Считываем значения регистров начальной и конечной линии 
	// курсора

	// Выбираем регистр начальной линии курсора
	WriteReg(crt_address++, 0x0A);

	// Считываем значение регистра
	top = (unsigned char) ReadReg(crt_address--);

	// Выбираем регистр конечной линии курсора
	WriteReg(crt_address++, 0x0B);

	// Считываем значение регистра
	bottom = (unsigned char) ReadReg(crt_address);

	// Отображаем на экране значение регистров
	printf("\nРегистр начальной линии курсора содержит: %d\n"
			 "\nРегистр конечной линии курсора содержит: %d\n",
			top, bottom);

	getch();
}

Для доступа к регистрам видеоадаптера мы пользуемся функциями WriteReg и ReadReg, определенными в файле DESIGN.C (листинг 4.5).

Листинг 4.5. Файл DESIGN.C


//=========================================================
// WriteReg(unsigned reg, unsigned char data)
// Функция выводит данные в порт
//
// Параметры:
//		reg - номер порта
//		data - данные, записываемые в порт reg
//=========================================================
void WriteReg(unsigned reg, unsigned char data) {
	_asm {
		mov  dx,reg
		mov  al,data
		out  dx,al
	}
}

//=========================================================
// unsigned char ReadReg(unsigned reg)
// Функция читает данные из определенного порта
//
// Параметры:
//		reg - номер порта
//
//	Возвращаемое значение:
//		данные, считанные из порта reg
//=========================================================
unsigned char ReadReg(unsigned reg) {

	unsigned char  data;

	_asm {
		mov  dx,reg
		in   al,dx
		mov  data,al
	}
	return(data);
}

Регистры начального адреса

Это группа из двух регистров: регистр старшего байта начального адреса (Start Address Register - SAR, high byte) (индекс 0Ch) и регистр младшего байта начального адреса (Start Address Register - SAR, low byte) (индекс 0Dh).

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

Если вы желаете использовать регистры для переключения страниц видеопамяти, то в регистры SAR надо записать смещение страницы видеопамяти (относительно начала видеопамяти), которую необходимо отобразить на экране.

На рисунке 4.4 показано, как происходит свертка экрана при изменении регистров начального адреса. В верхней части рисунка регистры начального адреса содержат ноль. Видеопамять отображается на экране с начала. В нижней части значение регистров начального адреса увеличено до 77h. В этом случае видеопамять отображается на экране начиная с данных, имеющих смещение 77h от начала видеопамяти. В нижней части экрана появляется изображение, ранее не помещающееся на экране.

Рисунок 4.4 Свертка изображения на экране

Регистры начального адреса доступны для чтения и для записи. При выборе режима работы видеоадаптера регистры обнуляются.

Регистры, определяющие положение курсора

Два регистра - регистр старшего байта позиции курсора (Cursor Location Register - CLR_h, high byte) (индекс 0Eh) и регистр младшего байта позиции курсора (Cursor Location Register - CLR_l, low byte) (индекс 0Fh) определяют положение курсора на экране (рис. 4.5). Регистры доступны как для записи, так и для чтения.

Рисунок 4.5 Отображение курсора на экране

Программа CURSLOC, приведенная в листинге 4.6 переводит видеоадаптер в текстовый режим, устанавливает курсор в позицию 5 строки 10. Затем программа считывает значения регистров позиции курсора (на момент запуска программы) и отображает их на экране монитора. Вы должны получить значение 0325h (80 * 10 + 5 = 805 = 0325h).

Листинг 4.6. Файл CURSLOC.C


// Чтение регистра положения курсора

#include <stdio.h>
#include "sysp.h"
#include "sysgraph.h"

// Описания функций
void	main(void);

// Функции WriteReg и ReadReg определены в файле 
// DESIGN.C. Смотри листинг 4.5
void	WriteReg(unsigned reg, unsigned char data);
unsigned char	ReadReg(unsigned reg);

// Главная функция
void main(void) {

	int				crt_port;
	unsigned char	h_pos, l_pos;
	BIOS_VAR _far	*bios_var_ptr;

	_asm {
		// Устанавливаем режим 3
		mov	ah,0
		mov	al,3
		int	10h

		//	Выбираем страницу видеоапамяти 0
		mov	ah,5
		mov	al,0
		int	10h

		// Устанавливаем курсор в положение (20,10)
		mov	ah,2
		mov	dh,10	//
		mov	dl,5	// строка 10, позиция 5:
						// CLR = 80 * 10 + 5 = 805 = 325h
		xor	bh,bh
		int	10h
	}

// Получаем указатель на область переменных видеофункций BIOS
	bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);

// Определяем адрес порта индексного регистра контроллера ЭЛТ
	crt_port = bios_var_ptr -> wAddrCRT;

// Выбираем старший байт регистра положения курсора
	WriteReg(crt_port, 0x0E);

// Читаем значение старшего байта регистра
	h_pos = ReadReg(crt_port + 1);

// Выбираем младший байт регистра положения курсора
	WriteReg(crt_port, 0x0F);

// Считываем значение младшего байта регистра
	l_pos = ReadReg(crt_port + 1);

// Отображаем полученные значения
	printf("\nТекущий адрес курсора %2.2X%2.2Xh\n",
		(unsigned char) h_pos, (unsigned char) l_pos );

	return;
}

Начало обратного вертикального хода луча (Vertical Retrace Start Register - VRSR) (индекс 10h)

Регистр определяет начало обратного вертикального хода луча. У видеоадаптера EGA регистр имеет 9, а для видеоадаптеров VGA и SVGA - 10 разрядов. Дополнительные биты регистра VRSR расположены в регистре OVR. Регистр VRSR доступен только для записи.

Конец обратного вертикального хода луча (Vertical Retrace End Register - VRER) (индекс 11h)

Регистр устанавливает конец обратного вертикального хода луча, а также выполняет некоторые другие функции. Данный регистр доступен только для записи.

Биты

Описание

D3-D0

Конец обратного вертикального хода луча

D4

Сброс вертикального прерывания

D5

Разрешения вертикального прерывания

D6

Изменение скорости регенерации экрана (видеоадаптеры VGA и SVGA)

D7

Защита от записи (видеоадаптеры VGA и SVGA)

D7 Если бит D7 равен единице, то регистры контроллера ЭЛТ, имеющие индексы от 0 до 7, будут защищены от записи. Защита от записи позволяет решить некоторые проблемы совместимости между адаптером VGA и видеоадаптерами, построенными на основе микросхемы 6845 (например CGA).

D6 Если бит D6 равен единице, то во время обратного горизонтального хода луча будет генерироваться пять циклов регенерации видеопамяти вместо обычных трех.

D5 Если бит равен нулю, то при каждом обратном вертикальном ходе луча на линии IRQ2 будет возникать прерывание. Сигнал прерывания сбрасывается при записи нуля в бит D4 данного регистра.

D4 Запись нуля в данный бит вызывает сброс прерывания на линии IRQ2 и переустановку флага незаконченного вертикального прерывания.

D3-D0 Сигнал обратного вертикального хода луча завершается, когда значение четырех младших бита счетчика горизонтальных линий совпадает с битами D3-D0

Регистр адреса светового пера (Light Pen Address Register - LPAR)

Это 16-битовый регистр видеоадаптеров CGA и EGA, доступный только для чтения. Регистр LPAR позволяет определить положение светового пера на экране монитора. Регистр, содержащий старший байт адреса светового пера, имеет индекс 10h, а регистр, содержащий младший байт, индекс 11h.

Регистр LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.

Завершение отображения вертикальной развертки (Vertical Display End Register - VDER) (индекс 12h)

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

У видеоадаптера EGA регистр VDER имеет 9, а у адаптеров VGA и SVGA - 10 разрядов. Девятый и десятый биты регистра доступны через дополнительный регистр (OVR).

Логическая ширина экрана (Offset Register - OFR) (индекс 13h)

Регистр позволяет отобразить на экране больше символов в строке, чем в стандартных текстовых режимах. Например, вы можете воспользоваться регистром OFR при переводе видеоадаптера в режим отображения 132 символов в строке.

В текстовых режимах регистр содержит смещение между соседними строками экрана, заданное в 16-битных словах.

В графических режимах регистр OFR задает логическую длину (в 16-битных словах или 32-битных двойных словах) горизонтальной линии развертки. Если линия Num развертки начинается по адресу Adr, то следующая линия развертки Num+1 начинается по адресу Adr+Offset, где Offset является значением регистра OFR.

Использование регистра OFR иллюстрируется рисунком 4.6. На верхней части рисунка видеоадаптер находится в стандартном текстовом режиме с разрешением 80 символов в строке. При этом значение регистра логической ширины экрана равно 40. На нижней части рисунка представлен результат увеличения содержимого регистра до 41. Логическая ширина экрана в этом случае увеличивается до 82 символов в строке. Последние два символа каждой строки не помещаются на экране. Для их отображения надо выполнить горизонтальную свертку экрана.

Рисунок 4.6 Логическая ширина экрана

Положение подчеркивания символа (Underline Location Register - ULR) (индекс 14h)

Регистр ULR используется только в текстовых режимах. Он определяет положение подчеркивания символа. Подчеркивание представляет собой одну из линий в матрице символа. Подчеркивание отображается, если установлен атрибут подчеркивания. Подчеркивание можно запретить, записав в регистр ULR величину большую, чем высота символов.

D4-D0 Определяют положение подчеркивания символа.

D5 Для видеоадаптеров VGA и SVGA установка этого бита означает, что для каждого знакоместа счетчик адреса регенерации будет увеличиваться на 4 вместо 1.

D6 Установка для видеоадаптеров VGA и SVGA этого бита выбирает адресацию видеопамяти по двойным словам.

D7 Не используется.

Программа, приведенная ниже, использует регистры контроллера ЭЛТ для перевода видеоадаптеров EGA и VGA в нестандартный текстовый режим, имеющий разрешение по вертикали 43 строки. Данная программа переводит видеоадаптер в текстовый режим с разрешением по вертикали 43 символа и затем отображает на экране монитора 43 строки текста.

Листинг 4.7. Файл MORESTR.ASM


#include <conio.h>

// Описания функций
void	main(void);

// Функция Set43Line опреелена в файле SET43.ASM 
// (листинг 4.8)
void	__pascal _far Set43Line(void);

// Главная функция
void main(void) {

	int  i;

	// Увеличиваем количество отображаемых строк текста
	Set43Line();

	// Отображаем на экране монитора несколько текстовых строк
	for(i = 0; i < 50; i++)
		 printf("Text line number %d\n", i);

	getch();
	return;
}

Основная функция программы MORESTR - функция Set43Line определена в файле SET43.ASM. Исходный текст файла помещен в листинге 4.8.

Листинг 4.8. Файл SET43.ASM


TITLE	SET43.ASM
NAME	SET43
PAGE	55,132

P286
IDEAL
NOWARN BRK

SEGMENT LINE_TEXT WORD PUBLIC 'CODE'
ASSUME	cs:LINE_TEXT

;============================================================
; void Set43Line(void)
; Переводит адаптеры EGA и VGA в режим отображения 43
; строк текста.
;============================================================

	CHAR_SIZE EQU 8

	PUBLIC	SET43LINE
	PROC	SET43LINE FAR

	enter	0, 0

	; Устанавливаем регистр es на начало оперативной памяти
	xor  ax,ax
	mov  es,ax

	; Получаем адрес порта индексного регистра контроллера ЭЛТ
	; (3B4h/3D4h), в монохромных режимах для адресации к 
	; индексному регистру используется порт с адресом 3B4h, 
	; а в цветных - порт 3D4h
	mov  dx,es:[463h]

	; Выбираем для обмена регистр максимальной линии 
	; сканирования этот регистр задает высоту символов на 
	; экране дисплея
	mov  al,9
	out  dx,al

	; Вычисляем адрес порта регистра данных контроллера ЭЛТ,
	; в монохромных режимах для адресации к регистру данных
	; используется порт с адресом 3B5h, в цветных - порт 3D5h
	inc  dx

	; Биты D4-D0, регистра максимальной линии сканирования
	; содержат число, меньшее на единицу, чем высота символов 
	; в пикселах
	mov  al,CHAR_SIZE-1
	out  dx,al

	; Вычисляем адрес порта индексного регистра 
	; контроллера ЭЛТ
	dec  dx

	; Выбираем для обмена регистр положения подчеркивания
	mov  al,14h
	out  dx,al

	; Вычисляем адрес порта регистра данных контроллера ЭЛТ
	inc  dx

	; Определяем положение подчеркивания символов
	mov  al,CHAR_SIZE
	out  dx,al

	; Вычисляем адрес порта индексного регистра 
	; контроллера ЭЛТ
	dec  dx

	; Выбираем для обмена регистр завершения отображения
	; вертикальной развертки

	; Регистр завершения отображения вертикальной развертки
	; содержит восемь младших бит, определяющих число
	; отображаемых горизонтальных линий растра минус один
	mov  al,12h
	out  dx,al

	; Вычисляем адрес порта регистра данных контроллера ЭЛТ
	inc  dx

	; Для отображения 43 текстовых символов, при высоте
	; символов 8 пикселов, необходимо иметь 43 * 8 = 344
	; горизонтальных линий растра

	; Помещаем в регистр завершения отображения вертикальной
	; развертки младшие 8 бит числа 344

	mov  al,(43 * CHAR_SIZE - 1 - 256)
	out  dx,al

	; Устанавливаем новые значения переменных BIOS
	; Количество символов в строке равно восьмидесяти
	mov  WORD PTR es:[44Ah],80

	; Количество строк текста минус один
	mov  BYTE PTR es:[484h],(350/CHAR_SIZE)-1

	; Высота символов в пикселах
	mov  WORD PTR es:[485h],CHAR_SIZE

	; Загружаем нулевую таблицу знакогенератора набором
	; символов (размер 8х8) из ПЗУ BIOS
	mov  ax,1112h
	xor  bl,bl
	int  10h

	leave
	ret

	ENDP	SET43LINE

ENDS	LINE_TEXT

END

Начало импульса гашения вертикальной развертки (Start Vertical Blank Register - SVBR) (индекс 15h)

Регистр определяет момент гашения луча в процессе вертикальной развертки. У видеоадаптера EGA регистр имеет 9, а у видеоадаптера VGA - 10 разрядов. Девятый бит регистра SVBR расположен в дополнительном регистре (OVR). Десятый бит расположен в регистре высоты символов текста (MSLR).

Конец импульса гашения вертикальной развертки (End Vertical Blank Register - EVBR) (индекс 16h)

Сигнал гашения вертикальной развертки завершается, когда счетчик горизонтальных линий соответствует значению регистра EVBR. Для видеоадаптера EGA регистр имеет 5 разрядов, а для VGA и SVGA 8 разрядов.

Управление режимом (Mode Control Register - MCR) (индекс 17h)

Регистр содержит набор битов, управляющих контроллером ЭЛТ.

D7 Бит D7 запрещает горизонтальный и вертикальный обратный ход луча.

D6 Если бит D6 равен единице, то установлен байтовый режим, а если он равен нулю - двухбайтовый. Двухбайтовый режим поддерживает разделение данных между двумя цветовыми слоями. Видеоадаптеры VGA и SVGA дополнительно поддерживают четырехбайтовый режим (см. регистр ULR).

Биты D6 D5

00

01

MA0

MA13

MA15

MA1

MA0

MA0

MA2

MA1

MA1

MA3

MA2

MA2

MA4

MA3

MA3

MA5

MA4

MA4

MA6

MA5

MA5

MA7

MA6

MA6

MA8

MA7

MA7

MA9

MA8

MA8

MA10

MA9

MA9

MA11

MA10

MA10

MA12

MA11

MA11

MA13

MA12

MA12

MA14

MA13

MA13

MA15

MA14

MA14

Бит D5 равен нулю только для видеоадаптеров EGA с объемом видеопамяти 64 Кбайт. В этом случае происходит сцепление слоев в графических режимах с высоким разрешением.

D4 Если бит D4 равен единице, то все выходные линии контроллера ЭЛТ переводятся в третье состояние. Этот бит используется при тестировании видеоадаптера.

D3 Если бит D3 равен нулю, то счетчик адреса регенерации изображения увеличивается на единицу на каждое знакоместо экрана, а если бит равен единице, то на каждые два знакоместа.

D2 Бит D2 может использоваться для увеличения в два раза вертикальной разрешающей способности. Если бит равен нулю, то счетчик числа линий экрана увеличивается после каждого обратного горизонтального хода луча, а если бит равен единице, то после двух обратных горизонтальных ходов луча.

D1 Используется для эмуляции графических режимов видеоадаптера Hercules. Запись нуля в этот бит приводит к замещению бита D14 адресного регистра битом D1 из регистра счетчика горизонтальных линий.

D0 Используется для эмуляции графических режимов CGA. Запись нуля в этот бит приводит к выделению в видеопамяти двух областей по 8 Кбайт каждая. Одна область соответствует четным, а другая нечетным строкам экрана. Такое отображение видеопамяти достигается в результате замещения бита D13 адресного регистра битом D0 из регистра счетчика горизонтальных строк.

Регистр сравнения линий (Line Compare Register - LCR) (индекс 18h)

Позволяет разделить изображение на две независимые части. При этом одну из них можно свертывать. Содержимое другой части экрана остается на месте.

Регистр LCR используют совместно с регистром начального адреса. Когда счетчик горизонтальных линий сканирования достигает значения, записанного в регистре LCR, происходит сброс счетчика адреса регенерируемой видеопамяти в ноль. В результате экран разбивается на две части. В верхней части экрана отображаются данные, на которые указывает регистр начального адреса, а в нижней - данные, находящиеся в начале видеопамяти. Процесс разделения экрана иллюстрируется рисунком 4.7.

Рисунок 4.7 Процесс разделения экрана

Изображение в верхней части экрана можно перемещать, изменяя содержимое регистра начального адреса.

У видеоадаптера EGA регистр сравнения линий имеет 9 разрядов. Девятый бит регистра доступен через дополнительный регистр (OVR) контроллера ЭЛТ. Регистр сравнения линий видеоадаптера VGA имеет 10 разрядов. Десятый бит регистра LCR расположен в регистре MSLR.

При изменении режима работы видеоадаптера, BIOS записывает в регистр сравнения линий значение 0FFh.

Программа, представленная ниже, выводит на экран монитора 25 строк текста, а затем, после нажатия любой клавиши, разделяет изображение на две части.

Листинг 4.9. Файл SCRSPLIT.C


#include <dos.h>
#include <stdio.h>
#include <conio.h>

void	__pascal __far Split(unsigned);
void	main(void);

// Главная функция
void main(void) {

	int   i;

	for(i = 0; i < 25; i++)
			 printf("Строка номер %d.\n",i);

	getch();

// Разделяем экран по линии 200
	Split(200);

// Ожидаем нажатие на клавиши клавиатуры
	getch();

// После завершения программы значения регистров не 
// восстанавливеются!
}

Для разделения изображения на экране монитора предназначена функция Split. Исходный текст этой функции представлен в листинге 4.10.

Листинг 4.10. Файл SPLIT.ASM


TITLE	SPLIT.ASM
NAME	SPLIT
PAGE	55,132

P286
IDEAL
NOWARN BRK

SEGMENT SPLIT_TEXT WORD PUBLIC 'CODE'
ASSUME	cs:SPLIT_TEXT

;===========================================================
; void Split(unsigned split_line)
; Функция разделяет экран на две части. Функция работает
; только на видеоадаптерах EGA и VGA.
; Параметр split_line определяет линию горизонтальной 
; развертки, в которой происходит разделение экрана монитора
;===========================================================

split_line	EQU	[bp+6]

PUBLIC	SPLIT
PROC	SPLIT FAR

	enter	0, 0

	; Устанавливаем регистр ES на начало оперативной памяти
	xor   ax,ax
	mov   es,ax

	; Получаем адрес порта индексного регистра контроллера ЭЛТ
	; (3B4h/3D4h), в монохромных режимах для адресации к 
	; индексному регистру используется порт с адресом 3B4h, а
	; в цветных - порт 3D4h
	mov   dx,es:[463h]

	; Вычисляем адрес порта регистра состояния 1, в 
	; монохромных режимах для адресации к регистру состояния 1
	; используется порт с адресом 3BAh, в цветных - порт 3DAh
	add   dx,6

	; Ожидаем начало обратного вертикального хода луча
	in    al,dx
	nop

	; Если бит D3 равен единице, то происходит обратный
	; вертикальный ход луча
	test  al,8
	jz    wait_on

wait_off:

	in    al,dx
	nop
	test  al,8
	jnz    wait_off

wait_on:

	in    al,dx
	nop
	test  al,8
	jz    wait_on


	; Вычисляем адрес порта индексного регистра 
	; контроллера ЭЛТ (3B4h/3D4h)
	sub   dx,6

	; Выбираем для обмена регистр сравнения линий
	mov   al,18h
	out   dx,al

	; Вычисляем адрес порта регистра данных контроллера ЭЛТ,
	; в монохромных режимах для адресации к регистру данных
	; используется порт с адресом 3B5h, а в цветных порт 3D5h
	inc   dx

	; Определяем линию горизонтальной развертки, в которой
	; происходит разделение экрана дисплея
	mov   ax,split_line

	; У видеоадаптера EGA регистр сравнения линий состоит из 9
	; бит, доступ к девятому биту происходит через
	; дополнительный регистр контроллера ЭЛТ; видеоадаптер 
	; VGA имеет еще и десятый бит, расположенный в регистре
	; высоты символов текста

	; Записываем младшие 8 битов в регистр сравнения линий
	out   dx,al

	; Вычисляем адрес порта индексного регистра 
	; контроллера ЭЛТ
	dec   dx

	; Вызываем функцию чтения конфигурации видеосистемы
	mov   ax,1A00h
	int   10h

	; Если после вызова функции регистр AL не равен 1Ah, то
	; используемый видеодаптер не VGA
	cmp   al,1Ah
	je    vga
	jmp   ega

vga:

	; Считываем в AL состояние дополнительнго регистра
	mov   al,7
	out   dx,al
	inc   dx
	in    al,dx

	; Модифицируем бит D4 дополнительного ргистра
	mov   bx,split_line
	mov   cl,4
	shl   bh,cl
	and   bh,00010000b

	and   al,11101111b
	or    al,bh
	out   dx,al

	; Сбрасываем бит D6 регистра высоты символов текста
	dec   dx
	mov   al,9
	out   dx,al
	inc   dx
	in    al,dx
	and   al,10111111b
	out   dx,al
	jmp   quit_split

ega:

	mov   bx,split_line
	mov   cl,4
	shl   bh,cl
	and   bh,00010000b

	cmp   dx,3B4h       ; монохромный режим?
	je    default_1Fh

	; Определяем наличие улучшенного цветного дисплея по 
	; положению переключателей на плате EGA
	mov   al,es:[488h]
	and   al,0Fh

	; Положение переключателей "OFF OFF ON ON" ?
	cmp   al,3
	je    default_1Fh

	; Положение переключателей "OFF ON ON OFF" ?
	cmp   al,9
	je    default_1Fh

	; Для видиосистем с монохромным или цветным дисплеями, 
	; дополнительный регистр по умолчанию содержит 11h
	or    bh,1
	jmp   set_overflow

	; Для видиосистем с улучненным цветным дисплеем или в 
	; монохромных текстовых режимах дополнительный регистр по 
	; умолчанию содержит 1Fh

default_1Fh:

	or    bh,0Fh

	; Устанавливаем дополнительный регистр

set_overflow:

	mov   al,07h
	out   dx,al
	inc   dx
	mov   al,bh
	out   dx,al

quit_split:

	leave
	ret 2

ENDP	SPLIT

ENDS	SPLIT_TEXT

END
[Назад] [Содеожание] [Дальше]