4.3.1 Вывод на экран одного символа.

Error message

Notice: Undefined index: add term path in hansel_get_breadcrumbs() (line 524 of /data/sites/msdosworld.ru/www/sites/all/modules/hansel/hansel.module).

  Все процедуры для  вывода  символа  на  экран  в BIOS и DOS (а
также  в  Бейсике) помещают символ в текущую  позицию  курсора  и
автоматически передвигают курсор на одну позицию вправо.  Все они
переносят вывод на следующую строку при достижении конца  строки,
если не сделано специальных  указаний  отбрасывать все символы за
80-м столбцом [4.2.2]. Важное отличие между отдельными процедура-
ми состоит в том, что некоторые  вместе  с символом пишут также и
его атрибуты, а некоторые этого не делают.
   Как  в языках высокого, так и в языках низкого уровня, символы
могут выводиться на  экран  без  использования  обычных  операций
печати.   Вместо этого используется прямое отображение в  память,
при котором коды символов и их атрибуты прямо засылаются в ячейки
памяти видеобуфера, соответствующие определенной позиции  курсора
на экране. Буфер начинается с  адреса  B000:0000 для монохромного
адаптора и с адреса B800:0000 - для цветного графического адапто-
ра и PCjr.  EGA использует те же самые адреса в аналогичных режи-
мах экрана.  Позиции с четными номерами (начиная с нуля) содержат
коды ASCII символов, а позиции с нечетными номерами - байты атри-
бутов.  На рис. 4-2 показан участок памяти видеобуфера.  При этих
операциях позиция курсора не  меняется  и  он может быть выключен
при  желании  [4.2.3].  Вместо курсора надо  хранить  переменные,
служащие указателями на текущую позицию.

   Высокий уровень.

   Бейсик выводит как  отдельные  символы,  так и целые строки, с
помощью  одних и тех же операторов PRINT и WRITE.   Как  правило,
используется  PRINT; WRITE - это один из вариантов со специальны-
ми, редко используемыми форматами вывода. PRINT работает с данны-
ми трех видов.  Он выводит содержимое как строковых, так и число-
вых переменных, например, PRINT S$ или PRINT X.  Он выводит также
символы, вставленные (в кавычках) внутрь самого оператора  PRINT,
например, PRINT "This words are printed". Он выводит также симво-
лы,  соответствующие  кодам ASCII, включенным в оператор PRINT  в
виде операторов CHR$, например,  PRINT  CHR$(65),  что приводит к
выводу на экран символа A (код ASCII #65).
   В  одном  операторе PRINT могут выводиться много  данных,  при
этом все три формы данных могут быть перемешаны. Отдельные данные
отделяются запятой или точкой с запятой. Запятая приводит к тому,
что следующие данные будут выводиться  со следующей позиции табу-
ляции данной строки.  Точка с запятой приводит к тому, что данные
печатаются на экране подряд, не  разделенные  пробелами (отметим,
что PRINT вставляет пробел перед выводом любой числовой  перемен-
ной, а WRITE не делает этого). Обычно оператор PRINT автоматичес-
ки  делает перевод на новую строку при завершении, таким  образом
следующий  такой  оператор  начнет  вывод  с новой строки экрана.
Чтобы перенос на новую строку не происходил надо в конце операто-
ра PRINT поставить точку с запятой, например, PRINT S$;.
   Для установки позиции курсора  перед  выводом используется оп-
ератор LOCATE. Без оператора LOCATE PRINT всегда начинает вывод с
первой позиции строки, в которой находится курсор. Последователь-
ные  операторы  PRINT заполняют экран до тех пор, пока  не  будет


записана 24-я строка, после  чего  экран  сдвигается вверх, с тем
чтобы  следующий оператор PRINT снова выводил 24-ю строку.  PRINT
может выводить в 25-й  строке  только  при  помощи  LOCATE; и это
также приводит к автоматическому сдвигу экрана вверх.  Чтобы зап-
ретить сдвиг надо окончить оператор PRINT точкой с запятой. Одна-
ко  этот  метод не сработает в последних позициях строк 24 и  25.
Для заполнения этих позиций без сдвига экрана Вы должны использо-
вать отображение в память, как показано ниже.
   Вы можете включать управляющие символы [7.1.9] внутрь операто-
ра PRINT для того чтобы  реализовать  перемещения  курсора внутри
строки.  Например, если Вы поместите в строку CHR$(13), то в этой
точке будет сделан возврат каретки.   Если Вы выведете оператором
PRINT строку "One"+CHR$(13)+"Two"+CHR$(13)+"Three", то в  резуль-
тате каждое слово будет  выводиться  с  новой строки.  Коды ASCII
28-31  сдвигают  курсор на одну  позицию  соответственно  вправо,
влево, вверх и вниз. Оператор PRINT не содержащий данных приводит
к  выводу  возврата каретки и, таким образом, следующий  оператор
PRINT будет выводить на строке через одну.
   Прямое отображение в память  существенно  увеличивает скорость
вывода на экран в Бейсике. Оно особенно полезно при конструирова-
нии табличного вывода, когда формы могут достигать правого нижне-
го  угла экрана.  Сначала надо установить указатель  сегмента  на
&HB000, а затем  использовать  оператор  POKE  для засылки байтов
памяти.  Прилегающие по горизонтали символы отстоят друг от друга
на два байта, разделяемые  байтом  атрибутов.   Для 80-символьных
экранов прилегающие по вертикали символы отстоят на 160 байт друг
от друга (2 байта для каждого  символа  и атрибутов). В следующих
двух  примерах  вдоль  границы экрана рисуется  рамка,  используя
символы псевдографики.  В первом примере чаще используется опера-
тор  PRINT, а во втором используется исключительно прямое отобра-
жение в память. Отметим, что и в первом случае приходится исполь-
зовать прямое отображение в память в последних столбцах строк  24
и 25, чтобы избежать сдвига экрана.

   Использование PRINT:

 10 CLS: KEY OFF              'очистка экрана
 20 DEF SEG = &HB000          'указываем на видеобуфер
 30 LOCATE 1,1: PRINT CHR$(201)   'левый верхний угол
 40 LOCATE 1,80: PRINT CHR$(187)  'правый верхний угол
 50 LOCATE 1,24: PRINT CHR$(186)  '
 60 LOCATE 1,25: PRINT CHR$(200)  '
 70 POKE 3838,186                 'позиция 80 строки 24
 80 POKE 3998,188                 'позиция 80 строки 25
 90 FOR N=2 TO 79                 'горизонтальные линии
100 LOCATE 1,N: PRINT CHR$(205);: LOCATE 25,N: PRINT CHR$(205)
110 NEXT                          '
120 FOR N=2 TO 23                 'вертикальные линии
130 LOCATE N,1: PRINT CHR$(186): LOCATE N,80: PRINT CHR$(186)
140 NEXT


   Использование прямого отображения в память:

 10 CLS: KEY OFF               'очистка экрана
 20 DEF SEG = &HB000           'буфер монохромного дисплея
 30 POKE 0,201                 'левый верхний угол
 40 POKE 158,187               'правый верхний угол
 50 POKE 3840,200              'левый нижний угол
 60 POKE 3998,188              'правый нижний угол
 70 FOR N=2 TO 156 STEP 2      'горизонтальные прямые
 80 POKE N,205: POKE N+3840,205  'как верхняя, так и нижняя
 90 NEXT
100 FOR N=160 TO 3680 STEP 160 'вертикальные прямые
110 POKE N,186: POKE N+158,186 'правая и левая
120 NEXT

   Средний уровень.

   Операционная  система  предоставляет шесть процедур вывода  на
экран - три в BIOS и три в DOS.   Они  отличаются главным образом
тем, передвигается курсор или нет, после вывода символа, вызывают
ли они сдвиг экрана, позволяют  ли  они  устанавливать атрибуты и
цвета символов, а также какие управляющие коды они интерпретируют
(некоторые  рассматривают  символ  BackSpace,  просто как обычный
символ, а некоторые действительно сдвигают курсор на одну позицию
назад). Эти шесть процедур следующие:

   Прерывание 10H:

   функция   9     вывод символа с атрибутами
             A     вывод символа без атрибутов
             E     "телетайпная" процедура (как на принтер)

   Прерывание 21H:

   функция   2     вывод символа без атрибутов
             6     вывод символа без атрибутов
             9     вывод строки символов

   Функции 9 и A прерывания 10H  вообще  не интерпретируют управ-
ляющие  символы.   Функции DOS интерпретируют  управляющие  коды,
приведенные в следующей таблице. Функция E прерывания 10H интерп-
ретирует все коды таблицы, кроме ASCII 9.

   ASCII   7     звонок
   ASCII   8     возврат на шаг (BackSpace)
   ASCII   9     табуляция
   ASCII  10     перевод строки
   ASCII  13     возврат каретки

   Первые  две функции прерывания 10H не передвигают курсор после
вывода символа.  Функция  9  этого  прерывания выводит на экран с
указанием  атрибутов, а функция A - без указания, при этом сохра-
няется текущее значение  байта  атрибутов  для  этого символа. AL
должен содержать выводимый символ, а BL - атрибуты. Номер страни-
цы дисплея содержится в BH. Он должен указываться даже для монох-


ромного  дисплея, который имеет только одну страницу памяти дисп-
лея. В этом случае должна быть установлена первая страница, кото-
рой соответствует номер 0. Особое свойство этих двух функций BIOS
состоит в том, что символ выводится такое число раз, какое указа-
но в CX. Обычно указывают CX равным 1, но эти функции могут легко
выводить целые  строки  символов,  если  указать большее значение
счетчика  - полезное свойство при создании рамок.   Отметим,  что
даже если выводится много  символов,  то позиция курсора не изме-
няется.   Когда  строка выводимых символов займет  все  свободное
пространство экрана справа-вниз  от курсора, то вывод будет пере-
несен в первые позиции экрана.

;---вывод символа в негативе
   MOV  AH,9             ;функция записи с атрибутами
   MOV  AL,THE_CHARACTER    ;символ в AL
   MOV  BL,112           ;атрибуты в BL
   MOV  BH,0             ;страница 1
   MOV  CX,1             ;вывести один раз
   INT  10H

Вместо  того, чтобы постоянно восстанавливать значение счетчика в
CX прерывание  BIOS  предоставляет  также  телетайпную процедуру,
которая  больше подходит для вывода строки символов.  Она  выпол-
няется функцией E.  Она  готовится так же, как и функция A, но не
надо  засылать  значение в CX.  Строка выводится просто  за  счет
изменения символа в AL и  повторного  вызова  прерывания. При ис-
пользовании в графическом режиме в BL устанавливается цвет палет-
ты, в противном случае сохраняется старый атрибут.

;---вывод строки с помощью телетайпной процедуры
            MOV  AH,0EH     ;номер функции
            MOV  BH,0       ;номер страницы
            LEA  BX,STRING  ;BX указывает на строку
NEXT_CHAR:  MOV  AL,[BX]    ;берем символ в AL
            CMP  AL,'$'     ;проверка на конец строки
            JE   ALL_DONE   ;если да, то выход
            INT  10H        ;вывод строки
            INC  BX         ;переходим к следующему символу
            JMP  SHORT NEXT_CHAR   ;повторяем процедуру
ALL_DONE:

   Прерывание DOS 21H как  правило  предоставляет  более полезные
процедуры,  поскольку они перемещают курсор и  приводят к  сдвигу
экрана при достижении нижней строки, а также интерпретируют неко-
торые из обычных управляющих кодов.  Функции DOS выводят на стра-
ницу, которая должна быть  установлена  функцией 5 прерывания 10H
[4.5.3].  Предоставляются две функции для вывода символа, с номе-
рами 2 и 6. Первая из них распознает Ctrl-Break [3.2.8], а вторая
-  нет.   (Когда с клавиатуры вводится Ctrl-Break,  то  процедура
обработки Ctrl-Break не  выполняется  до тех пор, пока не исполь-
зуется функция, которая распознает его наличие).
   Обе функции выводят белые символы на черном фоне, до тех  пор,
пока не сделана  специальная  установка  цвета с помощью драйвера
устройства ANSI.SYS [4.1.3].  В общем необходимо только поместить
символ в DL, номер функции в AH и  вызвать прерывание 21H. Однако


функция 6 особенная в том смысле, что она имеет второе назначение
в качестве функции ввода с клавиатуры.  Она выступает в этой роли
только  если в DL помещен код FF [3.1.5].  Во всех остальных слу-
чаях она выводит на  экран  содержимое  DL.  В  следующем примере
функция  6 поочередно принимает и печатает символ (в [3.1.4]  об-
суждается процедура, которая комбинирует оба этих свойства).

       MOV  AH,6       ;номер функции
NEXT:  MOV  DL,0FFH    ;при этом значении принимаем ввод
       INT  21H        ;выполняем прерывание
       JZ   NEXT       ;если не было ввода, то обратно
       CMP  AL,13      ;это был возврат каретки?
       JE   END_INPUT  ;если да, то на конец
       MOV  DL,AL      ;иначе посылаем символ в DL
       INT  21H        ;и выводим его на экран
       JMP  SHORT NEXT ;повторяем процедуру

   Низкий уровень.

   На  нижнем  уровне  весь вывод на экран  осуществляется  через
отображение в память.  Эту  технику  не рекомендуют использовать,
чтобы не столкнуться с проблемой совместимости с будущими поколе-
ниями машин, однако до сих пор IBM делало видеобуфер своих микро-
компьютеров устроенным одинаково и расположенным в одних и тех же
адресах памяти.  Поскольку буфер устроен таким образом, что байты
атрибутов  перемежаются с байтами символов, то символьные  данные
не могут просто пересылаться из памяти в буфер инструкцией MOVSB,
поскольку  указатель  в буфере должен увеличиваться на два  после
каждого переноса байта.  Однако,  использование  этой техники су-
щественно  ускоряет  вывод на экран.  Отметим, что отображение  в
память не работает при выводе  символов  в  графическом режиме. В
этом  случае размер видеобуфера 16K или 32K и BIOS рисует  каждый
символ поточечно.  Отметим также, что при отображении в память не
используется  курсор для указания на символ.  При  желании  можно
перемещать курсор по мере ввода  [4.2.1] или выключить его и соз-
дать свой псевдокурсор [4.2.6].

;---в сегменте данных
SAMPLE_STRING  DB   'PRINT THIS STRING$'

;---вывод строки
       MOV  AX,0B000H            ;монохромный дисплей
       MOV  ES,AX                ;указываем на видеобуфер
       LEA  BX,SAMPLE_STRING     ;BX указывает на строку
       MOV  DI,CURSOR_START      ;начальная позиция в буфере
NEXT:  MOV  AL,[BX]              ;берем символ
       CMP  AL,'$'               ;проверка на конец строки
       JE   ALL_DONE             ;если да, то выход
       MOV  ES:[DI],AL           ;иначе помещаем символ в буфер
       INC  DI                   ;увеличиваем указатель на 2
       INC  DI                   ;
       INC  BX                   ;переходим к обработке следу-
       JMP  SHORT NEXT           ;щего символа
ALL_DONE:


   У  цветного графического адаптора и PCjr (но не у EGA) имеется
проблема, связанная с  отображением  в память. Когда запись в бу-
ферную  память происходит одновременно с чтением ее для вывода на
экран, то на экране возникает интерференция. Эта проблема решает-
ся  ожиданием  сигнала "все чисто" (all clear)  перед  записью  в
видеобуфер. Надо непрерывно читать значение из порта 3DAH.  Когда
бит 0 равен 1, то можно спокойно писать.  (3DAH - это порт, через
который PCjr посылает данные массиву ворот дисплея; когда из него
читаем,  то он возвращает регистр статуса, как и у цветного адап-
тора.)

;---ожидаем пока все чисто
        MOV  DX,3DAH          ;порт регистра статуса
CHECK_AGAIN:   IN   AL,DX     ;получаем значение
        TEST AL,1             ;проверка первого бита
        JNE  CHECK_AGAIN      ;если он 0, то обратно
;---теперь выводим сообщение
        LEA  BX,MESSAGE       ;сообщение в сегменте данных
        MOV  DI,2000          ;начинаем вывод с центра экрана
        MOV  AH,01000001B     ;атрибут синий на красном
NEXT_CHAR:   MOV  AL,[BX]     ;берем символ
        CMP  AL,'$'           ;проверяем на конец строки
        JE   ALL_DONE         ;если конец, то на выход
        MOV  ES:[DI],AX       ;иначе выводим символ
        INC  BX               ;увеличиваем указатель строки
        INC  DI               ;увеличиваем указатель буфера
        INC  DI               ;
        JMP  SHORT NEXT_CHAR  ;обрабатываем следующий символ
ALL_DONE:

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

 

Вы находитесь в разделе: 

Добавить коментарий