Программирование видеоадаптеров.© Александр Фролов, Григорий ФроловТом 21, М.: Диалог-МИФИ, 1993. Регистры контроллера ЭЛТРегистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране и форму курсора. Для видеоадаптеров CGA и EGA регистры контроллера ЭЛТ также управляют световым пером. Большинство из регистров ЭЛТ не представляют интереса. Более того, их неправильное использование может послужить причиной физического разрушения монитора. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера. Назначение и формат ряда регистров контроллера ЭЛТ различаются для видеоадаптеров EGA, VGA, SVGA и для видеоадаптеров MDA, Hercules, CGA. При программировании регистров контроллера ЭЛТ используется понятие одного знакоместа (characters) и времени необходимого для отображения одного символа (character clock). При вычислении значений регистров следует учесть, что ширина одного символа составляет 8 пикселов. Растр состоит из совокупности строк развертки, следующих одна за другой. Электронный луч включается в начале каждой строки и выключается в конце. Включение и выключение электронного луча выполняется сигналом разрешения отображения (Display Enable), вырабатываемым контроллером ЭЛТ. Когда электронный луч включен (разрешено отображение) видеоадаптер читает данные из видеопамяти и соответствующим образом модулирует интенсивность и цвет электронного луча. После того как луч прочертит весь экран монитора справа налево, он перемещается в начало следующей строки. Контроллер ЭЛТ снова включает электронный луч, в ответ на сигнал разрешения отображения и выводит на экран следующую строку видеоинформации. Промежуток времени между окончанием отображения видеоинформации на одной строке и началом отображения следующей строки называется горизонтальным неотображаемым интервалом. Промежуток времени отводимый для обратного хода луча меньше горизонтального неотображаемого интервала. Поэтому на правой и левой границе экрана образуются неотображаемые области. Контроллер ЭЛТ позволяет оставить электронный луч включенным во время перемещения по не отражаемой области. При этом вокруг изображения образуется цветная рамка. Размер и цвет рамки вы можете задавать сами. После того как электронный луч прочертит все горизонтальные линии растра, контроллер ЭЛТ отключает сигнал разрешения отображения (электронный луч гаснет) и вырабатывает сигнал вертикального обратного хода луча. Электронный луч перемещается с нижней части экрана в верхний левый угол. Продолжительность вертикального обратного хода луча меньше, чем период вертикального неотображаемого интервала. В результате в нижней и верхней части экрана возникают неотображаемые области. Одной из основополагающих величин, определяющих разрешающую способность режимов видеоадаптера, является частота вывода пикселов на экран монитора. Эта частота определяется генератором синхросигналов видеоадаптера. Чем выше частота вывода, тем больше пикселов может уместиться на экране при известной частоте кадров и частоте строчной развертки. Генераторы синхросигналов видеоадаптеров MDA, CGA и Hercules работают только на одной частоте. Для видеоадаптеров EGA, VGA и SVGA доступно несколько различных частот. Старые модели мониторов могут работать только с фиксированными значениями частоты горизонтальной и вертикальной развертки. Практически все современные мониторы могут работать в некотором диапазоне частот. Поэтому они называются мультичастотными.
Чтобы вычислить, сколько пикселов помещается на каждой строке развертки разделите частоту вывода точек на частоту горизонтальной развертки. Затем разделите полученное значение на 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 регистра. В следующей таблице приведен список всех регистров контроллера ЭЛТ и их индексы, используемые для доступа к ним.
В отличие от внешних регистров, адресация к регистрам контроллера ЭЛТ происходит через два порта. В первый порт (индексный) записывается индекс регистра, к которому осуществляется доступ, а через второй порт (порт данных) можно выполнять обмен данными (запись или чтение). . Большинство регистров контроллера ЭЛТ видеоадаптера EGA доступны только для записи. Прочитать значение этих регистров нельзя У видеоадаптеров MDA и Hercules индексный порт имеет адрес 3B4h, а порт данных - адрес 3B5h. Для CGA адреса портов другие. Индексный порт имеет адрес 3D4h, а порт данных - адрес 3D5h. Адреса портов контроллера ЭЛТ для видеоадаптеров EGA и VGA зависят от режима работы видеоадаптера (монохромный или цветной). В монохромном режиме адрес порта индексного регистра равен 3B4h, а регистра данных - 3B5h. В цветном режиме адреса соответственно равны 3D4h и 3D5h:
Так как в монохромных и цветных режимах регистры адресуются через различные порты ввода/вывода, то к компьютеру можно одновременно подключить два видеоадаптера. Адрес порта индексного регистра записан в области переменных 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 следующие значения:
Если используется улучшенный цветной монитор, то эти значения отличаются:
Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) (индекс 1)Регистр задает длину отображаемого участка горизонтальной развертки. Величина, записанная в регистр должна быть единицу меньше, чем количество символов в строке экрана. При установке режима работы видеоадаптера, BIOS загружает в регистр HDER следующие значения:
Начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) (индекс 2)Регистр используется видеоадаптерами EGA, VGA и SVGA для определения начала импульса гашения луча горизонтальной развертки. При установке режима работы видеоадаптера, BIOS загружает в регистр SHBR следующие значения:
Если используется улучшенный цветной монитор, то эти значения отличаются:
Конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) (индекс 3)D4-D0 Конец импульса гашения луча горизонтальной развертки. Гашение луча горизонтальной развертки происходит, когда биты D4-D0 равны счетчику длины отображаемой части горизонтальной развертки. D6-D5 Биты смещения используются в текстовых режимах, чтобы разрешить отображение символов до разрешения вывода. Если величина битов смещения слишком маленькая, то символы на левой стороне экрана могут быть потеряны, а если она слишком большая, то символы на левой стороне экрана могут дублироваться по несколько раз. D7 Бит D7 равен единице для видеоадаптера VGA и нулю для EGA. При установке режима работы видеоадаптера, BIOS загружает в регистр EHBR следующие значения:
Если используется улучшенный цветной монитор, то эти значения отличаются:
Начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) (индекс 4)Для видеоадаптеров EGA, VGA и SVGA регистр задает момент начала импульса горизонтального обратного хода луча. При установке режима работы видеоадаптера, BIOS загружает в регистр SHRR следующие значения:
Если используется улучшенный цветной монитор, то эти значения отличаются:
Конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) (индекс 5)D4-D0 Конец импульса горизонтального обратного хода луча. Обратный горизонтальный хода луча завершается, когда значение счетчика символов в строке становится равным битам D4-D0. D6-D5 Смещение импульса горизонтального обратного хода луча относительно отображаемого участка горизонтальной развертки. Биты используются видеоадаптером EGA. 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). Предварительная
установка горизонтальной развертки
|
Режим |
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 |
||
1х |
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