Прямоугольники
Закрашивание прямоугольной области
В примере 3.13 приведена подпрограмма, закрашивающая заданным цветом прямоугольную область произвольного размера. Перед ее вызовом адрес левого верхнего угла прямоугольника помещается в регистр di и устанавливается окно видеопамяти, которому принадлежит этот адрес. Ширина прямоугольника (количество точек в строке) помещается в регистр dx, а высота (количество строк или точек по вертикали) – в регистр сх. Задание кода цвета точек зависит от того, какой вариант подпрограммы horiine вы будете использовать. Horiine может записывать в видеопамять байты, слова или двойные слова. Соответственно один и тот же код цвета указывается в регистре ai, в обоих байтах регистра ах или в четырех байтах регистра еах.
Пример 3.13. Подпрограмма закрашивания прямоугольной области.
rctngl: | PushReg <bx, ex, di, Cur win> | сохранение в стеке |
mov bx, horsize | копируем horsize в регистр bx | |
sub bx, dx | и вычитаем ширину прямоугольника | |
filler: | push ex | сохранение счетчика повторов |
mov ex, dx | задание размера строки | |
call horline | рисуем линию | |
pop ex | восстановление счетчика повторов | |
add di, bx | адрес начала следующей строки | |
jnc @F | › адрес в пределах окна | |
call NxtWin | переход к следующему окну | |
@@: | loop fillar | управление повторами цикла |
PopReg <Cur win,di, cx,bx> | восстановление из стека | |
call setwin | восстановление исходного окна | |
ret | возврат из подпрограммы |
Выполнение примера 3.13 начинается с сохранения в стеке содержимого используемых регистров и переменной cur_win. После этого с помощью двух команд в регистре bx формируется константа для коррекции адресов строк. Как говорилось выше, она равна разности между значением переменной Horsize и шириной прямоугольника, указанной в dx перед вызовом подпрограммы.
Закрашивание прямоугольной области производится в цикле, имеющем метку filiar. Он отличается от аналогичного цикла filibar примера 3.12 тем, что после рисования каждой строки производится коррекция текущего адреса (команда add di, bx). Если при сложении не происходит переполнение результата, то новое значение адреса находится в пределах сегмента и команда jnc @F исключает вызов процедуры Nxtwin. В случае переполнения условный переход не выполняется и происходит установка следующего окна.
После выхода из цикла filiar, перед возвратом в вызывающий модуль, восстанавливаются сохраненные в стеке величины и исходное окно видеопамяти.