Графические устройства

         

Общая характеристика процесса вывода текста

При выводе текста, для записи кодов символов в видеопамять, задача может использовать поддержку 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 описаны в предыдущей главе.

На практике наиболее часто используются атрибуты, имеющие следующие коды:

  • 07 — белые символы на черном фоне;
  • OF — яркие белые символы на черном фоне;
  • IF — яркие белые символы на голубом фоне.

В процессе загрузки ПК BIOS заполняет видеобуфер кодами символа "пробел" (20h) и кодами атрибутов 07, поэтому мы видим белые символы на черном фоне.

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

Управление текстовым курсором. Текстовый курсор — это мигающий символ прямоугольной формы, формируемый видеоконтроллером при работе в текстовых режимах. После загрузки DOS он имеет форму горизонтальной черты, расположенной в двух нижних строчках знакоместа, в которое будет помещен очередной введенный символ. Прикладные задачи могут изменять количество строк в изображении курсора и их расположение в прямоугольнике, но ширину курсора изменить невозможно, она зависит от установленного видеорежима. Кроме того, задачи могут гасить (выключать) курсор, но не могут изменить частоту его миганий.

В соответствии со стандартом VGA IBM в состав видеоконтроллера входят четыре однобайтовых регистра, содержащие следующие характеристики курсора:

  • регистр 10 (0АЬ) — первая строка рисунка курсора в прямоугольнике;
  • регистр 11 (0Bh) — последняя строка рисунка курсора в прямоугольнике;
  • регистр 14 (0Еh) — старший байт адреса курсора в видеопамяти;
  • регистр 15 (0Fh) — младший байт адреса курсора в видеопамяти.

Доступ к этим регистрам производится через порт с адресом 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.

Изображение курсора можно удалить с экрана тремя разными способами:

  1. 1. Запретить его вывод, указав в регистре 10 код 20h.
  2. 2. Записать в регистр 10 код равный высоте символов.
  3. 3. Переместить рисунок курсора за пределы рабочей области экрана.

Для перемещения курсора за пределы рабочей области его помещают в строку, которая не выводится на экран, но этого лучше не делать по причинам, описанным ниже.

Текстовый курсор является самостоятельным рисунком, а его увязка с процессами ввода и вывода символов производится программно. При вводе и редактировании текста курсор нужен для привлечения внимания оператора. Он указывает позицию на экране, в которую будет помещен очередной символ при вводе с клавиатуры.
Если процесс вывода текста не связан с процессом ввода, то изменение позиции курсора на экране не несет никакой смысловой нагрузки. Он может указывать конец выведенной строки, но едва ли такая информация пригодится тому, кто читает выводимый текст.

Разработчики BIOS использовали курсор для указания позиции, в которую выводится каждый символ текста. Это значит, что при вызове процедур BIOS координаты выводимого символа не указываются явно. В качестве координат процедуры используют текущую позицию курсора, сохраняемую в области данных BIOS. Если же курсор был перемещен за пределы рабочей области, то и выводимый текст окажется там же и не будет виден.

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

Страницы видеопамяти.

Если не принять специальные меры, то в текстовых режимах задача работает только с младшей частью сегмента видеопамяти, размер которой зависит от установленного видеорежнма. Для доступа ко всему пространству видеобуфера оно делится на страницы, которые могут использоваться независимо друг от друга.

Создание страниц и их отображение на экране при работе в графических режимах VESA обсуждалось в разделе . В текстовых режимах (неважно IBM или VESA) страницы располагаются в одном сегменте видеопамяти, что существенно упрощает их создание и отображение на экране.

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

При установке текстовых видеорежимов BIOS вычисляет необходимый для работы объем видеопамяти. Если режим позволяет выводить на экран м строк, содержащих по N символов каждая, то для хранения кодов символов вместе с атрибутами требуется M*N*2 байта видеопамяти. Для определения размера страницы это произведение увеличивается до ближайшего значения, кратного числу 4096, и сохраняется в слове 044Ch области данных BIOS. В зависимости от видеорежима страница может занимать 4096, 8192 или 16384 байта. Соответственно, в сегменте видеопамяти может располагаться 16, 8 или 4 страницы.

Для хранения позиции курсора на каждой странице в области данных BIOS (см. пример 5.3) выделяется слово, содержащее номер строки (старший байт) и столбца (младший байт), на пересечении которых он расположен. Всего в области данных зарезервировано восемь слов, в соответствии с количеством страниц, поддерживаемых BIOS. В исходном состоянии эти слова очищены, что соответствует расположению курсора в начале каждой страницы.

Номер страницы указывается при вызове всех функций прерывания int 10h, выполняющих вывод символов или строк, но фактически функции 09, ОАЬ и ОЕb прерывания int 10h размещают выводимые символы на нулевой странице. Реально номер страницы использует только функция I3h. По нему она определяет текущее положение курсора на странице и пересчитывает его в относительный адрес (адрес на странице). Затем номер страницы умножается на ее размер и получается смещение начала страницы в видеобуфере. Сумма этих двух величин и является адресом, начиная с которого записываются выводимые символы.

Страница является активной, если ее содержимое отображается на экране. В соответствии со стандартом VGA IBM в состав видеоконтроллера входят два однобайтовых регистра, содержащих адрес видеопамяти, начиная с которого ее содержимое выводится на экран. В регистре 12 (ось) хранится старший байт этого адреса, а в регистре 13 (ось) — младший. Доступ к этим регистрам осуществляется через порт 3D4h, если монитор цветной, или 3B4h, если он черно-белый.

После включения или перезагрузки компьютера BIOS очищает указанные регистры, поэтому активной является нулевая страница, расположенная в начале сегмента видеобуфера. Для изменения отображаемой области надо записать в регистры 12 и 13 новый адрес видеопамяти.

Задача может самостоятельно изменять адрес начала отображаемой области, но если при выводе текста используется поддержка BIOS, то для смены активной страницы лучше вызывать функцию 05 прерывания int 10h. Перед ее вызовом в регистре ai указывается номер новой активной страницы, а в регистре ah — код 05. Эта функция извлекает размер страницы из слова 044сь области данных BIOS, умножает его на указанный номер и результат помещает в регистры 12 и 13. На экране появляется содержимое новой страницы. Кроме того, функция записывает в слово 044Eh (пример 5.3) смещение активной страницы от начала сегмента видеобуфера.

Фрагмент области данных BIOS

При общей характеристике BIOS в разделе говорилось, что ее процедуры используют пространство оперативной памяти, называемое областью данных BIOS. Оно расположено в нулевом сегменте оперативной памяти ПК, начиная с адреса 400h. В частности, при выводе символов на экран функции прерывания int 10h используют следующие слова и байты, расположенные в области данных.

Пример 5.3. Фрагмент области данных BIOS

0000: 0449 - (байт) установленный видеорежим;
0000: 044А - (слово) количество столбцов (размер строки) ;
0000: 044С - (слово) размер страницы в байтах;
0000: 044Е - (слово) смещение активной страницы от начала видеобуфера;
0000: 0450 - (8 слов) позиции курсора на восьми страницах видеопамяти;
0000: 0460 - (слово) номера первой и последней строк рисунка курсора;
0000: 0462 - (байт) номер активной страницы;
0000: 0463 - (байт) базовый адрес видеоконтроллера (3D4h или 3B4h) ;
0000: 0484 - (байт) номер последней строки на экране;
0000: 0485 - (слово) размер рисунка символа в байтах.

Перечисленные в этом примере величины могут пригодиться в тех случаях, когда вы программируете вывод текста без использования функций BIOS.


Содержание раздела