Подробно описаны все основные функции BIOS, предназначенные для работы с видеоадаптерами. Основные функции BIOS реализуются на всех компьютерах серии IBM PC/XT/AT, PS/2. На каждую группу функций данная глава содержит примеры программ.
Использование функций BIOS предпочтительней, чем программирование регистров, это безопасней и надежнее, так как существует специальный видео-BIOS, установленный на плате адаптера. Этот BIOS гарантирует корректность работы с регистрами и исключает возможные повреждения адаптера и ЭЛТ.
Функция 00h прерывания 10h позволяет задать любой режим работы видеоадаптера:
На входе: AH = 00h; AL = номер устанавливаемого режима работы видеоадаптера, если бит D7 = 1, то при установке режима видеопамять не очищается; На выходе: Не используются.
Приведем пример выбора режима видеоадаптера:
mov ah,0 ; функция выбора режима работы видеоадаптера mov al,mode ; выбираем режим mode int 10h ;
Функция 01h позволяет изменить вертикальные размеры курсора путем задания верхней и нижней границ курсора (см. рис 9.1). Горизонтальные размеры курсора всегда одинаковы и равны ширине одного символа.
На входе: AH = 00h - изменение размеров курсора; CH = верхняя граница курсора: D3-D0 верхняя граница курсора D5-D4 00b - обычный курсор 01b - невидимый курсор 10b - мигающий курсор 11b - быстро мигающий курсор D7-D6 не используются; CL = нижняя граница курсора (0-31). На выходе: Не используются.
Курсор отображается только в текстовых режимах работы видеоадаптера.
При выборе режима работы видеоадаптера BIOS устанавливает следующие значения для верхней и нижней границ курсора:
Рисунок 9.1 Изменение положения курсора.
Функция 02h задает текущее положение курсора на экране дисплея.
Если видеопамять разделена на несколько страниц, то каждая из них имеет свой курсор, координаты которого можно устанавливать отдельно.
Координаты курсора определяют не только место на экране, где он отображается, но также и позицию, начиная с которой соответствующие функции BIOS будут выводить на экран строки или отдельные символы.
Координаты курсора определяют не только место на экране, где он отображается, но также и позицию, начиная с которой соответствующие функции BIOS будут выводить на экран строки или отдельные символы.
На входе: AH = 02h - установка позиции курсора; BH = номер страницы видеопамяти; DH = номер строки (0-24); DL = номер столбца (0-79). На выходе: Не используются.
Функция 03h позволяет узнать размер и текущие координаты курсора для любой страницы видеопамяти:
На входе: AH = 03h - опрделение размеров и координат курсора BH = номер страницы видеопамяти. На выходе: CH = верхняя граница курсора; CL = нижняя граница курсора; DH = позиция текущей строки курсора; DL = позиция текущего столбца курсора.
Функция 04h позволяет определить подключено ли световое перо или нет. Если подключено, можно определить его координаты. Функция позволяет узнать позицию светового пера и в текстовых, и в графических координатах.
Заметим, что световое перо EGA программно не полностью совместимо с CGA, в результате чего программы поддерживающие возможность использования светового пера для видеоадаптера CGA будут работать неправильно с видеоадаптером EGA. Видеоадаптер VGA не имеет светового пера.
На входе: AH = 04h. На выходе: AH = 0 - световое перо не подключено (все остальные регистры не содержат полезной информации); AH = 1 - световое перо подключено; CH = координаты вертикальной позиции курсора в пикселах (графические режимы с низким разрешением); CX = координаты вертикальной позиции курсора в пикселах (графические режимы с высоким разрешением); BX = координаты горизонтальной позиции курсора в пикселах; DH = координаты вертикальной позиции курсора в номерах строк; DL = координаты горизонтальной позиции курсора в номерах колонок.
Приведем пример использования этой функции:
mov ah,4 int 10h ; определяем положение светового пера cmp ah,0 ; переходим на метку not_pen, если jz not_pen ; перо не подключено mov light_pen_col,dl ; сохраняем координаты светового пера mov light_pen_row,dh
Функция 05h позволяет изменить активную страницу видеопамяти. Активная страница видеопамяти отображается на экране.
На входе: AH = 05h - выбор активной страницы видеопамяти; AL = номер страницы видеопамяти, которая станет активной. На выходе: Не используются.
Свернуть активное окно экрана вверх (при работе в текстовом режиме) можно при помощи функции 06h. Окно задается координатми верхнего левого и нижнего правого углов. При свертке окна снизу появляются новые пустые строки (строки, заполненые пробелами), а верхние строки исчезают. Область экрана вне окна не изменяется.
На входе: AH = 06h - свертка окна вверх; AL = число прокручиваемх линий, если оно равно нулю, то окно прокручивается целиком; BH = атрибут, используемый для строк, возникающих снизу окна; CH = номер строки верхнего левого угла окна; CL = номер колонки верхнего левого угла окна; DH = номер строки нижнего правого угла окна; DL = номер колонки нижнего правого угла окна. На выходе: Не используются.
Тот факт, что при свертке в нижней части окна возникают чистые строки, впоследствии заполняющие все окно, можно использовать для быстрой очистки экрана. Для этого достаточно задать размеры окна, равные размерам экрана и прокрутить его вверх на 25 или 0 строк. Приведем фрагмент программы на языке ассемблера, который можно использовать для очистки экрана дисплея:
push es ; сохраняем содержимое регистра es xor ax,ax ; устанавливаем регистр es на нулевой mov es,ax ; сегмент памяти mov ah,6 ; функция свертки экрана вверх mov al,0 ; очищаем все окно mov bh,7 ; устанавливаем нормальный атрибут xor cx,cx ; устанавливаем левый верхний угол окна в (0,0) ; Для определения размеров экрана испльзуется содержимое переменных ; видеофункций BIOS. Ячейка памяти, расположенная по адресу 0000:0484 ; содержит число, на единицу меньшее, чем количество строк на экране. ; По адресу 0000:044A находится переменная, определяющая число символов ; в строке. Более подробно переменные видеофункциий BIOS будут ; рассмотрены позже. mov dh,es:[484h] ; определяем число строк в данном режиме mov dl,es:[44Ah] ; определяем число символов в строке dec dl int 10h ; вызываем свертку экрана вверх pop es ; восстанавливаем регистр es
Свернуть активное окно экрана вниз (при работе в текстовом режиме) можно при помощи функции 07h. Окно задается координатами верхнего левого и нижнего правого углов. При прокрутке в верхней части окна появляются новые пустые строки (строки, заполненые пробелами), а нижние строки исчезают. Область экрана вне окна не изменяется.
На входе: AH = 07h - свертка окна вниз; AL = число прокручиваемх линий, если оно равно нулю, то окно прокручивается целиком; BH = атрибут, используемый для строк, возникающих в верхней части окна; CH = номер строки левого верхнего угла окна; CL = номер колонки левого верхнего угла окна; DH = номер строки правого нижнего угла окна; DL = номер колонки правого нижнего угла окна. На выходе: Не используются.
Эту функцию можно использовать для очистки окна аналогично функции 06h.
Данная функция позволяет прочитать символ и его атрибуты из позиции экрана, определенной текущим положением курсора. Чтение можно производить как из активной, так и из неактивных страниц памяти:
На входе: AH = 08h - чтение символа и его атрибутов; BH = номер страницы видеопамяти. На выходе: AL = ASCII-код символа; AH = байт атрибутов символа.
Следующий пирмер считывает символ и его атрибут из текущей позиции курсора на странице page:
... mov ah,8 ; читаем символ и его атрибуты mov bh,page ; выбираем страницу видеопамяти page int 10h ; считываем символ и его атрибут mov char,al ; сохраняем полученный ASCII-код символа mov attr,ah ; и его атрибут ...
Функция позволяет записать один или несколько одинаковых символов с атрибутами в текущей позиции курсора. При этом запись может происходить как в активную, так и в неактивные страницы видеопамяти. После выполнения операции записи положение курсора не изменяется. Управляющие символы, такие как возврат каретки и перевод строки, не действуют и записываются, как обычные символы. Данная функция работает как в ткстовых, так и в графических режимах.
На входе: AH = 09h - запись символа с атрибутом; AL = ASCII-код записываемого символа; BH = номер страницы видеопамяти; BL = атрибут (для текстового режма) или цвет (для графического режима); CX = число записываемых символов. На выходе: Не используются.
Если запись символа происходит на видеоадаптере EGA в графическом режиме, и бит D7 регистра BL содержит единицу, то новый символ накладывается на текущее содержимое экрана по логике булевой операции ИСКЛЮЧАЮЩЕЕ ИЛИ.
Ниже приведен пример, использующий рассмотренные функции BIOS для выбора режима работы видеоадаптера, выбора активной страницы видеопамяти, изменения формы и координат курсора и отображения символов на экране дисплея:
TITLE BIOS_FUNCTION .MODEL tiny DOSSEG .STACK 100h .DATA message DB "INT 10h", 0 video_page DB 2 .CODE .STARTUP ; выбираем режим 0 видеоадаптера xor ah,ah xor al,al int 10h ; изменяем форму курсора mov ah,1 ; начало курсора - линия 0 ; конец курсора - линия 7 mov ch,0 mov cl,7 int 10h ; выбираем страницу видеопамяти - video_page mov ah,5 mov al,video_page int 10h ; прокручиваем окно экрана mov ah,6 xor al,al ; прокручиваем все окно mov bh,0FFh ; используем атрибут 0FFh mov cl,10 ; задаем верхний левый угол окна mov ch,5 mov dl,30 ; задаем правый нижний угол окна mov dh,15 int 10h ; устнанавливаем координаты курсора mov ah,2 mov bh,video_page ; выбираем страницу video_page mov dh,12 ; строка 12 mov dl,20 ; колонка 20 int 10h ;отображаем на активной странице экрана строку message mov si,OFFSET message call WriteString .EXIT 0 ; процедура WriteString выводит на экран строку, имеющую ; смещение si в сегменте ds WriteString PROC ; определяем текущую активную страницу экрана mov ah,0Fh int 10h ; номер активной страницы в регистре bh ; получаем в dx координаты курсора mov ah,3 int 10h ; в цикле выводим на экран символы строки next_char: mov ah,9 lodsb cmp al,0 ; находим конец строки je exit_proc ; если конец строки достигнут, то оканчиваем процедуру mov bl,8 ; для отображаемых символов используем атрибут 8 mov cx,1 ; символы строки выводятся без повтора int 10h ; перемещаем курсор в следующую позицию строки mov ah,2 inc dl int 10h jmp next_char exit_proc: ret WriteString ENDP END
Функция позволяет записать символ в текущей позиции курсора на любой странице видеопамяти. Как и в предыдущей функции, можно производить запись сразу нескольких одинаковых символов. Атрибуты символа не задаются, а используются их старые значения из предыдущих операций записи. После операции записи положение курсора не изменяется. Управляющие символы, такие как возврат каретки и перевод строки, не действуют и записываются, как обычные символы.
На входе: AH = 10h - запись символа без атрибута; AL = ASCII-код записываемого символа; BH = номер страницы видеопамяти; BL = цвет (для графического режима); CX = число записываемых символов. На выходе: Не используются.
Если запись символа происходит на видеоадаптере EGA в графическом режиме, и бит D7 регистра BL содержит единицу, то новый символ накладывается на текущее содержимое экрана по логике булевой операции ИСКЛЮЧАЮЩЕЕ ИЛИ.
Данная функция позволяет выбрать одну из двух
стандартных цветовых палитр (см. таблицу 9.1).
Функция используется для обеспечения
совместимости с видеоадаптером CGA.
Номер цвета |
Палитра 0 |
Палитра 1 |
0 |
цвет фона |
цвет фона |
1 |
зеленый |
синий |
2 |
красный |
малиновый? |
3 |
коричневый |
белый |
Таблица 9.1 Стандартные цветовые палитры в режимах 4,5,6.
Функция 0Bh имеет следующий формат вызова:
На входе: AH = 0Bh - установка цветовой палитры; BH = 0, тогда BL = цвет фона и рамки (для графического режима) или цвет рамки (для текстового режима) BH = 1, тогда BL = номер палитры (0 или 1). На выходе: Не используются.
Использование функций BIOS для создания изображений, в частности для отображения отдельных пикселов, хотя и медленнее, чем прямая запись в видеопамять и программирование регистров, но более надежно с точки зрения совместимости для различных режимов и видеоадаптеров.
Функция используется в графических режимах для
записи пиксела заданного цвета в любую страницу
видеопамяти. Необходимо отметить, что у
видеоадаптера CGA в графических режимах
определена только одна страница видеопамяти.
Значения цветов, которые можно использовать в
различных режимах, перечилены в таблице 9.2:
Номер режима |
Используемые номера цветов |
4,5 |
0 - 3 |
6 |
0 и 1 |
0Dh |
0 - 15 |
0Eh |
0 - 15 |
0Fh |
0 и 1 |
10h |
0 - 15 |
Цвета, соответствующие номерам цветов в таблице можно посмотреь в главе "Режимы работы видеоадаптеров".
Таблица 9.2 Возможные значения номеров цветов для различных режимов.
Формат вызова функции 0Ch представлен ниже:
На входе: AH = 0Ch - запись пиксела; AL = номер цвета; BH = номер страницы (для CGA не используется); CX = координата X; DX = координата Y. На выходе: Не используются.
Если бит D7 регистра AL содержит единицу, то новый пиксел накладывается на текущее содержимое экрана по логике булевой операции ИСКЛЮЧАЮЩЕЕ ИЛИ.
Заметим, что начало системы координат находится в левом верхнем углу экрана, а оси координат направлены следующим образом: ось X - вправо, ось Y - вниз. Далее, если особо не оговарено, мы всегда будем использовать эту систему координат.
// Демонстрация функций - выбора цветовой палитры и вывода // пиксела. #include <dos.h> #include <stdio.h> void main(void); void main(void) { union REGS inregs, outregs; unsigned char i, j; // устанавливаем режим 4 видеоадаптера // (графический - 320х200, 4 цвета) inregs.h.ah = 0x0; inregs.h.al = 0x4; int86( 0x10, &inregs, &outregs ); // устанавливаем цвет фона inregs.h.ah = 0x0B; inregs.h.bh = 0x0; //устанавливаем цвет фона inregs.h.bl = 0x6; //номер устанавливаемого цвета фона int86( 0x10, &inregs, &outregs ); for(i = 0; i < 2; i++) { // устанавливаем цветовую палитру inregs.h.ah = 0x0B; inregs.h.bh = 0x1; // установка палитры inregs.h.bl = i; // номер палитры int86( 0x10, &inregs, &outregs ); // выводим массив точек for(j = 0; j < 64; j++) { // выводим на экран дисплея точку inregs.h.ah = 0x0C; inregs.h.al = (unsigned char)(j / 16);// номер цвета inregs.x.cx = 0x10 + j; // x-координата точки inregs.x.dx = 0x10 + j; // y-координата точки int86( 0x10, &inregs, &outregs ); } getch(); } }
Функция позволяет определить цвет любого пиксела экрана по его координатам. Функция используется только в графических режимах работы видеоадаптеров.
На входе: AH = 0Dh - определение цвета пиксела; BH = номер страницы (для CGA не используется); CX = координата X; DX = координата Y; На выходе: AL = номер цвета пиксела.
Приведем фрагмент программы, который определяет номер цвета пиксела, имеющего координаты x_pos и y_pos:
mov ah,0Dh mov cx,x_pos mov dx,y_pos int 10h ; сохраняем полученную величину mov color_number
Функция обеспечивает запись символа на экран в режиме телетайпа: символ отображается в текущей позиции курсора, после чего курсор сдвигется вправо на одну позицию. При необходимости курсор автоматически перемещается на новую строку, а когда весь экран заполняется, происходит вертикальная свертка экрана. В последнем случае верхняя строка экрана исчезает, а снизу возникает новая пустая строка и курсор помещается в ее начало.
Данная функция обрабатывает следующие управляющие символы: звуковой сигнал (BELL), возврат курсора назад на одну позицию (BACKSPACE), возврат каретки (CARRIAGE RETURN) и перевод строки (LINEFEED).
В текстовых режимах символы отображаются с атрибутами, использованными ранее. В графических режимах есть возможность задать цвет отображаемого символа.
Ниже приведен формат вызова функции:
На входе: AH = 0Eh - запись символа в режиме телетайпа; AL = ASCII-код записываемого символа; BH = номер страницы видеопамяти (только в текстовых режимах)?; BL = цвет символа (в графических режимах). На выходе: Не используются.
Приведем текст процедуры WriteStringT, которая выводит на экран строку, имеющую смещение si в сегменте ds, при помощи функции 0Eh прерывания INT 10h:
WriteStringT PROC ; определяем текущую активную страницу экрана mov ah,0Fh int 10h ; номер активной страницы в регистре bh ; в цикле выводим на экран символы строки next_char: mov ah,0Eh lodsb ; получаем следующий символ строки cmp al,0 ; находим конец строки je exit_proc ; если конец строки достигнут, то оканчиваем процедуру int 10h jmp next_char exit_proc: ret WriteStringT ENDP
Функция позволяет определить номер текущего режима работы видеоадаптера, номер активной страницы и количество символов в строке экрана. Список различных режимов приведен в таблице 3.1. Формат функции имеет следующий вид:
На входе: AH = 0Fh - определение текущего режима видеоадаптера. На выходе: AH = число символов в строке; AL = номер текущего режима; BH = номер активной страницы видеопамяти.