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

         

Регистры контроллера CRT (03D4h– 03D5H)


Контроллер CRT управляет разверткой и формированием кадров на дисплее. Как и для графического контроллера, для обращения к регистрам контроллера CRT следует записать индекс нужного регистра в порт 03D4h, после чего можно будет читать и писать данные для выбранного регистра в порт 03D5h. Если требуется только запись в регистры, можно просто поместить индекс в AL, посылаемый байт — в АН и выполнить команду вывода слова в порт 03D4h.

00h: Общая длина горизонтальной развертки

01h: Длина отображаемой части горизонтальной развертки минус один

02h: Начало гашения луча горизонтальной развертки

03h: Конец гашения луча горизонтальной развертки

биты 6 – 5: горизонтальное смещение в текстовых режимах

биты 4 – 0: конец импульса

04h: Начало горизонтального обратного хода луча

05h: Конец горизонтального обратного хода луча

биты 7, 4 – 0: конец импульса

биты 6 – 5: горизонтальное смещение импульса

06h: Число вертикальных линий растра без двух старших бит

07h: Дополнительный регистр

бит 7: бит 9 регистра 10h

бит 6: бит 9 регистра 12h

бит 5: бит 9 регистра 06h

бит 4: бит 8 регистра 18h

бит 3: бит 8 регистра 15h

бит 2: бит 8 регистра 10h

бит 1: бит 8 регистра 12h

бит 0: бит 8 регистра 06h

08h: Предварительная горизонтальная развертка

биты 6 – 5: биты 5 и 4 регистра горизонтального панорамирования

биты 4 – 0: номер линии в верхней строке, с которой начинается изображение

09h: Высота символов

бит 7: двойное сканирование (400 линий вместо 200)

бит 6: бит 9 регистра 18h

бит 5: бит 9 регистра 15h

биты 4 – 0: высота символов минус один (от 0 до 31)

0Ah: Начальная линия курсора (бит 5: гашение курсора)


0Bh: Конечная линия курсора (биты 6 – 5: отклонение курсора вправо)

0Ch: Старший байт начального адреса

0Dh: Младший байт начального адреса (это адрес в видеопамяти, начиная с которого выводится изображение)

0Eh: Старший байт позиции курсора

0Fh: Младший байт позиции курсора

10h:  Начало вертикального обратного хода луча без старшего бита

11h: Конец вертикального обратного хода луча без старшего бита

бит 7: защита от записи в регистры 00 – 07 (кроме бита 4 в 07h)

бит 6: 1/0 — 5/3 цикла регенерации за время обратного хода луча

бит 5: 1/0 — выключить/включить прерывание по обратному ходу луча

бит 4: запись нуля сюда заканчивает обработку прерывания

биты 3 – 0: конец вертикального обратного хода луча

12h: Число горизонтальных линий минус один без двух старших бит

13h: Логическая ширина экрана (в словах/двойных словах на строку)

14h: Положение символа подчеркивания

бит 6: 1/0 — адресация словами/двойными словами

бит 5: увеличение счетчика адреса регенерации на 4

биты 4 – 0: положение подчеркивания

15h: Начало импульса гашения луча вертикальной развертки без двух старших бит

16h: Конец импульса гашения вертикальной развертки

17h: Регистр управления режимом

бит 7: горизонтальный и вертикальный ходы луча отключены

бит 6: 1/0 — адресация байтами/словами

бит 4: 1 — контроллер выключен

бит 3: 1/0 — счетчик адреса регенерации растет на 2/1 на каждый символ

бит 2: увеличение в 2 раза разрешения по вертикали

18h: Регистр сравнения линий без двух старших бит

(от начала экрана до линии с номером из этого регистра отображается начало видеопамяти, а от этой линии до конца — видеопамять, начиная с адреса, указанного в регистрах 0Ch и 0Dh)



22h: Регистр-защелка (только для чтения)

23h: Состояние контроллера атрибутов

биты 7 – 3: текущее значение индекса контроллера атрибутов

бит 2: источник адреса палитры

бит 0: состояние порта контроллера атрибутов — 0/1 = индекс/данные

BIOS заполняет регистры этого контроллера соответствующими значениями при переключении видеорежимов. Так как одного контроллера CRT мало для полного переключения в новый видеорежим, мы вернемся к этому чуть позже, а пока посмотрим, как внести небольшие изменения в действующий режим, например, как превратить текстовый режим 80x25 в 80x30:

; 80x30.asm ; переводит экран в текстовый режим 80x30 (размер символов 8x16) ; (Norton Commander 5.0 в отличие от, например, FAR восстанавливает режим по ; окончании программы, но его можно обмануть, если предварительно нажать ; Alt-F9) .model tiny .code .186 ; для команды outsw org 100h ; СОМ-программа start: mov ax,3 ; установить режим 03h (80x25), int 10h ; чтобы только внести небольшие изменения mov dx,3CCh ; порт 3CCh: регистр вывода (MOR) на чтение in al,dx mov dl,0C2h ; порт 03C2h: регистр вывода (MOR) на запись or al,0C0h ; установить полярности 1,1 - для 480 строк out dx,al mov dx,03D4h ; DX = порт 03D4h: индекс CRT mov si,offset crt480 ; DS:SI = адрес таблицы данных для CRT mov cx,crt480_l ; CX = ее размер rep outsw ; послать все устанавливаемые параметры ; в порты 03D4h и 03D5h

; нельзя забывать сообщать BIOS об изменениях в видеорежиме push 0040h pop es ; ES = 0040h mov byte ptr es:[84h],29 ; 0040h:0084h - число строк ret

; данные для контроллера CRT в формате индекс в младшем байте, данные в ; старшем - для записи при помощи команды outsw crt480 dw 0C11h ; регистр 11h всегда надо записывать первым, ; так как его бит 7 разрешает запись в другие dw 0B06h,3E07h,0EA10h,0DF12h,0E715h,0416h ; регистры crt480_l = ($-crt480)/2 end start

Еще одна интересная возможность, которую предоставляет контроллер CRT, — плавная прокрутка экрана при помощи регистра 08h:

; vscroll.asm ; Плавная прокрутка экрана по вертикали. Выход - клавиша Esc ; .model tiny .code .186 ; для push 0B400h org 100h ; СОМ-программа start: push 0B800h pop es xor si,si ; ES:SI - начало видеопамяти mov di,80*25*2 ; ES:DI - начало второй страницы видеопамяти mov cx,di rep movs es:any_label,es:any_label ; скопировать первую ; страницу во вторую mov dx,03D4h ; порт 03D4h: индекс CRT screen_loop: ; цикл по экранам mov cx,80*12*2 ; СХ = начальный адрес - адрес середины экрана line_loop: ; цикл по строкам mov al,0Ch ; регистр 0Ch - старший байт начального адреса mov ah,ch ; байт данных - СН out dx,ax ; вывод в порты 03D4, 03D5 inc ax ; регистр 0Dh - младший байт начального адреса mov ah,cl ; байт данных - CL out dx,ax ; вывод в порты 03D4, 03D5



mov bx,15 ; счетчик линий в строке sub cx,80 ; переместить начальный адрес на начало ; предыдущей строки (так как это движение вниз) pel_loop: ; цикл по линиям в строке call wait_retrace ; подождать обратного хода луча

mov al,8 ; регистр 08h - выбор номера линии в первой ; строке, с которой начинается вывод изображения mov ah,bl ; (номер линии из BL) out dx,ax

dec bx ; уменьшить число линий, jge pel_loop ; если больше или = нулю - строка еще не ; прокрутилась до конца и цикл по линиям ; продолжается in al,60h ; прочитать скан-код последнего символа, cmp al,81h ; если это 81h (отпускание клавиши Esc), jz done ; выйти из программы, cmp cx,0 ; если еще не прокрутился целый экран, jge line_loop ; продолжить цикл по строкам, jmp short screen_loop ; иначе: продолжить цикл по экранам

done: ; выход из программы mov ax,8 ; записать в регистр CRT 08h out dx,ax ; байт 00 (никакого сдвига по вертикали), add ax,4 ; а также 00 в регистр 0Ch out dx,ax inc ax ; и 0Dh (начальный адрес совпадает out dx,ax ; с началом видеопамяти) ret

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 ; а теперь начала следующего wait_retrace endp

any_label label byte ; метка для переопределения сегмента в movs end start

Горизонтальная прокрутка осуществляется аналогично, только с использованием регистра горизонтального панорамирования 13h из контроллера атрибутов.


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