Showpnt: pusha сохранение содержимого регистров
push Cur win сохранение исходного окна
mov ax, Winpnt ах = окно с рисунком курсора
mov Cur win, ax Cur win = Winpnt
call setwin установка исходного окна
xor si, si очистка регистра si
mov di, Offspnt di = адрес в сегменте видеопамяти
mov ex, pntYsize сх = кол-во повторов внешнег о цикла
mov bx, horsize вычисляем константу для
sub bx, pntXsize коррекции адресов строк
Sh_l: push ex сохраняем значение счетчика строк
mov ex, pntXsize ex = количество точек в строке рисунка
Sh_2 : mov al, es: [di] ! ! al = код точки исходного фона
mov pntbuff[si], al ! ! сохраняем его в pntbuf f
and al, pntmask[si] ! ! накладываем маску
Начало примера 6.5 отличается от примера 6.4 только одной командой. Вместо записи адреса массива pntimage в регистр si последний просто очищается. Это сделано потому, что регистр si используется для доступа к трем массивам, а не к одному, как это было в примере 6.4.
Принципиальное различие между примерами в основных действиях, выполняемых во внутреннем цикле, который в данном случае имеет метку sh_2. Первая команда внутреннего цикла считывает код очередной точки из видеопамяти в регистр al, а вторая сохраняет его в очередном байте массива pntbuf f. После этого в регистр al помещается результат вычисления логической функции "И" от исходного значения регистра и содержимого очередного байта маски. В зависимости от кода байта маски регистр al либо будет очищен, либо его исходное значение не изменится — третьего не дано. Следующая команда завершает формирование нового кода точки, она вычисляет логическую функцию "исключающее ИЛИ" от содержимого регистра al и очередного байта массива pntimage. Остается записать новый код точки в видеопамять, что и делает команда stosb, одновременно она увеличивает содержимое регистра di на 1.
Основные действия выполнены, шестая команда увеличивает на 1 адрес оперативной памяти (содержимое регистра si). Адрес видеопамяти (содержимое di) увеличила команда stosb, но надо проверить, остался он в пределах текущего видеосегмента или нет. Признаком выхода за пределы сегмента является нуль в регистре di, при этом подпрограмма nxtwin установит следующее окно видеопамяти. Повторами внутреннего цикла управляет команда :оор Sh_2.
После построения строки из стека восстанавливается значение счетчика повторов, вычисляется адрес начала следующей строки в видеопамяти, команда loop sh_i повторяет выполнение внешнего цикла до тех пор, пока на экран не будут выведены все строки изображения курсора.
В заключение из стека выталкиваются исходные значения переменной cur_wir. У всех регистров, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.
Массивы в другом сегменте. Текст примера 6.5 составлен из расчета па то, что массивы pntimage, pntmask и pntbuff расположены в разделе данных п для доступа к ним используется регистр ds, имя которого не указывается перед операндами. Если вы предпочитаете расположить указанные массивы в другом сегменте, то в трех командах примера 6.5 перед именами массивов надо явно указать имя выбранного вами сегментного регистра. Например, mov fs:pntbuf f [si], ai, если для доступ а к массиву pntbuff используется сегментный регистр fs.
Важно
Еще раз напоминаем, что все три массива должны располагаться в одном сегменте.
Действия при удалении курсора. Перед перемещением курсора его старое изображение удаляется с экрана. Кроме того, изображение курсора удаляется перед выводом на экран новых рисунков. В разделе было описано, в каких случаях и почему это надо делать.
Для удаления изображения курсора надо восстановить исходный фон, сохраненный при его построении. Эта процедура ничем не отличается от построения небольшого рисунка, образ которого находится в оперативной памяти, только образом рисунка является исходный фон на месте, построения изображения курсора. В примере 3.21 (см. раздел) описана подпрограмма построения небольшого рисунка. При выполнении графических задач курсор перемещается достаточно часто, поэтому для восстановления исходного фона лучше составить специальную подпрограмму, а не использовать одну из общедоступных. Если же задача работает с указателем мыши в режиме прерываний, то без специальной подпрограммы просто не обойтись. Поэтому мы перепишем пример 3.21 применительно к данному случаю.
Подпрограмма Hidepnt. Текст подпрограммы, выполняющей удаление изображения курсора, приведен в примере 6.6. В нем использованы те же переменные, что и в примерах 6.4 и 6.5, а из трех массивов нужен только pntbuff, содержащий ранее сохраненный фон.