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

         

Рисование линии по частям в режимах HiColor



Пример 7.6. Рисование линии по част-ям в режимах Hi-Color

push dx coxp аняем содержимое регистра dx
mov dx, di копируем адрес в регистр dx
shl ex, 01 ! ! для True Color - shl ex, 02
add dx, ex сумма исходного адреса и размера линии
jc @F -> прямая расположена в двух окнах
xor dx, dx очис тка регистра dx
@@: sub ex, dx количество точек в текущем окне
shr сх, 01 ! ! для True Color - shr ex, 02
call baseip рисуем всю линию или ее первую часть
or di, di адрес в пределах текущего окна ?
jne hrl_exit -> да, линия нарисована полностью
call NxtWin установка следующего окна


add ex, dx количество не нарисованных точек
je hrl_exit линия нарисована полностью
shr ex, 01 !! для True Color - shr ex, 02
call baselp рисуем остаток линии
hrl exit: pop dx восстановление содержимого dx
ret возврат из подпрограммы
; Подпрограмма, выполняющая основные действия
baselp: mov es: [di],ax !! для True Color — mov es: [di], eax .
add di, bytppnt переадресация операнда
loop baselp управление повторами цикла
ret возврат из подпрограммы

Выполнение примера 7.6 начинается с сохранения в стеке содержимого регистра dx, поскольку оно изменяется в подпрограмме. При входе регистр сх содержит количество рисуемых точек, его надо преобразовать в количество байтов, с помощью сдвига и сложить с исходным адресом видеопамяти (в регистре dx). Если при этом происходит переполнение, то линия не помешается в текущем окне и ее надо рисовать по частям. В противном случае регистр dx очищается. После этого вычисляется количество точек в первой части и вызывается подпрограмма baselp, рисующая начало линии.

При первом вызове baselp может быть нарисована вся линия или только ее первая часть. Это важно знать для выполнения дальнейших действий. Они начинаются с проверки значения адреса, находящегося в регистре di.

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

После установки окна суммируется содержимое регистров сх и dx. Если сумма равна нулю, то линия нарисована целиком, а код ее последней точки был записан в последнее слово сегмента. В противном случае количество байтов, полученное в регистре сх, преобразуется в количество точек и повторно вызывается подпрограмма baselp. Перед возвратом на вызывающий модуль восстанавливается исходное содержимое регистра dx, соответствующая команда имеет метку hri_exit.

Замечание 1
Замечание 1


Практическая ценность примера 7.6 заключается в том, что он иллюстрирует способ обработки строки графического объекта по частям. Основные действия локализованы в подпрограмме baselp. Ее можно изменить так, чтобы вместо записи в видеопамять содержимого регистра ах выполнялись другие действия, например инверсия кодов точек, пересылка кодов из видеопамяти в оперативную или наоборот и т. д.

Ускоренное рисование линии. В подпрограмме baselp, текст которой приведен в примере 7.6, работу с видеопамятью выполняет одна команда, поэтому сразу после нее возможна переадресация операнда. Если при этом шаг переадресации совпадает с размером операнда, то вместо команды пересылки можно использовать строковую операцию. В таком случае тело цикла пересылки сокращается до одной команды rep stosw, которую надо вставить вместо call baselp. Это и сделано в примере 7.7.



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