4.3.3. Прямая работа с видеопамятью
Все, что изображено на мониторе - и графика, и одновременно присутствует в памяти, встроенной в видеоадаптер. Чтобы изображение появилось на мониторе, оно должно быть записано в память видеоадаптера. Для этой цели отводится специальная область памяти, начинающаяся с абсолютного адреса 0B800h:0000h (для текстовых режимов) и заканчивающаяся OB800h:OFFFFh. Все, что программы пишут в эту область памяти, немедленно пересылается в память видеоадаптера. В текстовых режимах для хранения каждого изображенного символа используются два байта: байт с ASCII-кодом символа и байт с его атрибутом, так что по адресу лежит байт с кодом находящимся в верхнем левом углу экрана; по адресу OB800h:0001h расположен атрибут этого символа; по адресу OB800h:0002h - код второго символа в верхней строке экрана и т. д.
Таким образом, любая программа может вывести текст на экран простой командой пересылки данных, не прибегая ни к каким специальным функциям DOS или BIOS.
dirout.asm
Выводит на экран все ASCII-символы используя прямой вывод на экран.
без исключения,
start:
.model |
tiny |
|
. code |
|
|
.386 |
|
Будет использоваться регистр ЕАХ |
|
|
и команда STOSD. |
org |
100h |
Начало СОМ-файла. |
mov |
ax,0003h |
|
int |
10h |
Видеорежим 3 (очистка экрана). |
eld |
|
Обработка строк в прямом направлении. |
|
|
Подготовка данных для вывода на экран: |
mov |
eax,1F201F00h |
первый символ 00 с атрибутом 1Рп, |
|
|
затем пробел (2011) с атрибутом Ш |
mov |
bx,OF20h |
Пробел с атрибутом ОРИ. |
mov |
cx,255 |
Число символов минус 1. |
mov |
ctable |
Е5:01 : начало таблицы. |
Основы программирования для
cloop:
stosd
inc test
jnz
push
mov
x'chg
rep
xchg pop
continue_loop:
loop
al
cx.OFh
continue_loop
CX
cx,80-32
ax, bx
stosw
bx,ax cx
cloop
stosd
собственно вывод на экран
Записать символ и пробел в таблицу ссаЫе. АЬ содержит следующий символ.
Если СХ не кратен 16, продолжить цикл.
Иначе: сохранить значение счетчика.
Число оставшихся до конца строки символов.
Заполнить остаток строки пробелами : .
с атрибутом (№. Восстановить значение ЕАХ. Восстановить значение счетчика.
Записать последний (256-й) символ и
mov |
ax,OB800ri |
Сегментный адрес видеопамяти. |
mov |
es.ax |
|
хог |
di.di |
DI = 0, адрес начала видеопамяти в ES:DI; |
mov |
si,offset ctable |
Адрес таблицы в DS:SI. |
mov |
cx,15*80+32 |
15 строк по В0 символов, последняя строка - 32. |
rep |
movsw |
Скопировать таблицу ctable в видеопамять. |
ret |
|
Завершение СОМ-файла. |
|
|
Данные для вывода на экран начинаются сразу |
|
|
за концом файла. В ЕХЕ-файле такие данные^ |
|
|
определяют в сегменте |
end |
start |
|
ctable:
В указанной программе при подготовке данных для копирования в видеопамять учитывалось следующее: в архитектуре Intel при записи слова (или двойного слова) в память старший байт располагается по старшему адресу. Так что при записи в память двойного слова сначала записывается самый младший байт 00h (ASCII-код текущего символа), потом lFh, используемый в этом примере атрибут, далее 20h (код пробела) и лишь затем, по самому адресу, - самый старший байт, lFh, атрибут для этого пробела. Кроме того, в данном примере использовались некоторые 32-битные команды (MOV и STOSD). Ими можно пользоваться из 16-битной программы (разумеется, если процессор 80386 и выше), но не стоит этим злоупотреблять, потому что каждая из команд оказывается длиннее на 1 байт и выполняется дольше на 1 такт.