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