Рисование в SVGA

Пикселы расположены линейно в памяти видеоадаптера. В 256-цветных режимах пиксел представляется одним байтом. Поэтому смещение точки с координатами (x,y) можно вычислить как 640*y+x в режиме с 640 пикселами по горизонтали. Единственное ограничение, связанное с такими вычисленими, - это то, что последний доступный пиксел, к которому может быть получен доступ, имеет координаты x=255, y=102, его смещение 65535. Это известное ограничение 64Kбайтных сегментов.

Чтобы обойти это ограничение, применяется переключение банков памяти. При этом переопределяется расположение физического адреса, которое соответствует логическому адресу. Так, логический адрес 0 соответствует физическому адресу 65536 если активен первый банк в видеодаптером с размером "окна" (granularity) 64 KB.

Логический адрес точки с координатами (x,y) определяется как 640*y+x-B*WG где B - номер банка и WG - размер "окна". Банк памяти может быть переключен с помощью функции AX=4F05h прерывания 10h в видеоадаптерах, поддерживающих стандарт VESA.

Далее процедура рисует пиксел на экране. Координаты пиксела находятся в регистрах AX и BX, а в регистре CX передается цвет пиксела. В процедуре предполагается, что размер "окна" равен 64 KB, что справедливо, например, для чипов S3.

SVGA_bank dw 0 ;номер активного банка памяти

S_rivi dw 640 ;длина строки в байтах

VGA_seg dw 0A000h ;сегмент памяти экрана VGA

CBpxl$ proc ;рисует пиксел с координатами x=AX, y=BX, цвет=CX

xchg AX,BX ;теперь x=BX, y=AX

mul S_rivi

add AX,BX

adc DX,0 ;в DX помещается требуемый номер банка

mov DI,AX ;логический адрес

cmp DX,SVGA_bank ;банк корректен?

je Cxl256_OK

mov SVGA_bank,DX ;новый банк

mov AX,4F05h

xor BX,BX ;функция: устанавливаем банк DX, окно A

int 10h

Cxl256_OK:

mov BX,ES ;сохраняем сегмент

mov AL,CL ;цвет

mov ES,VGA_seg

stosb ;рисуем пиксел

mov ES,BX

ret

CBpxl$ endp

Пишем напрямую в видеопамять

; полностью завершенная COM-программа

codeseg segment

assume cs:codeseg, ds:codeseg, es:codeseg

org 100h

Code: jmp Start

x dw 50 ;координата x выводимого текста

y dw 20 ;координата y выводимого текста

Text db 'string to be printed',0 ;не забываем 0

Start:

mov AX,80 ;вычисляем адрес

mul y

add AX,x

shl AX,1 ;адрес в AX=160*y+2*x

mov DI,AX

mov SI,offset Text

push ES ;сохраняем ES

mov AX,0B800h ;сегмент экранной памяти в текстовом режиме

mov ES,AX

Print:

lodsb ;загружаем AL из DS:[SI]

or AL,AL ;конец строки?

jz Ready ;да, AL=0

mov ES:[DI],AL ;символ для отображения

add DI,2 ;пропускаем байт атрибутов

jmp Print

Ready: pop ES ;восстанавливаем ES

;---------------------------------------

int 20H

codeseg ends

end Code