Оптимизированные версии OpaqueBlt() и TransparentBlt()
Листинг 17.4 содержит оптимизированные ассемблерные версии подпрограмм OpaqueBlt() и TransparentBlt(), которые имеются и на дискете (BLIT.ASM). Эти подпрограммы можно использовать вместо соответствующих функций на Си, что увеличит быстродействие программы примерно на 30 процентов.
Демонстрационная программа PARAL использует ассемблерные версии этих подпрограмм. Они были написаны с тем расчетом, чтобы могли работать с процессором 286. Поскольку они заполняют буфер системной памяти, их можно оптимизировать и дальше, применив 32-битовые команды перемещения банных.
Листинг 17.4. Оптимизированная подпрограмма (BLIT.ASM).
ideal
model compact,с
p286
dataseg
VIEW_WIDTH equ 320
VIEW_HEIGHT equ 100
TRANSPARENT equ 0
global MemBuf:dword
.codeseg
public OpaqueBIt public TransparentBIt
;
;Эта процедура копирует битовую карту в MemBuf. Кроме этого, она
; может скроллировать левую и правую части битового образа
; в зависимости от значения ScrollSplit ;
proc OpaqueBlt
ARG Bitmap:dword,StartY:word,Height:word,ScrollSplit:word
USES si,di
les di,[MemBuf] ; получить указатель на буфер памяти
mov ax,[StartY] ;получить начальную Y-координату
mov bx,ax ;скопировать
sal ax,6 ; умножить на 64
sal bx,8 ; умножить на 256
add ax,bx ; результат равен умножению на 320
add di,ax ; вычислить смещение внутри MemBuf
mov bx,[Height] ; получить высоту битовой карты
mov dx,[ScrollSplit] ; получить длину правой половины
push ds ; сохранить сегмент данных
lds si,[Bitmap] ; получить полный указатель на битовую карту
mov ax,VIEW_WIDTH ; получить ширину экрана
sub ax,dx ; вычислить длину левой половины
cld ; обрабатывать данные от младших адресов к старшим
@@lоор01: add di,dx ; вычислить начальную позицию
mov сх,ах ; получить длину левой половины
shr cx,1 ; разделить на 2 (поскольку выводим по 2 байта) :
rep movsw ; нарисовать правую половину карты
jnc short @@skip01 ; пропустить, если выполнено
movsb ; дорисовать последний пиксель
@@skip01:
sub di,VIEW_WIDTH ; получить ширину выводимого окна
mov cx,dx ; получить длину правой половины
shr сх,1 ; разделить на 2
rep movsw ; нарисовать правую половину карты
jnc short @@skip02 ; пропустить, если выполнено
movsb ; перейти к последнему пикселю
@@skip02:
add di,ax ; получить ширину следующей строки вывода
dec bx ; уменьшить счетчик столбцов
jnz short @@loop01 ; повторить
pop ds ; восстановить сегмент данных
ret ; завершить
endp OpaqueBlt
;
; Эта процедура копирует битовую карту в MemBuf. Функция не рисует
; пиксель, если его цвет равен "прозрачному"
;
proc TransparentBIt
ARG Bitmap:dword,StartY:word,Height:word,ScrollSplit:word USES si,di
les di,[MemBuf] ; получить указатель на память
mov ax,[StartY] ; получить начальную Y-координату
mov ex, ax ; получить копию
sal ax,б ; умножить на 64
sal ex,8 ; умножить 256
add ax, ex ; результат эквивалентен умножению на 320
add di,ax ; прибавить смещение к MemBuf
mov dx,[ScrollSplit] ; получить ширину левой половины
; изображения
mov bx,VIEW_WIDTH ; общая ширина изображений
sub bx,dx ; вычислить ширину правой половины
push ds ; сохрани,ть сегмент , данных
lds si,[Bitmap] ; получить полный указатель на битовый образ
@@lоор01;
add di,dx ; вычислить начальную позицию экрана
mov сх,Ьх ; получить ширину правой половины ;
;Нарисовать правую половину ;
@@lоор02;
mov аl,[si] ; получить пиксель карты
inc si ; следующий пиксель
cmp al,TRANSPARENT ; "прозрачный"?
je short @@skip01 ; ...пропустить, если да
mov [es:di],al ; иначе, нарисовать его
@@skip01:
inc di ; указать на следующий байт MemBuf
dec ex ; уменьшить счетчик
jnz short @@loop02
sub di,VIEW_WIDTH ; получить ширину выводимого окна
mov cx,dx ; получить ширину правой половины
; Нарисовать левую половину
@@lоор03:
mov ai,[si] ; получить пиксель карты
inc si ; следующий пиксель
cmp al,TRANSPARENT ; "прозрачный"?
je short @@skip02 ;...пропустить, если да
mov [es:di],al ;иначе, нарисовать его
@@skip02;
inc di ;перейти к следующему байту видеобуфера
dec ex ;уменьшить счетчик
jnz short @@loop03 ; повторить цикл, пока не сделаем все
add di,bx ;добавить значение ширины правой
части изображения
dec [Height] ;уменьшить счетчик колонок
jnz short @@loop01 ;повторить еще раз
pop ds ;восстановить сегмент данных
ret ; закончить
endp TransparentBlt
end