Студенту >> Язык программирования Си


Работа с экранной памятью

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

Рассмотрим принцип организации экранной памяти для вывода информации на экран в текстовом режиме. Каждому знакоместу экрана соответствует слово памяти (2 байта). Младший байт содержит код символа, старший атрибут символа, устанавливающий его цвет. В свою очередь, атрибут символа в старших четырех битах содержит цвет фона (самый старший бит может устанавливать режим мигания), а в младших четырех битах - цвет символа. Вычислить атрибут символа, зная цвет фона - fon и цвет символа sym, можно по следующей формуле:

attr = fon * 16 + sym; 
или
attr = fon << 4 | sym; 

Таким образом, каждой строке экрана соответствует 160 байт экранной памяти. Экранная память начинается с адреса 0xB8000000L. Буква L в конце адресной константы необходима для того, чтобы компилятор создал константу длиной 4 байта.

Ниже приведен текст функции, выводящей строку символов, на которую указывает указатель str, начиная с колонки col из строки row экрана. При выводе строки используется атрибут attr.

void PutsXY (int col, int row, char *str, int attr)
{
     char far *p = (char far *) 0xB8000000L;
     p+= 160*(row-1)+2*(col-1); /* Начало строки */
     while (*str)
     {
            *(p++) = *(str++); /* Вывод символа */
            *(p++) = attr; /* Вывод атрибута */
     }
}

Единственное замечание, которое следует сделать, заключается в том, что для адресации экранной области памяти используется дальний (far) указатель на символы. Такой указатель необходимо использовать для того, чтобы независимо от того, в какой 16-разрядной модели памяти создается программа (даже в Tiny), была возможной адресация этой памяти.

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

void PutAttr (int col, int row, int len, int attr)
{
      char far *p = (char far *) 0xB8000000L;
      p+= 160*(row-1)+2*(col-1)+1;
      while (len--)
      {
              *p = attr; /* Вывод атрибута */
              p += 2; /* Переход к следующему атрибуту */
       }
}

Рассмотренную функцию можно использовать для организации всякого рода световых меню.

НАВЕРХ