8. Основные средства BIOS для работы с видеоадаптерами

Подробно описаны все основные функции BIOS, предназначенные для работы с видеоадаптерами. Основные функции BIOS реализуются на всех компьютерах серии IBM PC/XT/AT, PS/2. На каждую группу функций данная глава содержит примеры программ.

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

8.1. Выбор режима работы - функция 00h

Функция 00h прерывания 10h позволяет задать любой режим работы видеоадаптера:

На входе:   AH = 00h;
            AL = номер устанавливаемого режима работы
            видеоадаптера,
            если бит D7 = 1, то  при установке режима
            видеопамять не очищается;
На выходе:  Не используются.

Приведем пример выбора режима видеоадаптера:

   mov   ah,0      ; функция выбора режима работы видеоадаптера
   mov   al,mode   ; выбираем режим mode
   int   10h      ;

8.2. Изменение формы курсора - функция 01h

Функция 01h позволяет изменить вертикальные размеры курсора путем задания верхней и нижней границ курсора (см. рис 9.1). Горизонтальные размеры курсора всегда одинаковы и равны ширине одного символа.

На входе:   AH = 00h - изменение размеров курсора;
            CH = верхняя граница курсора:
                D3-D0 верхняя граница курсора
                D5-D4
			        00b - обычный курсор
                    01b - невидимый курсор
                    10b - мигающий курсор 
                    11b - быстро мигающий курсор
            D7-D6   не используются;
            CL = нижняя  граница курсора (0-31).
На выходе:  Не используются.

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

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

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

8.3. Изменение положения курсора - функция 02h

Функция 02h задает текущее положение курсора на экране дисплея.

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

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

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

На входе:   AH = 02h - установка позиции курсора;
            BH = номер страницы видеопамяти;
            DH = номер строки (0-24);
            DL = номер столбца (0-79).
На выходе:  Не используются.

8.4. Определение положения и формы курсора - функция 03h

Функция 03h позволяет узнать размер и текущие координаты курсора для любой страницы видеопамяти:

На входе:   AH = 03h - опрделение размеров и координат
                       курсора
            BH = номер страницы видеопамяти.
На выходе:  CH = верхняя граница курсора;
            CL = нижняя граница курсора;
            DH = позиция текущей строки курсора;
            DL = позиция текущего столбца курсора.

8.5. Использование светового пера - функция 04h

Функция 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

8.6. Изменение активной страницы видеопамяти - функция 05h

Функция 05h позволяет изменить активную страницу видеопамяти. Активная страница видеопамяти отображается на экране.

На входе:   AH = 05h - выбор активной страницы видеопамяти;
            AL = номер страницы видеопамяти, которая станет
                 активной.
На выходе:  Не используются.

8.7. Свертка текстового окна вверх - функция 06h

Свернуть активное окно экрана вверх (при работе в текстовом режиме) можно при помощи функции 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

8.8. Свертка текстового окна вниз - функция 07h

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

На входе:   AH = 07h - свертка окна вниз;
            AL = число прокручиваемх линий, если оно равно
                 нулю, то окно прокручивается целиком;
            BH = атрибут, используемый для строк,
                 возникающих в верхней части окна;
            CH = номер строки левого верхнего угла окна;
            CL = номер колонки левого верхнего угла окна;
            DH = номер строки правого нижнего угла окна;
            DL = номер колонки правого нижнего угла окна.
На выходе:  Не используются.

Эту функцию можно использовать для очистки окна аналогично функции 06h.

8.9. Чтение символа и его атрибутов - функция 08h

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

На входе:   AH = 08h - чтение символа и его атрибутов;
            BH = номер страницы видеопамяти.
На выходе:  AL = ASCII-код символа;
            AH = байт атрибутов символа.

Следующий пирмер считывает символ и его атрибут из текущей позиции курсора на странице page:

   ...
   mov   ah,8         ; читаем символ и его атрибуты
   mov   bh,page      ; выбираем страницу видеопамяти page

   int   10h         ; считываем символ и его атрибут

   mov   char,al      ; сохраняем полученный ASCII-код символа
   mov   attr,ah      ; и его атрибут
   ...

8.10. Запись символа с атрибутами в текущей позиции курсора - функция 09h

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

На входе:   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

8.11. Запись символа в текущей позиции курсора - функция 0Ah

Функция позволяет записать символ в текущей позиции курсора на любой странице видеопамяти. Как и в предыдущей функции, можно производить запись сразу нескольких одинаковых символов. Атрибуты символа не задаются, а используются их старые значения из предыдущих операций записи. После операции записи положение курсора не изменяется. Управляющие символы, такие как возврат каретки и перевод строки, не действуют и записываются, как обычные символы.

На входе:   AH = 10h - запись символа без атрибута;
            AL = ASCII-код записываемого символа;
            BH = номер страницы видеопамяти;
            BL = цвет (для графического режима);
            CX = число записываемых символов.
На выходе:  Не используются.

Если запись символа происходит на видеоадаптере EGA в графическом режиме, и бит D7 регистра BL содержит единицу, то новый символ накладывается на текущее содержимое экрана по логике булевой операции ИСКЛЮЧАЮЩЕЕ ИЛИ.

8.12. Установка цветовой палитры (ржимы 4,5,6) - функция 0Bh

Данная функция позволяет выбрать одну из двух стандартных цветовых палитр (см. таблицу 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).
На выходе:  Не используются.

8.13. Вывод пиксела - функция 0Ch

Использование функций 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();
   }
}

8.14. Чтение пиксела - функция 0Dh

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

На входе:   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

8.15. Запись символа в режиме телетайпа - функция 0Eh

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

Данная функция обрабатывает следующие управляющие символы: звуковой сигнал (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

8.16. Определение текущего режима работы видеоадаптера - функция 0Fh

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

На входе:   AH = 0Fh - определение текущего режима
                       видеоадаптера.
На выходе:  AH = число символов в строке;
            AL = номер текущего режима;
            BH = номер активной страницы видеопамяти.