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

         

Подпрограмма переключения состояния курсора



Пример 6.4. Подпрограмма переключения состояния курсора

Tglpntr: pusha сохранение содержимого регистров
push Cur_win сохранение исходного окна
ir.ov ax, Winpnt ax = окно с рисунком курсора
mov Cur_win, ax Cur_win = Winpnt
call setwin установка исходного окна
lea si, pntimage si = адрес массива pntimage
mov di, Offspnt di = адрес Е сегменте видеопамяти
mov ex, pntYsize ex = кол-во повторов внешнего цикла
mov bx, horsize вычисляем константу для
sub bx, pntXsize коррекции адресов строк
Displ 1 : push ex сохраняем счетчик строк
mov ex, pntXsize сх = количество точек в строке рисунка
Displ 2: lodsb ! ! al = код очередной точки рисунка
xor es : [di] , al ! ! корректируем байт видеопамяти
inc di ! ! увеличение адреса видеопамяти


jnz @F -> адрес в пределах текущего сегмента
call nxtwin конец сегмента, смена окна
@@: loop Displ 2 управление повторами цикла
pop ex восстанавливаем счетчик строк
add di , bx адрес начала следующей строки
jnc @F -> адрес в пределах текущего сегмента
call nxtwin конец сегмента, смена окна
@@: loop Displ 1 управление повторами цикла
pop Cur win восстановление Cur win
popa восстановление содержимого регистров
call setwin восстановление исходного окна
ret возврат из подпрограммы

В подпрограмме примера 6.4 используется только 5 регистров — ах, bх, сх, si и di, но для сокращения ее текста первая команда pusna сохраняет в стеке содержимое всех регистров. Затем в стек помещается исходное значение переменной Cur win, а ей присваивается новое значение и устанавливается соответствующее окно видеопамяти. В регистры si, di записываются адреса оперативной и видеопамяти, а в сх — количество строк в рисунке курсора. В конце подготовки в регистре bх формируется разность horsize - pntxsize, используемая в цикле построения для коррекции адресов строк видеопамяти.

Построение рисунка выполняют два вложенных цикла. Внешний имеет метку oispi_i. Он начинается с сохранения в стеке и изменения содержимого регистра сх, после чего выполняется внутренний цикл.

Цикл построения строки имеет метку Dispi_2. Его первая команда lodsb считывает в регистр al байт, адрес которого находится в dsrsi, и увеличивает содержимое регистра si на 1. Затем логическая операция XOR записывает содержимое регистра al в видеопамять. Регистр-посредник al нужен потому, что у команды хог (как и у команды mov) оба операнда не могут находиться в памяти.

После вывода очередной точки адрес видеопамяти увеличивается на 1, и если его значение осталось в пределах сегмента, то команда jnz @F обходит call nxtwin. В противном случае команда call nxtwin выполняется и устанавливается следующее окно. Последняя команда (loop Disp_2) повторяет выполнение цикла до тех пор, пока не будет нарисована вся строка.

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

После построения (или удаления) курсора из стека выталкивается содержимое переменной cur_wir. и всех сохраненных регистров, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.



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