Assembler - язык неограниченных возможностей

         

Регистры VGA DAC (03C6h– 03C9h)


Таблица цветов VGA на самом деле представляет собой 256 регистров, в каждом из которых записаны три 6-битных числа, соответствующих уровням красного, зеленого и синего цвета. Подфункции INT 10h AX =1010h – 101Bh позволяют удобно работать с этими регистрами, но, если требуется максимальная скорость, программировать их на уровне портов ввода-вывода не намного сложнее.

03C6h для чтения/записи: Регистр маскирования пикселей (по умолчанию FFh)

При обращении к регистру DAC выполняется операция AND над его номером и содержимым этого регистра.

03C7h для записи: Регистр индекса DAC для режима чтения

Запись байта сюда переводит DAC в режим чтения, так что следующее чтение из 03C9h вернет значение регистра палитры с этим индексом.

03C7h для чтения: Регистр состояния DAC

биты 1 – 0: 00/11 — DAC в режиме записи/чтения

03C8h для чтения/записи: Регистр индекса DAC для режима записи

Запись байта сюда переводит DAC в режим записи, так что следующие записи в 03C3h будут записывать новые значения в регистры палитры, начиная с этого индекса.

03C3h для чтения/записи: Регистр данных DAC

Чтение отсюда считывает значение регистра палитры с индексом, записанным предварительно в 03C8h, запись — записывает новое значение в регистр палитры с индексом, записанным в 03C8h. На каждый регистр требуются три операции чтения/записи, передающие три 6-битных значения уровня цвета: красный, зеленый, синий. После третьей операции чтения/записи индекс текущего регистра палитры увеличивается на 1, так что можно считывать/записывать сразу несколько регистров

Команды insb/outsb серьезно облегчают работу с регистрами DAC в тех случаях, когда требуется считывать или загружать значительные участки палитры или всю палитру целиком, — такие процедуры оказываются и быстрее, и меньше аналогичных, написанных с использованием прерывания INT 10h. Посмотрим, как это реализуется на примере программы плавного гашения экрана.

; fadeout.asm ; выполняет плавное гашение экрана


.model tiny .code .186 ; для команд insb/outsb org 100h ; СОМ-программа start: cld ; для команд строковой обработки mov di,offset palettes call read_palette ; сохранить текущую палитру, чтобы ; восстановить в самом конце программы, mov di,offset palettes+256*3 call read_palette ; а также записать еще одну копию ; текущей палитры, которую будем ; модифицировать mov cx,64 ; счетчик цикла изменения палитры main_loop: push cx call wait_retrace ; подождать начала обратного хода луча mov di,offset palettes+256*3 mov si,di call dec_palette ; уменьшить яркость всех цветов call wait_retrace ; подождать начала следующего mov si,offset palettes+256*3 ; обратного хода луча call write_palette ; записать новую палитру pop cx loop main_loop ; цикл выполняется 64 раза - достаточно для ; обнуления самого яркого цвета (максимальное ; значение 6-битной компоненты - 63) mov si,offset palettes call write_palette ; восстановить первоначальную палитру ret ; конец программы

; процедура read_palette ; помещает палитру VGA в строку по адресу ES:DI read_palette proc near mov dx,03C7h ; порт 03C7h - индекс DAC/режим чтения mov al,0 ; начинать с нулевого цвета out dx,al mov dl,0C9h ; порт 03C9h - данные DAC mov cx,256*3 ; прочитать 256 * 3 байта rep insb ; в строку по адресу ES:DI ret read_palette endp

; процедура write_palette ; загружает в DAC VGA палитру из строки по адресу DS:SI write_palette proc near mov dx,03C8h ; порт 03C8h - индекс DAC/режим записи mov al,0 ; начинать с нулевого цвета out dx,al mov dl,0C9h ; порт 03C9h - данные DAC mov cx,256*3 ; записать 256 * 3 байта rep outsb ; из строки в DS:SI ret write_palette endp

; процедура dec_palette ; уменьшает значение каждого байта на 1 с насыщением (то есть, после того как ; байт становится равен нулю, он больше не уменьшается из строки в DS:SI ; и записывает результат в строку в DS:SI dec_palette proc near mov cx,256*3 ; длина строки 256 * 3 байта dec_loop: lodsb ; прочитать байт, test al,al ; если он ноль, jz already_zero ; пропустить следующую команду dec ax ; уменьшить байт на 1 already_zero: stosb ; записать его обратно loop dec_loop ; повторить 256 * 3 раза ret dec_palette endp

; процедура wait_retrace ; ожидание начала следующего обратного хода луча wait_retrace proc near push dx mov dx,03DAh VRTL1: in al,dx ; порт 03DAh - регистр ISR1 test al,8 jnz VRTL1 ; подождать конца текущего обратного хода луча, VRTL2: in al,dx test al,8 jz VRTL2 ; а теперь начала следующего pop dx ret wait_retrace endp

palettes: ; за концом программы мы храним две копии ; палитры - всего 1,5 Кб end start


Содержание раздела