Программирование видеоадаптеров CGA, EGA и VGA© Александр Фролов, Григорий ФроловТом 3, М.: Диалог-МИФИ, 1992, 287 стр. 7.3. Регистры контроллера ЭЛТРегистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране, форму курсора, а также для видеоадаптеров CGA и EGA управляют световым пером. Большинство из этих регистров не предсталяют интереса для их непосредственного программирования. Более того, их неправильное использоване может послужить причиной физического разрушения дисплея. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера. Назначение и формат ряда регистров контроллера ЭЛТ различаются для видеоадаптеров EGA, VGA и для видеоадаптеров MDA, Hercules и CGA. Кроме того, они могут различаться и для видеоадаптерв одного типа, но разных фирм-производителей. В результате могут возникнуть проблем совместимости на компьютерах, оснащенных другим видеоадаптером. Если вы все-таки решитесь их перепрограммировать, то обращайтесь к описанию вашего адаптера. Регистры контроллера ЭЛТ составляют самую многочисленную группу регистров видеоадаптеров. Для видеоадаптеров EGA и VGA группа содержит 24 регистра. В таблице 8.9 приведен список всех регистров
контроллера ЭЛТ и их индексы, используемые для
доступа к ним.
Таблица 8.9 Регистры EGA и VGA контроллера ЭЛТ. В отличие от внешних регистров, адресация к регистрам контроллера ЭЛТ происходит через два порта. В первый порт (индексный) записывается индекс регистра, к которому осуществляетя доступ, а через второй порт (порт данных) можно производить обмен данными (запись или чтение). Заметим, что у видеоадаптера EGA большинство регистров контроллера ЭЛТ доступны только для записи. У видеоадаптеров MDA и Hercules индексный порт имеет
адрес 3B4h, а порт данных - адрес 3B5h. Для CGA адреса
портов другие. Индексный порт имеет адрес 3D4h, а
порт данных - адрес 3D5h. Адреса портов контроллера
ЭЛТ для видеоадаптеров EGA и VGA зависят от режима
работы видеоадаптера (монохромный или цветной). В
монохромном режиме адрес порта индексного
регистра равен 3B4h, а регистра данных - 3B5h. В
цветном режиме адреса соответственно равны 3D4h и
3D5h:
Таблица 8.10 Адреса портов индексного регистра и регистра данных. Использование видеоадаптерами различного адресного пространства для портов контроллера ЭЛТ необходимо, чтобы создать возможность одновременного подключения к компьютеру двух видеоадаптеров. Адрес порта индексного регистра записан в области переменных видеофункций BIOS, по адресу 0000:0463. Приведем фрагмент программы, определяющей адрес индексного порта контроллера ЭЛТ: ; устанавливаем es на нулевой сегмент xor ax,ax mov es,ax ; записываем в dx адрес порта индексного регистра контроллера ЭЛТ mov dx,es:[463] Так как адреса портов индексного регистра и регистра данных контроллера ЭЛТ является смежными, то адрес порта регистра данных можно получить, прибавив единицу к адресу порта индексного регистра. Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) (индекс 0)Этот регистр относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов для дисплея. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптера. Кроме регистров, контроллер ЭЛТ использует еще два внутренних счетчика для управления синхросигналами. Счетчик числа горизонтальных знакомест экрана увеличивается при выводе очередного сивола на экран (регенерация экрана) и сбрасывается, когда его значение становится равным регистру общей длины линии горизонтальной развертки. Счетчик числа горизонтальных линий развертки увеличивается после окончания обратного горизонтального хода луча и сбрасывается, когда достигает величины, хранящейся в регистре числа горизонтальных линий растра. Регистр HTR определяет число знакомест на одной линии сканирования, включая обратный ход луча и рамку экрана. Для EGA число знакомест по горизонтали будет на два, а для VGA на пять больше, чем значение, хранящееся в регистре. При установке режима работы видеоадаптера, BIOS
загружает в регистр HTR следующие значения:
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) (индекс 1)Регистр задает длину отображаемого участка горизонтальной развертки. Величина, записанная в регистр на единицу меньше, чем число символов в строке экрана. При установке режима работы видеоадаптера, BIOS загружает в регистр HDER следующие значения:
Начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) (индекс 2)Регистр используется видеоадаптерами EGA и VGA для определения начала импульса гашения луча горизонтальной развертки. При установке режима работы видеоадаптера, BIOS
загружает в регистр SHBR следующие значения:
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) (индекс 3)
При установке режима работы видеоадаптера, BIOS
загружает в регистр EHBR следующие значения:
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) (индекс 4)Для EGA и VGA регистр задает момент начала импульса горизонтального обратного хода луча. При установке режима работы видеоадаптера, BIOS
загружает в регистр SHRR следующие значения:
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) (индекс 5)
Число горизонтальных линий растра (VTR) (индекс 6)Регистр определяет общее число линий горизонтальной развертки в кадре вертикальной развертки, включая гашение вертикального хода луча и обратный вертикальный ход луча. Для видеоадаптера EGA, регистр VTR содержит девять битов. Девятый бит находится в дополнительном регистре (OVR). Регистр VTR видеоадаптера VGA содержит десять битов. Десятый бит, также как и девятый, расположен в дополнительном регистре (OVR). Дополнительный регистр (OVR) (индекс 7)Многие регистры контроллера ЭЛТ, видеоадаптера EGA, имеют по девять, а для VGA и по десять битов. Дополнительный регистр содержит биты, которые не помещаются в восьмиразрядную сетку основных регистров.
Предварительная установка горизонтальной
развертки
|
Режим | 0,1,2,3 | 4,5,6,D,E,F,10 | 7 |
Содержимое регистра | 06 | 00 | 0Bh |
Конечная линия курсора
(Cursor End Register - CER) (индекс 0Bh)
Этот регистр, также как и регистр CSR, является доступным для чтения и для записи.
Регистр задает последнюю линию сканирования символа, в которой кончается курсор.
- D4-D0 Соответствует номеру последней линии курсора для VGA (см. рисунок 8.4). Для 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 |
Изменяя значение регистров начальной и конечной линии курсора, можно менять его положение и размер. На левой части рисунка, приведенного ниже, регистр начальной линии курсора равен 0Ah, регистр конечной линии курсора равен 0Bh. На правой части рисунка значение регистров изменено: регистр начальной линии равен 4, а регистр конечной линии - 5.
Рисунок 8.4 Изменение положения курсора.
Следующая программа позволяет прочитать значение регистров начальной и конечной линии курсора:
#include <stdio.h> #include "sysp.h" #include "sysgraph.h" 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->crt_address; // считываем значения регистров начальной и // конечной линии курсора // выбираем регистр начальной линии курсора WriteReg(crt_address++, 0x0A); // считываем значение регистра top = (unsigned char) ReadReg(crt_address--); // выбираем регистр конечной линии курсора WriteReg(crt_address++, 0x0B); // считываем значение регистра bottom = (unsigned char) ReadReg(crt_address); // отображаем на экране значение регистров printf("\nРегистр начальной линии курсора содержит %x\n" "\nРегистр конечной линии курсора содержит %x\n", top, bottom); getch(); }
Регистры начального адреса
Это группа из двух регистров: регистр старшего байта начального адреса (Start Address Register - SAR, high byte) (индекс 0Ch) и регистр младшего байта начального адреса (Start Address Register - SAR, low byte) (индекс 0Dh).
Регистры SAR содержат адрес данных видеопамяти, которые будут отображаться в верхнем левом углу экрана дисплея. Регистры начального адреса можно использовать для перемещения изображения по экрану (панорамирования) и для переключения активной страницы памяти.
Если вы хотите использовать регистры для переключения страниц видеопамяти, то в данные регистры надо записать смещение страницы, которую вы желаете отобразить на экране, относительно начала видеопамяти.
На рисунке 8.5 показано, как происходит панарамирование экрана при изменении регистров начального адреса. В верхней части рисунка регистры начального адреса содержат ноль. В этом случае видеопамять отображается на экране с начала. В нижней части значение регистров начального адреса увеличено до 77. Как видно из рисунка, в этом случае видеопамять отображается на экране начиная с данных, имеющих смещение 77 от начала видеопамяти. При этом снизу экрана возникает изображение, ранее не помещавщееся на экране.
Рисунок 8.5 Процесс панорамирования экрана.
Регистры начального адреса доступны для чтения и для записи. При установке режима работы видеоадаптера регистры обнуляются.
Регистры, определяющие положение курсора
Два регистра - регистр старшего байта позиции курсора (Cursor Location Register - CLR_h, high byte) (индекс 0Eh) и регистр младшего байта позиции курсора (Cursor Location Register - CLR_l, low byte) (индекс 0Fh) определяют положение курсора на экране (cм. рисунок 8.6). Регистры доступны как для записи, так и для чтения.
Рисунок 8.6 Отображение курсора на экране.
Программа, приведенная ниже считывает значения из регистров позиции курсора (на момент запуска программы) и отображает их на экране дисплея:
// чтение регистра положения курсора #include <stdio.h> #include <graph.h> #include "sysp.h" #include "sysgraph.h" void main(void) { int crt_port; unsigned char h_pos, l_pos; BIOS_VAR _far *bios_var_ptr; // получаем указатель на область переменных видеофункций BIOS bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410); // определяем адрес порта индексного регистра контроллера ЭЛТ crt_port = bios_var_ptr -> crt_address; // выбираем старший байт регистра положения курсора WriteReg(crt_port, 0x0E); // считываем значение старшего байта регистра положения курсора h_pos = ReadReg(crt_port + 1); // выбираем младший байт регистра положения курсора WriteReg(crt_port, 0x0F); // считываем значение младшего байта регистра положения курсора l_pos = ReadReg(crt_port + 1); printf("\nТекущий адрес курсора %X:%X\n", (unsigned char) h_pos, (unsigned char) l_pos ); }
Начало обратного вертикального хода луча (VRSR) (индекс 10h)
Регистр определяет начало обратного вертикального хода луча. Для EGA этот регистр содержит 9, а для VGA - 10 битов. Дополнительные биты расположены в регистре OVR.
Данный регистр доступен только для записи.
Конец обратного вертикального хода луча (VRER) (индекс 11h)
Данный регистр видеоадаптеров EGA и VGA доступен только для записи.
Регистр устанавливает конец обратного вертикального хода луча, а также выполняет некоторые другие функции.
D3-D0 Конец обратного вертикального хода луча. D4 Сброс вертикального прерывания. D5 Разрешения вертикального прерывания. D6 Изменение скорости регенирации экрана. (Только VGA.) D7 Защита от записи. (Только VGA.)
- D7 Этот бит позволяет решить некоторые проблеммы совместимости между VGA и видеоадаптерами, построенными на основе микросхемы 6845 (например CGA). Если бит D7 равен единице, то регистры контроллера ЭЛТ, имеющие индексы от 0 до 7, будут защищены от записи в них.
- D6 Если бит равен единице, то во время обратного горизонтального хода луча будет генерироваться пять циклов регенерации видеопамяти вместо обычных трех.?
- D5 Если бит равен нулю, то при каждом обратном вертикальном ходе луча на линии IRQ2 будет возникать прерывание. Сигнал прерывания сбрасывается записью нуля в бит D4 данного регистра.
- D4 Запись нуля в данный бит вызывает сброс вертикального прерывания и переустановку флага незаконченного вертикального прерывания.
- D3-D0 Когда значение этих битов поразрядно равны четырем младшим битам счетчика горизонтальных линий, сигнал обратного вертикального хода луча будет окончен.
Регистр адреса светового пера (LPAR)
Это 16-битовый регистр, который имеется в видеоадаптерах CGA и EGA, доступен только для чтения. Регистр LPAR дает возможность определить положение светового пера на экране. Регистр содержащий старший байт адреса светового пера имеет индекс 10h, а регистр содержащий младший байт - индекс 11h.
LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.
Завершение отображения вертикальной развертки (VDER) (индекс 12h)
Регистр определяет момент, когда заканчивается видемая часть вертикальной развертки и происходит гашение луча. Регистр содержит число, на единицу меньшее, чем количество горизонтальных линий растра.
Для видеоадаптера EGA регистр VDER содержит 9, а для VGA - 10 бит. Девятыи и десятый биты доступны через дополнительный регистр (OVR).
Логическая ширина экрана (OFR) (индекс 13h)
Регистр может быть использован для отображения большего, чем обычно, количества символов в строке. Например, для перевода видеоадаптера в режим отображения 132 симвов в строке.
В графических режимах регистр OFR задает логическую длину (в 16-битных словах или 32-битных двойных словах) горизонтальной линии развертки. Если линия num развертки начинается по адресу adr, то следующая линия развертки num+1 начинается по адресу adr+offset, где offset это значение регистра OFR.
В текстовых режимах регистр содержит смещение между соседними строками текста, заданное в 16-битных словах.
Использование регистраа OFR иллюстрируется рисунком 8.7. На верхней части рисунка видеоадаптер находится в стандартном текстовом режиме с разрешением 80 символов в строке. При этом значение регистра логической ширины экрана равно 40. На нижней части рисунка представлен результат увеличения содержимого регистра до 41. Логическая ширина экрана в этом случае увеличивается до 82 символов в строке. Последние два символа каждой строки не помещаются на экране. Для их отображения надо выполнить горизонтальную свертку экрана.
Рисунок 8.7 Логическая ширина экрана.
Положение подчеркивания символа (ULR) (индекс 14h)
Регистр ULR используется только в текстовых режимах. Он определяет положение подчеркивания символа. Подчеркивание предстовляет собой одну из линий в матрице символа. Подчеркивание отображается, если установлен атрибут подчеркивания. Отображение подчеркивания можно запретить, записав в регистр ULR величину большую, чем высота символов.
- D4-D0 Определяют положение подчеркивания символа (0-13).
- D5 Для VGA установка этого бита означает, что для каждого знакоместа счетчик адреса регенерации будет увеличиваться на 4 вместо 1.
- D6 Установка для VGA этого бита выбирает адресацию видеопамяти по двойным словам.
- D7 Не используется.
Программа, приведенная ниже, использует регистры контроллера ЭЛТ для перевода видеоадаптеров EGA и VGA в нестандартный текстовый режим, имеющий разрешение по вертикали 43 строки. Данная программа переводит видеоадаптер в текстовый режим с разрешением по вертикали 43 символа и затем отображает на экране диспля 43 строки текста.
#include <graph.h> void Set43Line(void); void main(void) { int i; // устанавливаем текстовый режим, принятый по умолчанию; // функция _setvideomode определена в графической библиотеке // трансляторов Microsoft Quick C 2.5 и C 6.0 _setvideomode(_DEFAULTMODE); // перепрограммируем видеоадаптер для отображения 43 строк Set43Line(); // выводим на экран дисплея 43 строки текста for(i = 0; i < 43; i++) printf("text line number %d\n", i); getch(); // восстанавливаем режим с 25 текстовыми строками _setvideomode(_DEFAULTMODE); } /** *.Name Set43Line * *.Title Установка текстового режима, использующего 43 строки. * *.Descr Переводит адаптеры EGA и VGA в режим отображения 43 * строк текста. * *.Proto void Set43Line(void) * *.Params Отсутствуют. * * *.Return Не используется. * *.Sample 43line.c **/ void Set43Line(void) { #define CHAR_SIZE 8 // новая высота символов _asm { ; устанавливаем регистр 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 ; процесс загрузки шрифтов более подробно описан в разделе "Загрузка ; таблиц знакогенератора" из главы "Дополнительные средства BIOS для ; управлния EGA и VGA" mov ax,1112h xor bl,bl int 10h } }
Начало импульса гашения вертикальной развертки (SVBR) (byltrc 15h)
Регистр определяет момент начала гашения луча в прцессе вертикальной развертки.
Для EGA регистр имеет 9, а для VGA - 10 битов. Девятый бит и для EGA и для VGA расположен в дополнительном регистре (OVR). Десятый бит для VGA расположен в регистре высоты символов текста (MSLR).
Конец импульса гашения вертикальной развертки (EVBR) (индекс 16h)
В момент, когда младшие 5 битов регистра для EGA или все 8 битов для VGA равны счетчику горизонтальных линий, заканчивается сигнал гашения вертикальной развертки.
Управление режимом (MCR) (индекс 17h)
Регистр содержит набор битов, управляющих контроллером ЭЛТ.
- D7 Если бит равен нулю, то горизонтальный и вертикальный обратный ход луча невозможен.
- D6 Если данный бит равен единице, то установлен байтовый режим, а если он равен нулю - двух-байтовый. Двух-байтовый режим поддерживает разделение данных между двумя цветовыми слоями. VGA дополнительно поддерживает четырех-байтовый режим (см. регистр 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 |
Таблица 8.11 Преобразование адреса.
Бит D5 равен нулю только для видеоадаптеров EGA с объемом видеопамяти 64К байт. При этом происходит сцепление слоев в графических режимах с высоким разрешением.
- D4 Если бит равен единице, то все выходные линии контроллера ЭЛТ переводятся в третье состояние. Этот бит используется только при тестировании видеоадаптера.
- D3 Если бит равен нулю, то счетчик адреса регенерации изображения увеличивается на единицу на каждое знакоместо экрана, а если бит равен единице, то на каждые два знакоместа.
- D2 Бит может использоваться для увеличения в два раза вертикальной разрешающей способности. Если бит равен нулю, то счетчик числа линий экрана увеличивается после каждого обратного горизонтального хода луча, а если бит равен единице, то после каждых двух.
- D1 Используется при эмуляции графических режимов видеоадаптера Hercules. Запись в этот бит нуля приводит к замещению бита D14 адресного регистра битом D1 из регистра счетчика горизонтальных строк.
- D0 Используется при эмуляции графических режимов CGA. Запись в этот бит нуля приводит к выделению в видеопамяти двух областей по 8 Кбайт. Одна содержит даннные для четных, а другая для нечетных строк экрана. Это достигается путем замещения бита D13 адресного регистра битом D0 из регистра счетчика горизонтальных строк.
Регистр сравнения линий (Line Compare Register - LCR) (индекс 18h)
Обеспечивает разделение экрана на две независимые части. При этом одну из них можно свертывать, содержимое другой части экрана остается на месте.
Данный регистр используют совместно с регистром начального адреса. Когда счетчик горизонтальных линий сканирования достигает значения, записанного в регистре LCR, происходит сброс счетчика адреса регенерируемой видеопамяти в ноль. В результате экран разбивается на две части, где в верхней отображаются данные, на которые указывает регистр начального адреса, а в нижней - данные, находящиеся в начале видеопамяти. На рисунке 8.8 иллюстрируется процесс разделения экрана:
Рисунок 8.8 Процесс разделения экрана.
Содержимое верхнего окна можно перемещать, изменяя содержимое регистра начального адреса.
Заметим, что у видеоадаптера EGA регистр сравнения линий состоит из 9 бит. Доступ к девятому биту возможен через дополнительный регистр (OVR) контроллера ЭЛТ. Видеоадаптер VGA имеет дополнительно еще и десятый бит, расположенный в регистре MSLR.
При изменении режима работы видеоадаптера, BIOS записывает в регистр сравнения линий значение 0FFh.
Следующая программа выводит на экран дисплея 25 строк текста, а затем, после нажатия любой клавиши, разделяет экран на две части.
// пример разделения экрана дисплея на две части при помоши // регистра сравнения линий контроллера ЭЛТ #include <dos.h> #include <stdio.h> void Split(unsigned); void main(void) { int i; // выводим на экран дисплея 25 строк текста for(i = 0; i < 25; i++) printf("Строка номер %d.",i); getch(); // разделяем экран по линии 200 Split(200); getch(); // после завершения программы // значения регистров не восстанавливаются! } /** *.Name Split * *.Title Разделение экрана. * *.Descr Функция разделяет экран на две части. Функция работает * только на EGA и VGA. * *.Proto void Split(unsigned split_line) * *.Params unsigned split_line - линия горизонтальной развертки, * в которой происходит разделение экрана дисплея. * *.Return Не используется. * *.Sample split.c **/ void Split(unsigned split_line) { _asm { ; устанавливаем регистр 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 ; вызываем функцию чтения конфигурации видеосистемы, ; данная функция подробно описана в главе ; "Дополнительные средства BIOS для управлния EGA и VGA" 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 ; если да, то переходим ; на метку 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,bl out dx,al quit_split: } }