При выводе текста, для записи кодов символов в видеопамять, задача может использовать поддержку BIOS и DOS или делать это самостоятельно. Мы опишем оба способа вывода текста на экран, но предварительно обсудим общие особенности программирования работы с текстом.
Из личного опыта работы с компьютером вы знаете, что символы и окружающий их фон могут иметь разные цвета. Например, после загрузки DOS текстовые сообщения выводятся белыми символами на черном фоне, а на обеих панелях оболочки Norton commander фон имеет синий цвет (если разрешена работа с цветом). Таблицы шрифтов не содержат никакой информации о цветах символов и фона, их формирует задача в процессе вывода текста. Покажем, как это делается.
Атрибуты символов предназначены для раскрашивания выводимого на экран текста. В видеопамяти код атрибута располагается после кода символа, т. е. четные байты видеопамяти содержат коды символов, а нечетные — коды их атрибутов. Если слово видеопамяти прочитать в один из регистрон общего назначения, например в ах, то код символа окажется в младшем байте регистра (аx), а код атрибута — в старшем байте (ah).
Для размещения символа на экране всегда выделяется прямоугольная область, которую в литературе принято называть "знакоместо". Размер знакоместа (количество точек по горизонтали и вертикали) зависит от видеорежима. Для стандартных текстовых режимов его размеры составляют 8x8, 8x14 или 8x16 точек. Собственно изображение символа занимает часть знакоместа, в англоязычной документации ее принято называть передним планом (foreground). Свободная часть знакоместа, не занятая рисунком символа, называется задним планом (background), мы будем называть ее фоном. Например, изображение символа "пробел" состоит только из фона.
Байт атрибута рассматривается как три группы независимых разрядов. Младшая тетрада (разряды 0—3) содержит код цвета точек изображения символа (foreground). Следующие три разряда (4—6) содержат код цвета фона (background). Старший (седьмой) разряд байта атрибута управляет миганием точек символа (foreground flashes). Его установка разрешает, а очистка запрещает мигание символа на экране.
Коды цветов точек изображения символа могут принимать значения от о до F, а фона от о до 7. Если задача не изменяла установленную по умолчанию палитру, то указанным кодам соответствуют цвета стандартной палитры CGA (см. табл. 4.2). Следовательно, точки фона могут иметь следующие цвета: черный, синий, зеленый, циан, красный, фиолетовый, коричневый или белый. Для раскрашивания точек символа можно дополнительно использовать цвета второй половины табл. 4.2.
Вы можете выбрать другие цвета для раскраски изображения символов и фона, для этого задача должна установить собственную палитру в 16-ти младших регистрах цвета видеокарты. Способы установки палитры не зависят от видеорежима. Используемые для этого функции BIOS описаны в предыдущей главе.
На практике наиболее часто используются атрибуты, имеющие следующие коды:
В процессе загрузки ПК BIOS заполняет видеобуфер кодами символа "пробел" (20h) и кодами атрибутов 07, поэтому мы видим белые символы на черном фоне.
Таким образом, для раскрашивания выводимого текста вы должны выбрать подходящие коды атрибутов и предусмотреть их запись в видеопамять после кодов символов, к которым они относятся. Если задача записывает в видеопамять только коды символов, то сохраняются те значения атрибутов, которые уже находятся в нечетных байтах.
Управление текстовым курсором. Текстовый курсор — это мигающий символ прямоугольной формы, формируемый видеоконтроллером при работе в текстовых режимах. После загрузки DOS он имеет форму горизонтальной черты, расположенной в двух нижних строчках знакоместа, в которое будет помещен очередной введенный символ. Прикладные задачи могут изменять количество строк в изображении курсора и их расположение в прямоугольнике, но ширину курсора изменить невозможно, она зависит от установленного видеорежима. Кроме того, задачи могут гасить (выключать) курсор, но не могут изменить частоту его миганий.
В соответствии со стандартом VGA IBM в состав видеоконтроллера входят четыре однобайтовых регистра, содержащие следующие характеристики курсора:
Доступ к этим регистрам производится через порт с адресом 3D4h, если монитор цветной, или с адресом 3B4h, если монитор черно-белый.
В регистрах 10 и И номер строки располагается в 5-ти младших разрядах (0—4) и может изменяться от 0 до 31. Отсчет строк ведется сверху вниз. Если, например, высота символов равна 16-ти точкам (стандартная для VGA) и рисунок курсора занимает две последние строчки прямоугольника, то в регистрах 10 и 11 находятся коды ОЕb и OFh.
Вам не обязательно программировать работу с портами, хотя в данном случае это не сложно. Функция 01 прерывания int ioh предназначена для записи данных в регистры 10 и 11. Перед ее использованием в регистрах ch и d указываются номера первой и последней строк рисунка курсора. В регистр ah помещается код запроса (oi) и выполняется команда int ioh. При выполнении этой функции новая форма курсора запоминается в слове 0460 области данных BIOS (см. пример 5.3).
Расположение (позицию) курсора или символа на экране удобнее задавать не в виде адреса, а в виде номера строки и столбца, на пересечении которых он должен находиться. Если строки и столбцы пронумерованы начиная с нуля, то для вычисления адреса слова видеопамяти надо умножить номер строки на количество символов в строке и к произведению прибавить номер столбца. Если нужен номер байта (для записи кода символа), то полученный результат умножается на 2. Количество символов в строке является одной из характеристик видеорежима. BIOS сохраняет эту величину в своей области данных, и в нужных случаях ее используют функции прерывания int 10h. Эту величину можно прочитать из массива info, описанного в главе 2, или из слова 044Ah области данных BIOS (см. пример 5.3).
Задача может самостоятельно пересчитывать координаты в адрес и записывать его в регистры видеокарты (14 и 15). Однако если при выводе текста используется поддержка BIOS, то лучше обратиться к специальной функции 02 прерывания int lOh. Она не только выполняет указанные вычисления, но и сохраняет значения строки и столбца в одном из 8-ми слов, расположенных в области данных BIOS (см. пример 5.3). Сохраненные координаты курсора используются процедурами, выводящими текст на экран. Для вызова функции 02 код запроса (02) записывается в регистр ah, номера строки и столбца, на пересечении которых должен располагаться рисунок курсора указываются в регистрах dh и di, а в регистр bb помещается номер страницы видеопамяти, на которой располагается курсор (см. ниже). После этого выполняется команда int 10h.
Изображение курсора можно удалить с экрана тремя разными способами:
Для перемещения курсора за пределы рабочей области его помещают в строку, которая не выводится на экран, но этого лучше не делать по причинам, описанным ниже.
Текстовый курсор является самостоятельным рисунком, а его увязка с процессами ввода и вывода символов производится программно. При вводе и редактировании текста курсор нужен для привлечения внимания оператора. Он указывает позицию на экране, в которую будет помещен очередной символ при вводе с клавиатуры.
Если процесс вывода текста не связан с процессом ввода, то изменение позиции курсора на экране не несет никакой смысловой нагрузки. Он может указывать конец выведенной строки, но едва ли такая информация пригодится тому, кто читает выводимый текст.
Разработчики BIOS использовали курсор для указания позиции, в которую выводится каждый символ текста. Это значит, что при вызове процедур BIOS координаты выводимого символа не указываются явно. В качестве координат процедуры используют текущую позицию курсора, сохраняемую в области данных BIOS. Если же курсор был перемещен за пределы рабочей области, то и выводимый текст окажется там же и не будет виден.
Сейчас трудно судить, почему был выбран такой способ позиционирования при выводе текста. Возможно, в свое время, это решение было оправдано, но постепенно оно превратилось в серьезное препятствие, ограничивающее возможности применения поддержки BIOS.