CallWin: PushReg <dx, ax> | сохранение регистров dx и ах |
mov ax, horsize | помещаем в ах размер строки |
mul dx | умножаем на номер строки |
add ax, ex | прибавляем номер столбца |
adc dx, 00 | учитываем возможность переполнения |
mov di, ax | копируем адрес в регистр di |
mov ax, GrUnit | единица приращения окна |
mul dl | умножаем на номер окна |
add ax, Base win | ! ! только при работе со страницами ! ! |
mov Cur win, ax | копируем окно в Cur win |
PopReg <ax, dx> | восстанавливаем регистры |
jmp SetWin | установка окна и выход |
Прежде чем рассматривать примеры использования этой подпрограммы, несколько слов об особенностях команды умножения (mul). При ее записи явно указывается только один операнд, второй выбирается из аккумулятора (ai, ax или еах), куда его надо предварительно поместить. Команда может умножать байты, простые или двойные слова, размер сомножителей определяется по размеру (типу) указанного в команде операнда. В зависимости от размера сомножителей произведение может содержать Гб, 32 или 64 разряда и соответственно находиться в регистре ах, в регистрах dx и ах, или в регистрах edx и еах. В примере 3.4 первая команда mul dx умножает слова, поэтому произведение расположено в регистрах dx и ах, а вторая (mul di) умножает байты, поэтому результат занимает только регистр ах.
Для того чтобы с адресом точки можно было работать, надо установить вычисленное окно видеопамяти. Поэтому в примере 3.4 номер окна записывается в Cur_win и происходит переход на процедуру setwin, которая устанавливает окно. Смещение в окне помещается в регистр di для того, чтобы его можно было использовать для записи кодов точек с помощью строковой операции stos.
В примере 3.4 нет команды возврата из подпрограммы (ret). Она не нужна потому, что процедура установки окна не вызывается командой call Setwin, а происходит безусловный переход на ее начало (jmp setwin). Возврат на вызывающий модуль выполнит процедура setwin.
В данном случае нет острой необходимости в указанной замене. Мы привели ее в качестве примера того, как можно исключать ненужные действия. При каждой такой замене исключаются одна команда и несколько тактов при обращении к процедуре.
Важно
При замене команды call командой jmp надо следить за тем, чтобы в верхушке стека находился адрес возврата на вызывающий модуль.
Указание номеров столбца и строки в регистрах сх и ах выбрано для совместимости с драйвером манипулятора "мышь", который описан в главе 6. При каждом перемещении мыши приходится вычислять новый адрес начала рисунка курсора, это и объясняет выбор указанных регистров.