Окна видеопамяти
Закрашивание рабочей области экрана
Для иллюстрации работы с окнами рассмотрим подпрограмму, которая последовательно заполняет заданным "содом отображаемую на экране часть видеопамяти, в результате чего весь экран окрашивается в заданный цвет. Ее текст приведен в примере 3.3. Перед обращением к подпрограмме в байтах регистра еах надо указать код выбранного вами цвета. Предположим, что синему цвету соответствует код 01 (см. табл. 4.2). В таком случае для вызова подпрограммы используются следующие две команды:
nov еах, OlOlOlOlh; запись кода 01 в байты регистра еах;all fillscr ; выполнение подпрограммы fillscr: продолжение текста основной программы
В тексте основной (вызывающей) программы должны быть описаны макроопределения PushReg и popReg (Пример 2.12) и подпрограммы для работы с окнами (Примере 2.8). Кроме того, до обращения к fillscr надо установить эдин из видеорежимов PPG и определить значения переменных Horsize, versize и 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, то строковая операция не будет выполняться ни разу.
Заключительные действия выполняет фрагмент, имеющий метку fi_oui В нем восстанавливаются сохраненные в стеке величины, исходное окно видеопамяти и происходит возврат из подпрограммы.
Приведенный пример иллюстрирует простейший случай работы с окнами видеопамяти, когда не требуется специальная проверка достижения границы сегмента и необходимости переключения окна. В большинстве случаев такая проверка нужна и на ее выполнения затрачиваются дополнительные действия, замедляющие процесс построения изображения на экране. Исключить такие действия невозможно, но можно попытаться свести их к необходимому минимуму, в зависимости от конкретного алгоритма построения изображения. Мы будем неоднократно возвращаться к этому вопросу при описании приводимых в книге примеров.