8.6.3. Текстовый режим

Два текстовых режима цветного графического адаптера дают простой способ вывода символов на экран. В текстовых режимах цветная плата аналогична монохромному адаптеру, но она позволяет указать цвет каждого символа. Так же, как и в монохромной плате, каждая символьная позиция цветной платы имеет байт атрибутов. Этот байт атрибутов определяет цвета символов и фона каждой позиции. На Фиг.8.9 показана структура байта атрибутов в цветном текстовом режиме. Три бита, помеченных ФОН, определяют один из восьми возможных цветов фона. Три бита СИМВОЛ определяют цвет символа. Бит Я также влияет на цвет символа: его установка делает цвет символа более ярким. Тем самым обеспечивается выбор одного из 16 цветов символа. Байт атрибута управляет единственным символом, позволяя выбрать любую комбинацию цветов фона и символа каждой позиции. Старший бит, помеченный буквой М, обычно вызывает мигание символа. Установка бита мигания равным 1 заставляет контроллер дисплея переключать цвет символа между его цветом и цветом фона со скоростью примерно четыре раза в секунду. Так как символ, изображенный в цвете фона, невидим, то получается эффект мигания. Можно заменить бит мигания четвертым битом цвета фона, разрешив при этом 16 цветов фона и 16 цветов символа. Это делает один из битов регистра выбора цветов. Еще надо обратить внимание на то, что одинаковая установка цветов символа и фона означает, что вы не видите символ. Символ есть, но это все равно что пытаться увидеть северного медведя в пургу - все одного цвета. На Фиг. 8.10 показаны все 16 цветов, возможных в текстовом режиме.

Номер бита
76543210
МФОНЯСИМВОЛ

Фиг. 8.9 Байт атрибута для CGA

IRGBЦвет
0000черный
0001синий
0010зеленый
0011морской волны
0100красный
0101магента
0110коричневый
0111светло-серый
1000темно-серый
1001голубой
1010светло-зеленый
1011светлый морской
1100розовый
1101светлый магента
1110желтый
1111белый

Фиг. 8.10 Цвета
(Фирма IBM, © 1981 г.)

Если вы сравните байт атрибута для CGA с атрибутами для монохромного адаптера на Фиг. 8.7, то увидите, что они аналогичны. Конечно, вы не можете указать цвета монхромному адаптеру, но все остальное совпадает. Поскольку цветная плата не поддерживает атрибут подчеркивания, то установка монохромного атрибута подчеркивания соответствует голубому символу на черном фоне.

Такая организация байта атрибутов является попыткой сделать два видео адаптера по-возможности совпадающими. Каждый символ в буфере дисплея находится по четному адресу, а байт атрибутов - по нечетному. Память цветного дисплея находится на видео адаптере, но по другому адресу: у монохромного дисплея она имеет адрес 0B0000H, а у цветного - 0B8000H. О сходстве дисплеев говорит то, что если при модификации программы для монохромного дисплея на Фиг. 8.8, изменить содержимое указателя AT сегмента на значение 0B800H, программа будет верно работать и на цветной плате. То есть одна и та же программа работает на любом видео адаптере при минимуме изменений.

Для управления адаптером на цветной плате также используется контроллер ЭЛТ 6845 фирмы Motorola. Два порта ввода-вывода этого контроллера имеют адреса ввода-вывода 3D4H и 3D5H. На самом деле контроллер 6845 имеет 18 внутренних регистров. Доступ ко всем регистрам осуществляется с помощью двух портов ввода-вывода и косвенной адресации. Для обращения к регистру микросхемы 6845, нужно сначала загрузить индекс регистра в порт 3D4H, а затем читать этот регистр или записать в него данные через порт 3D5H.

Приведем пример, чтобы пояснить, как работает контроллер. На Фиг. 8.11 перечислены все 18 регистров микросхемы 6845. В примере мы используем только регистры R10 и R11. Эти регистры определяют начальную и конечную строки растра одного знакоместа для курсора. Каждый символ, порождаемый цветной платой, состоит из восьми строк растра, имеющих номера от 0 до 7. Вы можете поместить курсор в любых из этих восьми строк. Регистр R10 сообщает микросхеме 6845, на какой строке начинается курсор, а регистр R11 определяет последнюю строку курсора. ROM BIOS инициализирует курсор, находящийся на строках 6 и 7; это делается загрузкой числа 6 в R10 и числа 7 в R11.

Прогамма на Фиг.8.12(а) модифицирует курсор цветной графической платы. Она смещает курсор так, что он оказывается на верхних пяти строках растра вместо нижних двух. Сначала программа загружает в индексный регистр контроллера 6845 (3D4H) число 10, а затем записывает номер начальной строки, равный 0, в регистр данных (3D5H). Затем, поместив 11 в индексный регистр, она устанавливает номер конечной строки равным 4. Теперь курсор имеет вид мигающего блока в верхней части позиции символа, а не митающего подчеркивания. Подобный этому способ модификации курсора используется несколькими редактирующими программами (редакторами) персональной ЭВМ, включая встроенный редактор интерпретатор языка Бейсик. При установке режима вставки во время редактирования, курсор становится жирнее; интерпретатор Бейсика делает это, меняя параметры в микросхеме 6845.

Вернувшись к Фиг. 8.11, можно увидеть, что в микросхеме 6845 есть и другие регистры. Большинство из них управляет сигналами горизонтальной и вертикальной синхронизации телевизионного растра. Вы можете модифицировать коды в этих регистрах для каких-либо действий дисплеем. Например, команда MODE системы DOS, которая может сдвигать катринку на экране влево и вправо, модифицирует регистр R2, задающий положение строчного синхроимпульса. Если вы захотите поэкспериментировать с этими регистрами, вам придется писать короткие программы, делающие требуемые изменения.

Регистр
#
Регистр хранит Объект в
программе
чтение запись
R0 Гориз. сумма Символ Нет Да
R1 Выводимая горизонталь Символ Нет Да
R2 Гориз. поз. синхронизации Символ Нет Да
R3 Гориз. ширина синхронизации Символ Нет Да
R4 Вертикальный итог Симв. ряд Нет Да
R5 Общая вертикальн.коррекция Скан. строки Нет Да
R6 Выводимая вертикаль Симв. ряд Нет Да
R7 Поз. вертикальной синхрон. Симв. ряд Нет Да
R8 Режим совмещения - Нет Да
R9 Макс.адрес скан. строки Скан. строки Нет Да
R10 Начало курсора Скан. строки Нет Да
R11 Конец курсора Скан. строки Нет Да
R12 Начальный адрес (гориз.) - Нет Да
R13 Начальный адрес (строка) - Нет Да
R14 Курсор (Гориз.) - Да Да
R15 Курсор (Строка) - Да Да
R16 Световое перо (гориз.) - Да Нет
R17 Световое перо(строка) - Да Нет

Фиг. 8.11 Регистры микросхемы 6845 (с разрешения фирмы Motorola)

Если попытаться изменять регистры с помощью утилиты DEBUG, то это может не сработать. Регистры R14 и R15 управляют позицией курсора, и если утилита DEBUG переместит курсор между вашими обращениями к индексному регистру и к регистру данных, изменения не произойдет. Так получилось потому, что утилита DEBUG изменила содержимое индексного регистра микросхемы 6845, и он уже больше не указывает на тот внутренний регистр, который вы хотели изменить.

Другая интересная регистровая пара микросхемы 6845 - пара регистров начального адреса R12 и R13. Адаптер цветного графического дисплея имеет 16K байт памяти, а монохромная плата 4K байта. Дополнительная память в цветной плате используется для графических режимов, но она целиком в вашем распоряжении и в текстовых режимах. Для текстового режима 80*25 требуется 4K байта памяти, так что в буфере есть место для четырех разных страниц памяти. Сдвигать данные на экране можно переносом данных с одного места на другое, как это делалось на Фиг. 8.8. В случае же вертикального сдвига нужно лишь изменить начальный адрес в микросхеме 6845. Обычно начальный адрес равен 0. Если вы измените его на 80 (число символов в строке), отображение будет начинаться со второй строки. Это даст немедленный эффект сдвига всех данных экрана вверх на одну строку.

На самом деле вы не изменяли данные, а сдвинули начало сканирования памяти дисплея. Можно рассматривать дисплей как окно 80*25, через которое мы смотрим в 8192-символьный буфер дисплея.

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

[Прим. перев.: стр. 252 текста оригинала в моей копии отсутствует. Очевидно, на ней находится только начало Фиг. 8.12]


Microsoft (R) Macro Assembler Version 5.00                  1/1/80 04:03:56
Фиг. 8.12 Программа управления цветным дисплеем                   Page  1-1
PAGE  ,132
                         TITLE    Фиг. 8.12 Программа управления цветным дисплеем

0000                     STACK    SEGMENT STACK
0000    0040[                     DW        64 DUP (?)
             ????
            ]
0080                     STACK    ENDS

0000                     DISPLAY_BUFFER     SEGMENT AT 0B800H
0000                     DISPLAY_START      LABEL     WORD
0000                     DISPLAY_BUFFER     ENDS

        = 03D4           CRT_INDEX          EQU       03D4H
        = 03D5           CRT_DATA           EQU       03D5H
        = 03DA           CRT_STATUS         EQU       03DAH
        = 000A           CURSOR_START       EQU       10  ; Регистры управления курсором
        = 000B           CURSOR_END         EQU       11  ; в контроллере дисплея 6845

0000                     CODE     SEGMENT

                                  ASSUME    CS:CODE
0000                     COLOR_GRAPHICS     PROC      FAR
0000    1E                        PUSH      DS            ; Адрес возврата в ДОС
0001    2B C0                     SUB       AX, AX
0003    50                        PUSH      AX            ;-----   Фиг. 8.12 (а) Изменение курсора
0004    BA 03D4                   MOV       DX, CRT_INDEX
0007    B0 0A                     MOV       AL, CURSOR_START ; Установка индексного регистра
0009    EE                        OUT       DX, AL        ; 6845 на регистр начала курсора
000A    42                        INC       DX
000B    B0 00                     MOV       AL, 0
000D    EE                        OUT       DX, AL        ; Установка начала курсора
000E    4A                        DEC       DX
000F    B0 0B                     MOV       AL, CURSOR_END
0011    EE                        OUT       DX, AL        ; Выбор регистра конца курсора
0012    42                        INC       DX
0013    B0 04                     MOV       AL, 4
0015    EE                        OUT       DX, AL        ; Установка конца курсора
0016    B8 0002                   MOV       AX, 2
0019    CD 10                     INT       10H           ; Выбор символьного режима 80*25
001B    B8 ---- R                 MOV       AX, DISPLAY_BUFFER
001E    8E C0                     MOV       ES, AX        ; Адрес буфера дисплейной памяти
0020    B8 0720                   MOV       AX, 0720H     ; Вывод начинается с пробела
0023                     NEXT_CHAR:
0023    BF 0000                   MOV       DI, 0
0026    B9 0050                   MOV       CX, 80
0029    F3/ AB                    REP       STOSW         ; Вывод строки из 80 символов
002B    FE C0                     INC       AL            ; Следующий символ
002D    75 F4                     JNZ       NEXT_CHAR
002F    BB 0720                   MOV       BX, 0720H
0032                     NEXT_CHAR_1:
0032    B9 0050                   MOV       CX, 80
0035    BF 0000                   MOV       DI, 0
0038    BA 03DA                   MOV       DX, CRT_STATUS  ; Порт состояния для адаптера
                                                          ; цветного дисплея
003B                     WAIT_NO_RETRACE:
003B    EC                        IN        AL, DX        ; Проверка на обратный ход луча
003C    A8 01                     TEST      AL, 1
003E    75 FB                     JNZ       WAIT_NO_RETRACE  ; Запрещение прерываний
0040    FA                        CLI
0041                       WAIT_RETRACE:
0041    EC                        IN        AL, DX
0042    A8 01                     TEST      AL, 1
0044    74 FB                     JZ        WAIT_RETRACE  ; Ожидание обратного хода луча
0046    8B C3                     MOV       AX, BX        ; Выборка символа
0048    AB                        STOSW                   ; Занесение в дисплейный буфер
0049    FB                        STI                     ; Разрешение прерываний
004A    E2 EF                     LOOP      WAIT_NO_RETRACE
004C    FE C3                     INC       BL
004E    75 E2                     JNZ       NEXT_CHAR_1
                         ;-----   Фиг. 8.12 (в) Вывод линии по диагонали
0050    B8 0004                   MOV       AX, 4
0053    CD 10                     INT       10H           ; Установка графического 
                                                          ; режима 320*200 
0055    06                        PUSH      ES
0056    1F                        POP       DS
0057    B3 32                     MOV       BL, 50        ; Число групп строк
0059    B1 02                     MOV       CL, 2         ; Счетчик сдвига
005B    BF 0000                   MOV       DI, 0
005E                     DOT_LOOP:
005E    B0 C0                     MOV       AL, 0C0H      ; В AL маска первой точки в байте
0060    88 05                     MOV       [DI], AL
0062    81 C7 2000                ADD       DI, 2000H     ; Переключение на нечетную строку
0066    D2 E8                     SHR       AL, CL        ; Сдвиг до следующей точки в байте
0068    88 05                     MOV       [DI], AL
006A    81 EF 1FB0                SUB       DI, 2000H-80  ; Переключение на четную строку
006E    D2 E8                     SHR       AL, CL
0070    88 05                     MOV       [DI], AL
0072    81 C7 2000                ADD       DI, 2000H     ; Переключение на нечетную строку
0076    D2 E8                     SHR       AL, CL
0078    88 05                     MOV       [DI], AL
007A    81 EF 1FAF                SUB       DI, 2000H-81  ; Переключение на четную строку,
007E    FE CB                     DEC       BL            ; следующий байт
0080    75 DC                     JNZ       DOT_LOOP
                         ;-----   Возврат к символьному режиму 80*25
0082    B8 0002                   MOV       AX, 2
0085    CD 10                     INT       10H
0087    CB                        RET
0088                     COLOR_GRAPHICS    ENDP
0088                     CODE     ENDS
                         END

                                  Фиг. 8.12 Программа управления цветным дисплеем 

Цветной графический адаптер имеет еще три регистра ввода-вывода. Регистр режима находится по адресу ввода-вывода 03D8H. Этот регистр устанавливает аппаратные переключатели различных режимов отображения. Например, вы можете установить бит 5 этого регистра в "0" и получить 16 цветов фона в текстовых режимах, а установка бита 5 в "1" переключает 7-й бит атрибута на функцию мигания. Полное описание структуры этого регистра, и всех других, дано в техническом описании.

Регистр выбора цвета находится по адресу ввода-вывода 03D8H. Этот регистр устанавливает цвет окаймления в текстовых режимах. Поскольку сам по себе текст не занимает весь экран, текст можно окружить каким-либо выбираемым цветом. Кроме того, регистр выбора цвета может управлять выбором палитр в графических режимов, как мы увидим в следующем разделе. Младшие 4 бита этого регистра устанавливают для окаймления один из 16 цветов, перечисленных на Фиг. 8.10.

И наконец, регистр состояния по адресу ввода-вывода 3DAH организует информационную обратную связь между цветной платой и программой. Например, программа может использовать этот регистр для определения текущего состояния светового пера, если оно подключено к системе. Более важным является то, что регистр состояния сообщает, когда безопасно читать или записывать данные в дисплейный буфер.

Не вдаваясь в технические детали, заметим, что чтение или запись данных в буфер дисплея цветной платы может вызвать "снег" на экране, если вы будете это делать в неподходящие моменты времени. Это случается только в текстовом режиме с высоким разрешением 80*25. Вспомните, что ранее приводился пример на Фиг. 8.12, в котором постоянно записывались данные в буфер дисплея. Если для этого примера использовать цветную плату, на экране появится масса помех. Чтобы избежать этого, можно использовать регистр состояния.

Существуют моменты, когда можно безопасно работать с данными в буфере дисплея. В такие моменты бит 0 регистра состояния равен 1. Нужно подождать, когда бит 0 станет равным 1, а затем читать или записывать данные. На Фиг. 8.12б изображена программа, которая записывает символ на экран дисплея. Первые строки этой программы записывают данные в буфер, не используя регистр состояния. Эта часть программы 224 раза записывает 80 симвлов в первую строку буфера, что эквивалентно заполнению экрана около девяти раз. Когда вы запустите программу, то увидите короткую вспышку помех в тот момент, когда будут записываться данные.

Вторая часть программы на Фиг. 8.12б повторяет те же действия, но на этот раз проверяя бит состояния. Обратите внимание, что эта часть программы проверяет бит состояния двумя различными способами. Сначала она ждет, пока бит состояния не станет равным 0. Затем, как только он станет равен 1, программа записывает данные. Так сделано потому, что интервал, в течение которого можно записывать данные, очень мал, и если бы программа делала проверку только на равенство 1, она могла бы захватить бит состояния непосредственно перед его обращением в 0. В этом случае, чтобы избежать помех, микропроцессор уже не может записывать данные достаточно быстро, но такая организация цикла гарантирует, что бит состояния захватывается в первый же момент, когда он становится равным 1.

Используя бит состояния, вы уже не увидите на экране никаких помех, но и заметите, что выполнение программы стало гораздо медленнее. Выполняться медленнее программу заставляет дополнительное время, затрачиваемое на ожидание бита состояния. Если вам нужно записать на экране много данных - например, организовать горизонтальный сдвиг, как на Фиг. 8.8, то потребуется другой способ. Простейший способ - сбросить в нуль разряд отображения в регистре режима. Бит 3 регистра режима (3D8H) управляет отображением на дисплее. Если сбросить этот бит в 0, экран погаснет. Чтобы переслать многоданных в буфер цветного дисплея, вы можете выключить отображение и переслать данные без проверки бита состояния. Поскольку отображение выключено, на экране не возникнут помехи. Когда пересылка блока закончится, включите отображение. Вы заметите короткое мигание изображения в момент его выключения и включения. Фирма IBM использует этот метод для обслуживания вертикального сдвига цветного дисплея.