» Главная
eXcode.ru » Статьи » Assembler
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 15





Работа с LFB в DOS





Осознав своё место в мире, постигнув
единство всего сущего, относительность
добра и зла, человек обретает душевное
равновесие и покой, поколебать который
не в силах никакие бури…

Традиции воинских искусств [КЭМПО]

Наверняка всем кто только начинал программировать на Ассемблере, неизбежно приходилось сталкиваться с проблемой вывода на экран в режимах SVGA. Многие использовали банки видеопамяти или перемещение окна, но есть несколько минусов использования такого подхода:
• Нужно написать довольно большую процедуру для вывода точек на экран
• Переключение банков занимает значительное время. (Особенно заметно на 386-ом с VGA картой :) )
Но есть и плюс: переключение банков видеопамяти можно использовать даже на 286-ом, в то время как для работы LFB нужна видеокарта как минимум поддерживающая спецификацию VESA VBE 2.0 и т.д. и т.п.
Не будем забегать вперёд и разберём всё по порядку…
И так, LFB (Linear Frame Buffer) – линейный кадровый буфер, использующийся для отображения видеопамяти на непрерывный кусок адресного пространства. Для работы с видеорежимами и видеокартой используется соответствующее прерывание BIOS – INT 10. Программировать линейный кадровый буфер мы будем в BIG REAL MODE, так как в реальном режиме LFB не используется, за исключением совсем экзотических случаев. Я предполагаю, что вы немного разбираетесь в защищённом режиме (далее PM), селекторах, дескрипторах и прочей бесовщине, а если нет, тоже не беда… Ведь чтобы использовать электрочайник не обязательно в совершенстве знать его устройство, формулы теплового баланса и т.п. :) Если вы готовы, то начнём-с!

Прерывание INT 10

Прежде всего, нам понадобятся несколько функций для переключения режимов и определения номера версии VBE:
INT 10h АН = 4Fh, AL = 00 — Получить общую SVGA-информацию
Ввод: AX = 4F00h
ES:DI = адрес буфера (512 байт)
Вывод: AL = 4Fh, если функция поддерживается
АН = 01, если произошла ошибка
АН = 00, если данные получены и записаны в буфер

Буфер для общей SVGA-информации:
+00h: 4 байта — будет содержать [VESA] после вызова прерывания, чтобы получить поля, начиная с 14h, здесь надо предварительно записать строку [VBE2]
+04h: слово — номер версии VBE в двоично-десятичном формате (0102h — для 1.2, 0200h — для 2.0)
+06h: 4 байта — адрес строки-идентификатора производителя
+0Ah: 4 байта — флаги:
бит 0 — АЦП поддерживает 8-битные цветовые компоненты (см. подфункцию 08h)
бит 1 — видеоадаптер несовместим с VGA
бит 2 — АЦП можно программировать только при обратном ходе луча
бит 3 — поддерживается спецификация аппаратного ускорения графики VBE/AF 1.0
бит 4 — требуется вызов EnableDirectAccess перед использованием LFB
бит 5 — поддерживается аппаратный указатель мыши
бит 6 — поддерживается аппаратное отсечение
бит 7 — поддерживается аппаратное копирование блоков
биты 8 – 31 зарезервированы
+0Eh: 4 байта — адрес списка номеров поддерживаемых видеорежимов (массив слов, последнее слово = FFFFh, после которого обычно следует список нестандартных режимов, также заканчивающийся словом FFFFh)
+12h: слово — объем видеопамяти в 64-килобайтных блоках
+14h: слово — внутренняя версия данной реализации VBE
+16h: 4 байта — адрес строки с названием производителя
+1Ah: 4 байта — адрес строки с названием видеоадаптера
+1Eh: 4 байта — адрес строки с версией видеоадаптера
+22h: слово — версия VBE/AF (BCD, то есть 0100h для 1.0)
+24h: 4 байта — адрес списка номеров режимов, поддерживающих аппаратное ускорение (если бит поддержки VBE/AF установлен в 1)
+28h: 216 байт — зарезервировано VESA
+100h: 256 байт — зарезервировано для внутренних данных VBE. Так, например, в эту область копируются строки с названиями производителя, видеоадаптера, версии и т.д.

INT 10h АН = 4FH, AL = 02 — Установить режим
Ввод: AX=4F02h
ВХ = номер режима:
биты 0 – 6 — собственно номер режима
бит 7 — видеопамять не очищается при установке режима, если все следующие биты — нули
бит 8 — стандартный VBE SVGA-режим
бит 9 — нестандартный SVGA-режим
биты 10 – 12 — зарезервированы
бит 13 — режим использует аппаратное ускорение
бит 14 — режим использует LFB
бит 15 — видеопамять не очищается при установке режима
Кроме того, специальный номер режима 81FFh соответствует доступу ко всей видеопамяти и может использоваться для сохранения ее содержимого.
Вывод: AL = 4Fh, если функция поддерживается
АН = 00, если режим установлен
АН = 01 или 02, если произошла ошибка

Вот номера всех стандартных режимов (в скобках указан размер требуемой памяти):
4-битные режимы (16 цветов):
VGA
• 012h: 640x480 (64 Кб)
VESA VBE 1.0
• 102h: 800x600 (256 Кб)
• 104h: 1024x768 (192 Кб)
• 106h: 1280x1024 (768 Кб)
Каждый пиксель описывается одним битом, для вывода цветного изображения требуется программирование видеоадаптера на уровне портов ввода-вывода.
8-битные режимы (256 цветов):
VGA
• 013h: 320x200 (64 Кб)
VBE 1.0
• 100h: 640x400 (256 Кб)
• 101h: 640x480 (320 Кб)
• 103h: 800x600 (512 Кб)
• 105h: 1024x768 (768 Кб)
• 107h: 1280x1024 (1,3 Мб)
VBE 2.0
• 120h: 1600x1200 (1,9 Мб)
Каждый пиксель описывается ровно одним байтом. Значение байта — номер цвета из палитры, значения цветов которой можно изменять, например, вызывая подфункцию 09 видеофункции 4Fh.
15-битные режимы (32 К цветов):
VBE 1.2
• 10Dh: 320x200 (128 Кб)
• 110h: 640x480 (768 Кб)
• 113h: 800x600 (1 Мб)
• 116h: 1024x768 (1,5 Мб)
• 119h: 1280x1024 (2,5 Мб)
VBE 2.0
• 121h: 1600x1200 (3,8 Мб)
Каждый пиксель описывается ровно одним словом (16 бит), в котором биты 0 – 4 содержат значение синей компоненты цвета, биты 5 – 9 — зеленой, а биты 10 – 14 — красной. Бит 15 не используется.
16-битные режимы (64 К цветов):
VBE 1.2
• 10Eh: 320x200 (128 Кб)
• 111h: 640x480 (768 Кб)
• 114h: 800x600 (1 Мб)
• 117h: 1024x768 (1,5 Мб)
• 11Ah: 1280x1024 (2,5 Мб)
VBE 2.0
• 121h: 1600x1200 (3,8 Мб)
Так же как и в 15-битных режимах, каждый пиксель описывается ровно одним словом. Обычно биты 0 – 4 (5 бит) содержат значение синей компоненты, биты 5 – 10 (6 бит) — зеленой, а биты 11 – 15 (5 бит) — красной. В нестандартных режимах число бит, отводимое для каждого цвета, может отличаться, так что при их использовании следует вызвать подфункцию 01 видеофункции 4Fh и получить информацию о видеорежиме, включающую битовые маски и битовые смещения для цветов.
24-битные и 32-битные режимы (16 М цветов):
VBE 1.2
• 10Fh: 320x200 (192 Кб)
• 112h: 640x480 (1 Мб)
• 115h: 800x600 (1,4 Мб)
• 118h: 1024x768 (2,3 Мб)
• 11Bh: 1280x1024 (3,7 Мб)
VBE 2.0
• 122h: 1600x1200 (7,7 Мб)
В режимах с 24-битным и 32-битным цветом каждому пикселю на экране соответствуют три байта и одно двойное слово (4 байта). Если видеорежим использует модель памяти 6 (Direct Color), то младший байт (байт 0) содержит значение синего цвета, байт 1 содержит значение зеленого, байт 2 — значение красного, а байт 3 — в 32-битных режимах резервный и используется либо для выравнивания, либо содержит значение для альфа-канала. Некоторые видеорежимы могут использовать не Direct Color, a YUV (модель памяти 7) — здесь младший байт соответствует насыщенности красного, байт 1 — насыщенности синего, а байт 2 — яркости.
INT 10h АН = 4Fh, AL = 01 — Получить информацию о режиме
Ввод: AX = 4F01h
СХ = номер SVGA-режима (бит 14 соответствует использованию LFB, бит 13 — аппаратному ускорению)
ES:DI = адрес буфера для информации о режиме (256 байт)
Вывод: AL = 4Fh, если функция поддерживается
АН = 01, если произошла ошибка
АН = 00, если данные получены и записаны в буфер

Буфер для информации о SVGA-режиме:
+00h: слово — атрибуты режима:
бит 0 — режим присутствует
бит 1 — дополнительная информация (смещения 12h – 1Eh) присутствует (для VBE 2.0 эта информация обязательна и бит всегда установлен)
бит 2 — поддерживается вывод текста на экран средствами BIOS
бит 3 — режим цветной
бит 4 — режим графический
бит 5 — режим несовместим с VGA
бит 6 — переключение банков не поддерживается
бит 7 — LFB не поддерживается
бит 8 — не определен
бит 9 — (для VBE/AF) приложения должны вызвать EnableDirectAccess, прежде чем переключать банки
+02h: байт — атрибуты окна А:
бит 1 — окно существует
бит 2 — чтение из окна разрешено
бит 3 — запись в окно разрешена
+03h: байт — атрибуты окна В
+04h: слово — гранулярность окна — число килобайтов, которому всегда кратен адрес начала окна в видеопамяти (обычно 64)
+06h: слово — размер окна в килобайтах (обычно 64)
+08h: слово — сегментный адрес окна А (обычно A000h)
+0Ah: слово — сегментный адрес окна В
+0Ch: 4 байта — адрес процедуры перемещения окна (аналог подфункции 05h, но выполняется быстрее)
+10h: слово — число целых байт в логической строке
+12h: слово — ширина в пикселях (для графики) или символах (для текста)
+14h: слово — высота в пикселях (для графики) или символах (для текста)
+16h: байт — высота символов в пикселях
+17h: байт — ширина символов в пикселях
+18h: байт — число плоскостей памяти (4 — для 16-цветных режимов, 1 — для обычных, число переключений банков, требуемое для доступа ко всем битам (4 или 8), — для модели памяти 5)
+19h: байт — число бит на пиксель
+1Ah: байт — число банков для режимов, в которых строки группируются в банки (2 — для CGA, 4 — для HGC)
+1Bh: байт — модель памяти:
00h — текст
01h — CGA-графика
02h — HGC-графика
03h — EGA-графика (16 цветов)
04h — VGA-графика (256 цветов в одной плоскости)
05h — Режим X (256 цветов в разных плоскостях)
06h — RGB (15-битные и выше)
07h — YUV
08h – 0Fh — зарезервированы VESA
10h – FFh — нестандартные модели
+1Ch: байт — размер банка в килобайтах (8 — для CGA и HGC, 0 — для остальных)
+1Dh: байт — число видеостраниц
+1Eh: байт — зарезервирован
+1Fh: байт — битовая маска красной компоненты
+20h: байт — первый бит красной компоненты
+21h: байт — битовая маска зеленой компоненты
+22h: байт — первый бит зеленой компоненты
+23h: байт — битовая маска синей компоненты
+24h: байт — первый бит синей компоненты
+25h: байт — битовая маска зарезервированной компоненты
+26h: байт — первый бит зарезервированной компоненты
+27h: байт — дополнительные флаги:
бит 0: —поддерживается перепрограммирование цветов (подфункция 09h)
бит 1 — приложение может использовать биты в зарезервированной компоненте
+28h: 4 байта — физический адрес начала LFB
+2Ch: 4 байта — смещение от начала LFB, указывающее на первый байт после конца участка памяти, отображающейся на экране
+30h: слово — размер памяти в LFB, не отображающейся на экране, в килобайтах
+32h: 206 байт — зарезервировано

Реализация.

И так, мы изучили достаточно, чтобы приступить непосредственно к программированию. Собирать всё будем в TASM 5.0. Как уже было сказано выше, для каждого режима свой алгоритм вывода точки, будем использовать в нашем примере 640X480X32 бита или 112h, но т.к мы используем LFB, то необходимо бит 14, номера режима, установить в 1. Так же неплохо было бы, сделать проверку на наличие VBE 2.0 и выше. И конечно же не нужно забывать о двух дескрипторах: нулевом и 16-бином, лимитом в 4 Гб. Вроде всё. Вот наконец код, который переводит экран в режим 112h, и выводит точку красного цвета:



; LFB.asm
; Простенькая программа, демонстрирующая работу с LFB
; Компиляция:
; tasm.exe /m LFB.asm
; Линк:
; tlink.exe /x /3 LFB.obj

.386p ; 32-битные регистры появились на 386
LFB_seg segment para public "code" use16 ; Наш сегмент
assume CS:LFB_seg,DS:LFB_seg,SS:LFB_seg ; Код, данные, стек
; находятся в одном сегменте
start:

; Этот блок кода отвечает за переход в BIG REAL MODE
; мы не будем на нём подробно останавливаться…

push cs
pop ds
mov eax,cr0
test al,1
jz no_V86
mov dx,offset v86_msg
err_exit:
mov ah,9
int 21h
mov ah,4Ch
int 21h
v86_msg db "Error!Bad mode in v86!$"
win_msg db "Error!Windows is runing!$"
no_V86:
mov ax,1600h
int 2Fh
test al,al
jz no_windows
mov dx,offset win_msg
jmp err_exit
no_windows:
xor eax,eax
mov ax,cs
shl eax,4
add ax,offset GDT
mov gdt_base,eax
lgdt fword ptr gdtr
cli
mov eax,cr0
or al,1
mov cr0,eax
jmp start_PM

start_PM:
mov ax,8
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax

mov eax,cr0
and al,0FEh
mov cr0,eax
jmp exit_PM

exit_PM:
xor ax,ax
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
sti
mov ax,cs
mov ds,ax
; Всё, теперь мы в BIG REAL MODE
; Нам нужны некоторые сегментные регистры
push ds
pop es
; Получаем общую SVGA информацию
mov ax,4F00h
; Сохраняем её в буфере
mov di,offset Video_Buffer
int 10h
; Считываем номер версии VBE в BX
mov bx,word ptr [Video_Buffer+04h]
; Если он ниже чем 2.0
cmp bx,0200h
; Выдать сообщение об ошибке
jl Not_support_LFB
; Иначе переходим далее
jmp Next_step
Not_support_LFB:
mov ah,9
mov dx,offset Error
int 21h
ret
Next_step:

; Получаем информацию о режиме
mov ax,4F01h
mov cx,4112h
mov es:edi,offset Info_Buffer
int 10h
; Записываем физический адрес начала LFB в ESI
mov esi,dword ptr [Info_Buffer+028h]
push esi
; Устанавливаем режим
mov ax,4F02h
mov bx,4112h
int 10h
pop esi
; Теперь выводим точку

mov X_scr,640
mov Pos_X,100
mov Pos_Y,100
mov Cr_Red,255
mov Cr_Blue,0
mov Cr_Green,0
mov Cr_Alpha,0
call pset32bit
; Ожидание нажатия клавиши
mov ah,1
int 21h
; Выход
mov ah,4Ch
int 21h

; Процедура вывода точки на экран

pset32bit proc
pusha
; В общем случае формула выглядит так:
; X_scr * Pos_Y * Количество компонент цвета + Pos_X * Количество компонент цвета

mov eax,Pos_Y
mov ebx,X_scr
imul eax,ebx
imul eax,4
mov ebx,Pos_X
imul ebx,4
add eax,ebx
xor ecx,ecx
xor ebx,ebx
mov cl,Cr_Blue
mov ch,Cr_Green
mov bl,Cr_Red
mov bh,Cr_Alpha
mov byte ptr fs:[esi+eax],cl
inc eax
mov byte ptr fs:[esi+eax],ch
inc eax
mov byte ptr fs:[esi+eax],bl
inc eax
mov byte ptr fs:[esi+eax],bh
popa
ret
pset32bit endp
; Начало области данных

GDT label byte
; Нулевой дескриптор
db 8 dup(0)
; 16-битный 4 Гб сегмент:
db 0FFh,0FFh,0,0,0,10010010b,11001111b,0
; Размер GDT
gdtr dw 16
; Линейный адрес GDT
gdt_base dd ?
Pos_X dd 0 ; Координата X точки
Pos_Y dd 0 ; Координата Y точки
X_scr dd 0 ; Разрешение по X
Cr_Red db 0 ; Красная компонента
Cr_Green db 0 ; Зелёная компонента
Cr_Blue db 0 ; Синяя компонента
Cr_Alpha db 0 ; Альфа
Info_Buffer db 256 dup(0) ; Буфер для информации о режиме
Video_Buffer db 512 dup (0) ; Буфер для общей SVGA информации
Error db "Not support VESA VBE 2.0 or higher!$"
LFB_seg ends
end start

Вот собственно и всё. Если возникнут вопросы по теме, мыльте на Exs42@yandex.ru, я с радостью на них отвечу. Приятного клавишевания.


К началу статьи





Добавил: Exs42Дата публикации: 2006-11-21 23:45:53
Рейтинг статьи:3.27 [Голосов 11]Кол-во просмотров: 10259

Комментарии читателей

Всего комментариев: 2

2006-11-30 00:29:28
Exs42
Почитай книгу Зубкова, там подробно рассказанно о написании дров для дос и винды.

2006-11-29 02:41:22
Che
Круто!!! ТО что я искал. Узнать бы как дрова пишутся. Будет просто супер.!
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Какую музыку вы предпочитаете?
Techno
11% (29)
Rap
10% (26)
Rock
48% (126)
Trance
10% (27)
Pop
7% (17)
house
5% (13)
Классическую
7% (19)
Я не слушаю музыку
2% (4)

Проголосовало: 261
Всю ночь потел над непослушной Клавой...
Рейтинг: 7.8/10 (4)
Посмотреть все анекдоты