Иллюстрированный самоучитель по SVGA

Вывод информационных строк

Подпрограмма Delinfo

Текст подпрограммы, восстанавливающей исходный фон из оперативной памяти, приведен в примере 5.22. Перед ее вызовом надо сохранить содержимое переменной Cur_win и поместить в нее номер окна из переменной infiinw, предварительная установка этого окна не требуется.

Пример 5.22. Восстановление фона на месте информационной строки.

Delinfo: PushReg <Cur win, ax, ex, si, di, fs>; сохранение в стеке
call setwin установка исходного окна
mov di, Inflino di = адрес начала информ. строки
mov fs, GenSeg fs = сегмент общего назначения
xor si, si si = смещение в GenSeg (0)
mov ax, horsize ах = ширина экрана
mul byte ptr hsymh) умножаем ее на высоту символа
mov ex, ax копируем результат в сх
shr ex, 02 и уменьшаем его в 4 раза
Dellp: movs dword prr [di fs:[si]; копирование двойного слова
or di, di адрес в пределах видеосегмента?
jne @F › да, переход на команду loop
call nxtwin установка следующего окна
@@: loop dellp управление циклом копирования
PopReg <fs,di,si,cx, Cur win>; восстановление из стека
call setwin восстановление исходного окна
ret возврат из подпрограммы

В примере 5.22 данные пересылаются из оперативной в видеопамять, что и объясняет все различия текстов примеров 5.21 и 5.22. Цикл пересылки, практически, повторяет аналогичный цикл из примера 3.15 с той разницей, что копируются не байты, а двойные слова. Подразумевается, что регистр es содержит код видеосегмента, указанный в переменной vbuff.

Замечание
При компиляции инструкции movs в том виде, как она записана в примерах 5.21 и 5.22, Макроассемблер MASM 5.1 выдает предупреждающее сообщение, но генерирует правильный код. На это сообщение можно не обращать внимание
.

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

Упрощение подпрограмм

Во всех режимах PPG при выбранном нами размере и расположении информационная строка полностью помещается в последнем окне видеопамяти. Поэтому в цикле пересылки проверять значение текущего адреса видеопамяти не имеет смысла. В примерах 5.21 и 5.22 циклы пересылки состоят из пяти команд и имеют метки savip и oeiip. Все пять команд надо исключить из текста примеров, а вместо них записать одну команду, одинаковую в обоих случаях:

rep movs dword ptr [di],fs: [si]/цикл пересылки для примеров 5.21, 5.22.

Кроме этого, из списка параметров макровызовов PushReg и PopReg надо исключить имя переменной cur_win и удалить команду call setwin перед ret.

Упрощенный вариант подпрограмм можно использовать, только если информационная строка полностью расположена в одном окне. Кроме рассмотренного нами случая, это условие выполняется, если строка расположена вверху рабочей области экрана (коды ее точек расположены в нулевом окне видеопамяти).

Вывод информационной строки

Мы описали сопутствующие действия и можем, наконец, рассмотреть конкретную подпрограмму для вывода строки на экран. Ее текст приведен в примере 5.23. Перед обращением адрес начала строки помещается в регистр si, предполагается, что строка расположена в разделе данных задачи. Признаком конца строки является пустой байт, т. е. строка подготавливается в формате ASCIIZ.

Пример 5.23. Вывод текста информационной строки.

Outlnf: push Cur_win; сохранение исходного значения Cur_win
mov ax, Inflinw; ax = номер окна информационной строки
mov Cur_win, ax; Cur_win = ax
call Savinfo; сохранение исходного фона
jmp short outstr; переход на выборку первого символа
outl: call outsgn вывод на экран очередного символа
outstr: lodsb al = К°Д очередного символа (al = ds:si)
or al, al конец выводимого текста?
jne outl › нет, переход на метку outl;
Здесь могут выполняться сопутствующие действия pop Cur_win
восстановление исходного значения Cur win
call setwin восстановление исходного окна
ret возврат из подпрограммы

Собственно вывод текста в примере 5.23 выполняется в цикле, состоящем из четырех команд. Первая из них имеет имя outl, но точкой входа является следующая команда, имеющая метку outstr. Код очередного символа строки считывается в регистр al, и если он не равен нулю, то происходит возврат на метку outl для обращения к подпрограмме outsgn (см. Пример 5.19). Цикл повторяется, пока в строке не будет обнаружен пустой байт.

При желании вы можете изменить цикл так, чтобы использовался другой признак конца строки или задавалось количество символов в строке. Однако формат ASCIIZ является наиболее удобным.

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

Если другие действия не нужны, то восстанавливается исходное значение переменной Cur_win, устанавливается исходное окно и происходит возврат на вызывающую программу. Выведенный текст остается на экране, а сохраненный фон – в буфере GenSeg.

Замечание
При планировании текстового оформления задачи имеет смысл выделить неизменяемые фрагменты текста, расположенные в различных окнах и заставках. Их можно заранее включить в рисунки окон или заставок с помощью графического редактора. При этом текст становится частью соответствующего рисунка, выводится, перемещается или удаляется вместе с ним. В некоторых случаях это удобно, а современные графические редакторы позволяют включать в рисунки текст, состоящий из символов различных размеров, начертаний и цветов
.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.