числяться медленно. Ее можно упростить, если ввести такое по-
нятие, как размер скан-линии. Скан-линия — это, по сути, стро-
ка изображения во всю ширину экрана. Для удобства при уста-
новке видеорежима можно в поле S creen.B ytesP erS canline
записать размер скан-линии в байтах, вычисляемый по форму-
ле: BytesPerScanline=uiHpHHa*LiBeTHOCTb или загрузить из поля Mod-
e ln fо . B ytesP erS canline, где в запись M odelnfо предваритель-
но будут получены характеристики соответствующего режима.
Теперь формула будет выглядеть как a flpec= Y *B ytesP erS canline+
Х*цветность, где произведение Х*цветность впоследствии можно
упростить до элементарного битового сдвига.
Так, для режима 320x200x8 бит все весьма просто: ад-
pec=Y *320+X *8/8=Y *320+X . По такому адресу уже можно
заносить байт цвета точки. При этом, если координаты точ-
ки лежат в пределах (0.
.319;0.
.199), то ее адрес всегда ле-
жит в пределах видеобуфера размером в 64 Кб, а значит,
сдвигать видеобуфер нет необходимости. Следующие две
подпрограммы представляют сабой оптимизированный код
для рисования точек на 8-битный экран 320x200. Процеду-
ра P u tP ix e l8 B its V g a выводит точку (записывает) цветом
C o lo r на экран в позицию координат (X ;Y ):
p ro c e d u re P u tP ix e l8 B its V g a ( X , Y : w o rd ; C o lo r :
T C o lo r ) ; a s s e m b le r;
asm
m o v d i,x ; m o v a x .y ; s h l a x ,2 {AX=Y*4}
mov s i, a x {S I= Y *4 > ; s h l a x ,2 {AX=Y*16}
add a x , s i {AX =Y *16+Y*4=Y*(1 6 + 4 )= Y *20}
add ax,O A000h; mov e s , a x ; mov a l. b y t e p t r c o lo r
mov e s : [ d i] , a l
end;
Думаю, следует расшифровать данный ассемблерный код.
Для оптимальной работы с параметрами величины х и
y
за-
гружаются в регистры
d i и а х процессора соответственно.
Далее необходимо величину Y помножить на 320, та бишь
на размер скан-линии. Для умножения можно использовать
ассемблерную команду миь, но поскольку она работает мед-
ленно, можно применить ряд манипуляций с битовым сдви-
гом влево, чтобы осуществить эквивалентное умножение
на 320. А чтобы количество таких сдвигов свести к миниму-
му, можно выполнить вычисление адреса не в байтах, а в
16-байтных параграфах, что потребует умножить Y всего
лишь на 20, так как 16*20=320. После выполнения битовых
сдвигов в регистре
а х будет получен адрес точки в парагра-
фах относительно начала видеобуфера. Добавив к адресу
точки адрес видеобуфера командой add ax,0A000h, полу-
чим полный адрес тачки в параграфах в регистре
а х После
чего адрес загружается в сегментный регистр ES. Командой
mov a l ,b y te p t r c o lo r цвет точки загружается в регистр AL,
и точка выводится на экран командой m ove s: [ d i] , a l
Безусловно, при работе с изображением может понадо-
биться функция G e tP ix e l8 B its V g a , которая выполняет об-
ратное действие, то есть читает цвет точки с координатами
(X;Y) с экрана. Вычисление адреса выполняется аналогичным
образом. При этом командами x o r d x ,d x n хо га х,а хд л я
корректности осуществляется инициализация 4-байтного зна-
чения цвета, после чего в младший байт
a l цвета заносится
считываемое значение.
fu n c tio n G e tP ix e l8 B its V g a ( X, Y : w ord ) : T C o lo r; a s-
se m b le r;
asm
mov d i, x ; mov s i , y ; s h l s i ,2 ; mov a x , s i ; s h l a x ,2
add a x , s i; add ax,OAOOOh; m o v e s ,a x ; x o r d x ,d x
x o r a x ,a x ; mov a l, e s : [ d i]
end;
Иначе обстоит дело с режимами 640x400, 640x480,
800x600 и т д., где значение адреса может превысить 64 Кб.
Как раз тут возникает необходимость вычислять номер стра-
ницы, на которую следует позиционировать видеобуфер. Ес-
ли ан уже установлен на требуемую страницу, то переме-
щать его не нужно. Так, пока видеобуфер находится на нуж-
ной странице, можно выполнять ряд операций с ее точками
и с точками последующих страниц, которые еще умещают-
ся в видеобуфере. Таким образом, для точек, находящихся в
пределах видеопамяти, отображенной в видеобуфере, опе-
рацию перемещения видеобуфера делать не понадобится.
Как же вычислить номер тай самой страницы? Это не очень
сложна. Поскольку значение адреса может получиться в пре-
делах типа Longint, то есть 4 байт, достаточно взять от него
старшее слово, в котором будет количество сегментов по
64 Кб. Затем это количество сдвигаем влево на величину
G r a n u lS h ift, после чего получим номер необходимой стра-
ницы, на которую должен быть позиционирован видеобуфер.
Что есть G ra n u lS h ift? Это размер битового сдвига влево,
эквивалентного умножению на количество страниц в 64 Кб.
Откуда взялась величина G ra n u lS h ift? Она получается при
помощи вспомогательной функции G e tG ra n u lS h ift каждый
раз при установке режима. Стало быть, если гранулярность
видеопамяти 64 Кб, та размер сдвига будет 0, что приводит
очередные 64 Кб адреса в соответствие очередной страни-
це в 64 Кб. При гранулярности 8 Кб размер сдвига будет
равен 3, что приводит очередные 64 Кб адреса в соответ-
ствие очередным 8 страницам (8*8 К б = 6 4 Кб).
Итак, для установки 8-битной точки на SVGA-экран со-
ставим процедуру P u tP ix e l8 B its V e s a :
p ro c e d u re P u tP ix e l8 B its V e s a ( X , Y : w o rd ; C o lo r :
T C o lo r ) ; a s s e m b le r;
asm
mov s i, X ; m o v b x ,Y ; mov a x ,S c re e n . B y te s P e rS c a n lin e
m ul bx [m u l Y } ; add a x , s i {add a x ,X ) ; a d c d x ,0
mov c x ,G r a n u lS h ift; s h ld x , c l; m o v d i.a x
mov ax.SegAOOO; mov e s ,a x ; cmp d x,L a stP a g e
je @a
mov L a s tP a g e ,d x ; mov a x ,4 f0 5 h ; x o r b x ,b x ; i n t 10h
@a: mov a l,b y te p t r C o lo r; mov e s : [ d i] , a l
end;
где величины X и Y заносятся в регистры S i и ВХ. Размер скан-
линии — в регистре
а х . В данном случае все же пришлось
прибегнуть к применению команды MOL, чтобы Y умножить на
размер скан-линии. При этом физика этого умножения тако-
ва, чта ей эквивалентна формула
d x :AX=a x * b x — та есть ум-
ножение двухбайтных регистров
а х и в х естественно может
привести к переполнению двухбайтного результата. Поэтому
процессор заносит результат умножения в регистровую па-
ру DX:AX, обеспечивая 32-битный результат. Далее к полу-
ченному произведению добавляется X командой add a x ,s i,
что в свою очередь тоже может привести к переполнению ре-
гистра
а х , который получит результат сложения. В случае пе-
реполнения флаг переноса
c f установится в единицу. Чтобы
при получении полного линейного адреса точки учесть пере-
полнение, далее следует ввести команду ade d x ,0 , которая,
прибавляя нуль к регистру DX адреса точки, также прибавля-
ет единицу флага переноса, если он установлен. Таким об-
разам, оперируя 16-битными регистрами, получаем 32-бит-
ный адрес тачки, где регистр
dx содержит количество стра-
ниц по 64 Кб. Остается лишь умножить его при помощи ло-
гического сдвига s h l d x ,c l, чтобы получить номер искомой
страницы видеопамяти, на которую следует позиционировать
видеобуфер. Младшие 16 бит адреса точки регистра
а х пред-
ставляют собой смещение в байтах относительно сегмента
$ОАООО видеобуфера, которые помещаем в регистр d i .
Командой cmp d x.L a stP a g e сравниваем искомую страни-
цу с текущей, и если они не равны, то командой mov L a s t-
Page, dx искомую страницу делаем текущей. Командами mov
a x ,4 f 05h, x o r b x ,b x и i n t 10h заставляем BIOS отобразить
в видеобуфере новую страницу видеопамяти экрана. Затем
командами mov a l ,b y te p t r C o lo r и mov e s : [ d i] , a l рису-
ем точку. Если искомая и текущая страницы равны, то коман-
ду вызова функции BIOS пропускаем, переходя по метке @а.
Функция G e tP ix e l8 B its V e s a для чтения цвета точки име-
ет практически тот же код, за исключением концовки, кото-
рая содержит команды для инициализации 32-битного цвета
точки и читает значение лишь в младший байт результата,
fu n c tio n G e tP ix e l8 B its V e s a ( X , Y : w ord ) : T C o lo r;
a s s e m b le r;
asm
mov s i ,X
i n t 10h
^ О кончание на стр. 4 3
предыдущая страница 39 Мой Компьютер 2005 05 читать онлайн следующая страница 41 Мой Компьютер 2005 05 читать онлайн Домой Выключить/включить текст