Графические устройства

         

Окна видеопамяти

При работе в видеорежимах SVGA изображение, находящееся на экране монитора содержит большое количество точек. Оно зависит от разрешающей способности установленного режима и равно произведению количества точек в строке на количество строк. Например, при разрешении 640x480 на экране находится 307200 точек, а при разрешении 1600x1200— 1 920000 точек. Объем видеопамяти, необходимый для хранения содержимого экрана, также зависит от размера кода точки. В режимах PPG код точки занимает 1 байт, поэтому объем видеопамяти совпадает с количеством точек, находящихся на экране, в режимах direct color он в 2 или 4 раза больше. Следовательно, для работы с графическими объектами в режимах SVGA нужен доступ к большому пространству видеопамяти.

Сегментирование памяти

Независимо от конкретного назначения команды IBM PC всегда имеют доступ к ограниченному пространству адресов, предельный размер которого зависит от нескольких факторов, в том числе и от режима работы микропроцессора. Начиная с модели Intel 80386, микропроцессоры могут работать в реальном, виртуальном и защищенном режимах. В реальном и виртуальном режимах все


пространство памяти делится на сегменты, предельный размер которых составляет 65 536 байтов. Указанные в командах адреса операндов всегда относятся к конкретному сегменту, и ни при каких условиях не могут выходить за его пределы, — это вызывает ава-, рийную ситуацию. Значение сегмента хранится в одном из сегментных регистров, который либо явно указывается в имени операнда, либо используется по умолчанию.

Доступ к сегментам

При работе на IBM PC в реальном режиме для доступа к пространству адресов, расположенному за пределами сегмента, используются два разных способа, выбор которых зависит от типа памяти.

Первый способ заключается в том, что в сегментный регистр записывается абсолютный адрес начала нужного сегмента. Специфической особенностью семейства IBM PC является то, что при работе с сегментами общий объем адресуемого пространства не может превышать один мегабайт. Следовательно, возможно использование только 16 сегментов предельного размера (16x65536 = 1048576 = 1 Мбайт). Поэтому прямое указание адреса начала сегмента применяется только при работе с младшей частью оперативной памяти (первые 640 Кбайт). Как это делается, описано в приложении Б данной книги.

Второй способ заключается в том, что сегмент выполняет роль окна, через которое "видна" (доступна) та или иная часть реального пространства адресов. Содержимое сегментного регистра при этом неизменно, а доступная или "отображаемая" часть адресов изменяется по запросам задачи. Такой способ подразумевает существование специального устройства и программного обеспечения, поддерживающих работу с нужным пространством адресов. На IBM PC он применяется для доступа к видеопамяти и к расширенному пространству оперативной памяти ПК (см. приложение Б).

Доступ к видеопамяти. Рассмотрим, как организуется работа со всем пространством видеопамяти. Для обращения к нему используется специальный сегмент, который принято называть видеосегментом. При работе в графических режимах он обычно имеет код АОООЬ, но лучше взять его точное значение из массива info (см. главу 2). Код видеосегмента является просто признаком обращения к видеокарте, а не к какому-либо другому устройству, и не является частью адреса видеопамяти.

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

Во внутреннем регистре видеоконтроллера хранится число, которое принято называть номером окна (или банка) видеопамяти. У современных видеокарт размер окна фиксирован и составляет 65 536 байтов, поэтому, зная объем видеопамяти, можно вычислить количество существующих окон. Одному мегабайту видеопамяти соответствует 16 окон, двум — 32 и т. д.

При каждой смене видеорежима регистр, содержащий номер окна, очищается, т. е. устанавливается нулевое окно видеопамяти. В дальнейшем текущий юмер окна зависит только от действий, выполняемых в задаче, которая мо-кет устанавливать его любое допустимое значение. При переключении окон надо изменять содержимое внутреннего регистра видеоконтроллера, поэтому Для выполнения таких действий предусмотрена специальная процедура BIOS. к Уже говорилось в главе 2, ее вызов через прерывание int 10h не существо замедляет переключение окон, и стандарт VBE рекомендует прямое э°ращение, минуя прерывание int 10h.

В примере 2.8 приведены тексты трех подпрограмм для установки заданного (setwin), следующего (Nxtwin) и предыдущего (prevwin) окна. Они работают c переменной Cur win, имеющей размер слова и содержащей номер теку-лего окна. В примере 2.11 показано, как зарезервировать эту переменную з разделе данных программы. Если задача составлена корректно, то при ее зыполнении значение cur_win должно совпадать с номером окна, храня-лимся в видеоконтроллере.

Закрашивание рабочей области экрана

Для иллюстрации работы с окнами эассмотрим подпрограмму, которая последовательно заполняет заданным «содом отображаемую на экране часть видеопамяти, в результате чего весь жран окрашивается в заданный цвет. Ее текст приведен в примере 3.3. Пе-эед обращением к подпрограмме в байтах регистра еах надо указать код выбранного вами цвета. Предположим, что синему цвету соответствует код 01 (см. табл. 4.2). В таком случае для вызова подпрограммы используются следующие две команды:

nov еах, OlOlOlOlh ; запись кода 01 в байты регистра еах ;all fillscr
; выполнение подпрограммы fillscr : продолжение текста основной программы

В тексте основной (вызывающей) программы должны быть описаны макроопределения PushReg и popReg (пример 2.12) и подпрограммы для работы с жнами (примере 2.8). Кроме того, до обращения к fillscr надо установить эдин из видеорежимов PPG и определить значения переменных Horsize, /ersize и vbuff. Способы описания и определения этих и других, часто используемых переменных, обсуждались в главе 2.

Пример 3.3. Закрашивание всего экрана заданным цветом

fillscr: PushReg <es,di,dx, ex, Cur win,eax>; сохранение в стеке
mov Cur win, 0 очистка переменной Cur win
call SetWin установка нулевого окна
mov es, Vbuff es <= значение видеосегмента
xor di, di 0 — исходный адрес видеопамяти
mov ax, Versize ах <= количество строк (Versize)
mul Horsize dx:ax = Versize Horsize
mov ex, dx ex = количество полных окон
mov dx, ax dx = размер последнего окна
pop eax восстановление содержимого еах
; Цикл записи в полностью заполняемые окна
:l_lp: push ex сохранение счетчика сегментов
mov ex, 16384 количество повторов для rep
rep stosd запись в полное окно
call NxtWin установка следующего окна
pop ex восстановление счетчика сегментов
loop fl Ip управление повторами цикла
l рсяолсги р/лс;/
Запись в частично заполненное окно, если оно существует
mov ex, dx rep stosb
f 1 out: pop Cur_win call SetWin PopReg <cx,dx,di,es>
ret
ex <= оставшееся число байтов запись в неполное окно
; Действия, связанные с завершением работы подпрограммы
восстановление Cur win восстановление исходного окна восстановление регистров возврат из подпрограммы

Первые пять команд примера 3.3 выполняют вспомогательные действия, а именно, сохранение в стеке тех величин, которые будут испорчены при выполнении подпрограммы, установку нулевого окна видеопамяти, запись в регистр es кода видеосегмента и очистку регистра di. В основной части подпрограммы полностью и частично заполненные окна обрабатываются по-разному. Поэтому надо предварительно вычислить количество полных окон, содержащихся в рабочей области памяти, и количество байтов в частично заполненном окне, если оно есть. В примере 3.3 эти величины вычисляются путем умножения значений переменных versize и Horsize.
Один из сомножителей команды умножения должен находиться в регистре ах, а второй указывается в самой команде. Старшая часть результата умножения находится в регистре dx, а младшая — в ах. Таким образом, произведение равно 65 536 [dx] + [ах], квадратные скобки обозначают содержимое указанных в них регистров. Другими словами, после умножения в регистре dx находится количество полных окон, а в регистре ах — количество байтов в частично заполненном окне.

После умножения содержимое регистра dx копируется в сх, содержимое регистра ах — в dx и восстанавливается из стека испорченное при умножении содержимое регистра еах (код цвета точек). Далее действия выполняются в следующем порядке: сначала окрашиваются точки полностью заполненных окон, а затем точки частично заполненного окна, если такое есть.

Окрашивание точек полностью заполненных окон происходит в цикле, имеющем метку fi_ip, он повторяется столько раз, сколько полных окон содержит рабочая область экрана. Заполнение окна выполняет микропрограммный цикл rep stosd, для его ускорения строковая операция (stosd) записывает в видеопамять сразу четыре байта. Поэтому предварительно в регистре сх задается 16 384 повтора этой операции. После закрашивания всего сегмента происходит обращение к подпрограмме Nxtwin для установки следующего окна. Затем из стека восстанавливается содержимое регистра сх и команда loop управляет повторами никла.

После выхода из цикла f i_ip в регистр сх копируется из dx оставшееся количество байтов и выполняется микропрограммный цикл rep stosb.

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

Содержание раздела