; Установка следующего окна | |
NxtWin: push ax | ; сохраняем содержимое ах |
mov ax, GrUnit | ; читаем единицу приращения окна |
add Cur win, ax | ; увеличиваем номер окна |
pop ax | ; восстанавливаем содержимое ах |
; Установка окна, указанного в Cur win | |
SetWin: PushP,eg <ax,bx,dx> | ; сохранение содержимого регистров |
xor bx, bx | ; признак установки окна |
mov dx, Cur win | ; номер устанавливаемого окна |
call [VMC] | ; обращение к подпрограмме BIOS |
PopReg <dx,bx,ax> | ; восстановление содержимого регистров |
ret | ; возврат из подпрограммы |
; Установка предыдущего окна | |
PrevWin push ax | ; сохранение содержимого ах |
mov ax, GrUnit | ; читаем единицу приращения окна |
sub Cur win, ax | ; уменьшаем номер окна |
pop ax | ; восстанавливаем содержимое ах |
jmp SHORT SetWin | ; переходим на установку окна |
Процедура VMC расположена в "удаленном" сегменте, т. е. в пространстве адресов, не принадлежащих задаче. В таких случаях для обращения к подпрограммам используется команда call, у которой операнд является двойным словом, содержащим полный адрес (сегмент и смещение). При компиляции Макроассемблер формирует специальный код, указывающий процессору, что переход производится на удаленный адрес. В примере 2.8 операндом команды call является переменная VMC, описанная как двойное слово. Заключение имени переменной в квадратные скобки указывает на то, что адресом процедуры является не VMC, а хранящееся в ней значение, которое было установлено при выполнении команд примера 2.6.
Указание типа short в команде jmp заставит Макроассемблер сформировать короткую команду (для перехода не более чем на 128 байтов), код которой занимает два байта. pushReg и PopReg — это макросы (макровызовы). Первый эквивалентен трем командам push ax, push bx и push dx, а второй — трем командам pop dx, pop bx, pop ax. В реальной программе вы должны либо заменить макросы указанными командами, либо поместить в начале текста программы соответствующие им макроопределения, текст которых приведен в примере 2.12. Сохранение исходного содержимого регистров в стеке и восстановление при выходе делается для того, чтобы находящиеся там данные не изменялись в результате выполнения подпрограммы.
Чтение текущего окна. Еще раз вернемся к текущему окну. При корректной работе задачи с окнами значение переменной Cur_win всегда соответствует номеру, находящемуся в регистре видеоконтроллера. Если по каким-то причинам такое соответствие нарушено, то текущее значение окна можно восстановить, прочитав его из видеоконтроллера. Оформлять чтение текущего окна в виде самостоятельной процедуры не целесообразно, поскольку регулярных обращений к ней не должно быть.
Для чтения окна с помощью функции 4F05h надо выполнить следующие три команды:
mov bx, 10Oh | ; признак чтения окна |
mov ax, 4F05h | ; код запрашиваемой функции |
int 10h | ; обращение к BIOS |
Другой способ чтения текущего значения окна заключается в прямом обращении к процедуре BIOS, а именно:
mov bx, lOOh | ; признак чтения окна |
call [VMC] | ; обращение к процедуре BIOS |
В обоих случаях номер текущего окна возвращается в регистре dx. Каким из двух способов лучше воспользоваться, решает программист. Мы привели эти примеры для того, чтобы еще раз проиллюстрировать различие между прерыванием и прямым обращением к процедуре.