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 ! ! увеличение адреса видеопамяти
В подпрограмме примера 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. и всех сохраненных регистров, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.