Непосредственная работа с экранной памятью
В качестве примера использования указателей различных типов рассмотрим ряд функций, предназначенных для вывода текстовой информации непосредственно в экранную память компьютера. Эти функции работают быстрее соответствующих функций из стандартных библиотек.
Рассмотрим принцип организации экранной памяти для вывода информации на экран в текстовом режиме. Каждому знакоместу экрана соответствует слово памяти (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; /* Переход к следующему атрибуту */
}
}
Рассмотренную функцию можно использовать для организации всякого рода световых меню.
Дата добавления: 2015-02-13; просмотров: 667;