Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lec_12_pres.doc
Скачиваний:
3
Добавлен:
05.12.2018
Размер:
246.27 Кб
Скачать

4. Безпосереднє програмування відеопам'яті

Безпосереднє звертання до відеопам'яті комп'ютера є не тільки найшвидшим способом виведення інформації на екран у текстових режимах роботи відеосистеми, а й надає програмістові додаткові можливості для формування та опрацювання текстових повідомлень. Зокрема, саме таким способом (або через BIOS-переривання) можна:

  • зчитати символ і/або його атрибути із заданої позиції екрана;

  • змінити виведені на екран символи і/або їх атрибути;

  • вивести символ у правій нижній позиції екрана або текстового вікна, уникнувши скролінга;

  • записати і/або зчитати текстову інформацію з ненульової сторінки відеопам'яті.

Стандартним текстовим режимом, який автоматично встановлюється для відеоадаптерів VGA та SVGA, є режим номер 3 (25 рядків по 80 символів, 16-кольорів). Вся інформація, що виводиться на екран, зберігається у спеціальній області оперативної пам'яті, яка називається відеопам'яттю. Кожен символ займає у відеопам'яті два байти: у молодшому байті зберігається код, а в старшому - атрибути даного символа (колір фону, колір і яскравість символа, прапорець блимання). Байт коду символа завжди записується у відеопам'ять за парною адресою, а байт атрибутів - за непарною (рис. 3).

ASCII-код символа

Атрибути символа

парний байт непарний байт

Адреси відеопам'яті

Рис. 3. Розташування символів у відеопам'яті

Відеопам'ять текстових режимів входить у загальний адресний простір центрального мікропроцесора. Початок відеопам'яті для всіх кольорових відеоадаптерів має однакову адресу B800:0000h, а для монохромних відеоадаптерів - B000:0000h.

Всю відеопам'ять текстових режимів поділено на 8 сторінок, які пронумеровано від 0 до 7. У режимі 25x80 символів обсяг відеосторінки становить 4 Кбайт (4096 байтів). У кожен момент часу на екрані може відображатись тільки одна сторінка, стандартно активною є нульова сторінка відеопам'яті.

Оскільки сторінки відеопам'яті мають фіксовані адреси, то можна безпосередньо звертатись до кожного байта екранного зображення. Зміна значень байтів, що потрапляють у межі активної відеосторінки, відразу ж відображається у відповідній зміні символів і/або атрибутів текстових повідомлень на екрані.

Для звертання до відеопам'яті використовують або far-вказівники (як це було зроблено в функції PutLastScrSmb (), наведеній у попередньому пункті), або спеціальні короткі _es-вказівники (приклади подамо далі). За сегментний компонент адреси здебільшого приймають адресу початку відеопам'яті (BSOOh для кольорових відеоадаптерів), а зміщення обчислюють за координатами символа на екрані з урахуванням номера відеосторінки:

зміщення = ((рядок -1)*80 + (позиція -1) )*2 + сторінка* 4096

Першою запишемо функцію, яка повертає код і атрибути символа, що висвітлюється у позиції col екранного рядка row і зберігається на нульовій сторінці відеопам'яті.

/* Функція зчитування символа зі заданої позиції екрана */

#include <dos.h>

unsigned GetScrSymbol (int row, int col)

{

unsigned far * addr = (unsigned far*)MK_FP(Oxb800, 0);

addr += (row-1) *80+(col-1); /* адреса символа у відеопам'яті */

return (*addr); /* повертає код і атрибути символа */

}

Для звертання до двобайтових слів відеопам'яті у функції GetScrSymbol () використано довгий вказівник addr. Початково addr отримує адресу першого байта відеопам'яті - ця адреса формується за допомогою бібліотечного макроса MK_FP (), а потім встановлюється на задане знакомісце.

Значенням виразу *addr є числове дане з типом unsigned, у молодшому байті якого записано ASCII-код символа, а в старшому -його атрибути.

Байти коду та атрибутів символа можна легко виділити зі значення, яке повертає функція, використовуючи порозрядні операції. Наприклад:

unsigned int scr_symb, code, attr;

scr_symb=GetScrSymbol(symy, symx);

code = scr_symb & 0xff; /* код символа */

attr = scr_symb >> 8; /* атрибути символа */

Вищої швидкодії звертання до відеопам'яті можна досягти, застосовуючи спеціальні near-вказівники: char _es* та unsigned _es*. Перший з них використовують для побайтової роботи з відеопам'яттю, а другий - у разі запису/зчитування цілих слів.

Нагадаємо, що ці вказівники зберігають тільки зміщення адреси символа, а сегментну частину адреси перед звертанням до відеопам'яті треба занести в системний регістр ES.

Записана далі функція Invert () візуально виділяє задану частину рядка екрана, інвертуючи двійкові коди атрибутів символів. Параметри х1 та х2 задають номери початкового та кінцевого символів ділянки інвертування у рядку r. Просування по байтах атрибутів у функції Invert () здійснюється через вказівник patr, що має тип char _es * і зберігає зміщення адрес.

/* Функція інвертування атрибутів символів рядка */

void Invert (int r, int x1, int x2)

{

char _es *patr=(char _es*) (((r-l)*80+x1-l)*2+l) ;

_es = 0xb800; /* сегментна частина адрес */

while (x1++ <= x2) {

*patr = ~ *patr; /* інвертування байта атрибутів */

patr += 2;

}

}

Наступна функція ScreenCopy () виконує копіювання цілої відеосторінки (точніше, видимої на екрані частини). Сторінка, номер якої задається параметром from_page, переписується на іншу відеосторінку, що має номер to_page. Фактично функція копіює масив обсягом 25x80x2 байт, тому для неї питання швидкодії є особливо важливими.

Оскільки сегментна частина адрес двобайтового слова, що копіюється, та ділянки, в яку воно записується, однакова (це адреса сегмента відеопам'яті), то найбільш ефективним способом адресації даних буде використання двох коротких _es-вказівників pfrom та pto.

/* Функція копіювання відеосторінки */

void ScreenCopy(int from_page, int to_page)

{

unsigned _es *pfrom = (unsigned _es *)(from_page*4096);

unsigned _es *pto = (unsigned _es *)(to_page*4096);

int n; /* номер символа, що копіюється */

_ES = 0xbS00; /* сегмент адрес */

for (n=0; n< 25*80; n++, pfrom++, pto++)

*pto = *pfrom; /* копіювання символів з атрибутами */

}

За допомогою функції ScreenCopy () можна швидко зберегти поточне екранне зображення на вільній відеосторінці, а потім відновити його на екрані, активізувавши дану відеосторінку або повторно скопіювавши її на нульову сторінку відеопам'яті.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]