Глава 4. Вывод на терминал.

Раздел 3. Вывод символов на экран.

4.3.4 Создание специальных символов.

Только монохромный адаптор не может выводить символы вида, заданного самим программистом. Цветной адаптор позволяет 128 символов, определяемых пользователем, PCjr - 256, а EGA - 1024 из которых одновременно доступно 512. Для цветного адаптора ROM-BIOS содержит данные для разрисовки только первых 128 символов набора ASCII (с номерами от 0 до 127). Следующие 128 символов недоступны для Вас, пока Вы не создатите их, используя описанную здесь технику. Отметим, что MS DOS 3.00 предоставляет команду GRAFTABL, которая предоставляет требуемые данные для второй порции из 128 символов. EGA имеет полные наборы символов для режимов с 200 строками и с 350 строками.

Символы для графического адаптора и PCjr описываются с помощью матрицы 8*8 точек. Данные для каждого символа содержатся в восьми байтах. Kаждый байт содержит установку для точек одного ряда, начиная с верхнего ряда, причем старший бит (номер 7) соответствует самой левой точке в ряду. Kогда соответствующий бит равен 1, то точка высвечивается. Для описания символа Вы должны определить правильные последовательности битов для восьми байтов и поместить их в последовательные ячейки памяти. Hа рис. 4-3 показано как 8 байтов описывают бубновую масть.

Все 128 символов вместе требуют 1024 байта, хотя вовсе не требуется, чтобы были описаны все символы. Специальный вектор прерывания (постоянный указатель в младших адресах памяти {1.2.0}) указывает на адрес первого байта первого символа расширенного набора, т.е. на символ номер 128. Kогда в позицию символа в видеобуфере посылается код 128, то просматриваются и выводятся первые восемь байт. Если номер символа 129, то выводятся байты с девятого по шестнадцатый, и т.д.

Hомер этого вектора прерывания 1FH и он расположен по адресу 0000:007C. Поместите значение смещения в младшее слово (сначала младший байт), а адрес сегмента - в старшее слово (снова, сначала младший байт). Отметим, что можно символы с большими номерами кодов, не отводя памяти для символов с меньшими номерами; надо просто чтобы вектор указывал на некоторый адрес, который меньше, чем адрес начала блока, содержащего данные для описания символов. Восьмибайтные последовательности, описывающие символы ASCII с кодами 128-255 приведены в {4.3.5}. У PCjr вектор 1FH указывает на вторые 128 символов ASCII, а вектор 44H - на первые. Оба этих вектора могут быть изменены, допуская полный набор 256 символов, определяемых пользователем.

Для EGA картина намного сложнее, но и намного гибче. При инициализации текстового режима один из двух наборов символов (8*8 или 8*14) копируется из ПЗУ EGA в карту битов 2 видеобуфера. Эта часть буфера рассматривается как разбитая на блоки, причем стандартный набор символов помещается в блок 0. При условии, что EGA оснащен достаточной памятью могут быть определены еще три блока для описания символов. Размер блока определяется числом строк матрицы, используемой для описания символа. Символы, описываемые матрицей 8*8 требуют 8*256 или 2048 байт. Kогда разрешены более одного блока символов, то бит 3 байта атрибутов определяет из какого блока будут браться данные для описания символа.

Kакой из блоков будет использоваться зависит от установки битов 0-3 регистра выбора карты символов, адрес порта которого 3C5H. Предварительно надо послать 3 в порт 3C4H, чтобы указать требуемый регистр. Биты 1-0 дают номер блока символов, который берется когда бит 3 байта атрибутов равен 0, а биты 3-2 - делают то же самое, когда бит 3 равен 1. Kогда установка обоих пар битов совпадает, то возможность использования двух наборов символов отсутствует и бит 3 байта атрибутов переключается на установку интенсивности символа. В этом случае используется только блок 0. Однако никто не может помешать Вам поместить свои символы в любую нужную Вам позицию в этом блоке. Если Вы изменили стандартный набор символов, то Вы можете в любой момент восстановить его из ПЗУ.

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

Для цветного адаптора и PCjr используйте функцию 25H прерывания 21H для изменения вектора прерывания 1FH. При входе DS:DX должны указывать на первый байт блока данных. Более подробное описание см. в {1.2.3}. В примере создаются два символа с номерами 128 и 129. Они являются зеркальными отображениями друг друга, а выведенные подряд образуют небольшой прямоугольник.
;---в сегменте данных
CHARACTER_DATA DB 11111111B, 10000000B, 10000000B, 10000000B
DB 10000000B, 10000000B, 10000000B, 11111111B
DB 11111111B, 00000001B, 00000001B, 00000001B
DB 00000001B, 00000001B, 00000001B, 11111111B
;---установка вектора прерывания
PUSH DS ;сохраняем DS
LEA DX,CHAR_DATA ;смещение для данных в DX
MOV AX,SEG CHAR_DATA ;сегмент для данных в DS
MOV DS,AX ;
MOV AH,25H ;функция установки вектора
MOV AL,1FH ;номер изменяемого вектора
INT 21H ;установка вектора
POP DS ;восстанавливаем DS
;---печать символов
MOV AH,2 ;номер функции
MOV DL,128 ;первый символ
INT 21H ;вывод его
MOV DL,129 ;второй символ
INT 21H ;вывод его

Для EGA функция 11H прерывания 10H манипулирует набором символов. Эта функция может быть очень сложной, когда она используется для создания специальных режимов экрана, но ее основное применение достаточно простое. Имеется четыре подфункции. Kогда AL равен 0, то данные, определяемые пользователем переносятся из памяти в специальный блок символов. Kогда AL равен 1 или 2, то наборы данных для символов 8*14 и 8*8 соответственно копируются из ПЗУ в блок символов. Kогда AL равен 3, то функция устанавливает назначение блока в регистре выбора карты символов, как описано выше. В последнем случае надо просто поместить соотвествующие данные в BL и вызвать функцию. Для загрузки данных из ПЗУ поместите номер блока в BL и выполните функцию. Для загрузки своих данных надо чтобы ES:BP указывали на них, число передаваемых символов должно быть в CX, смещение (номер символа) в блоке должно быть в DX, число байтов на символ - в BH, а номер блока - в BL. После этого вызывайте прерывание 10H. Вот пример:
;---устанавливаем 128 пользовательских символов в блоке 0
MOV AX,SEG CHARACTER_DATA ;ES:BP должны указывать на данные
MOV ES,AX ;
MOV BP,OFFSET CHARACTER_DATA ;
MOV CX,128 ;число символов
MOV DX,128 ;начальное смещение
MOV BL,0 ;номер блока
MOV BH,8 ;матрица 8*8
MOV AL,1 ;номер подфункции
MOV AH,11H ;номер функции
INT 10H ;переносим данные


<~-4.3.3 Чтение символа и его атрибутов в данной позиции.
Содержание
4.3.5 Сводка данных для описания символов.-~>

Сайт управляется системой uCoz