Рисование пикселей в графическом режиме VESA

Как нарисовать пиксель в графическом режиме VESA?

Я пытаюсь перебить 10h функция 0ch, но это не работает. Что случилось?

(Примечание: я написал этот код в синтаксисе NASM и протестировал его с помощью qemu)

; Code:
Mov ax, 4F02h
Mov bx, 0105h ; 1024x768 pixels
Int 10h

Mov ah, 0ch ; Draw pixel function
Mov cx, 2           ; column
Mov dx, 3           ; row
Mov bh, 0    
Mov bl, 00000101b   ; colour
Int 10h

Jmp $            ; jump forever
Times 510-($-$$) db 0
Dw 0xaa55

1 ответ

Решение

Функция Int 10h/AH=0Ch должна работать даже при использовании режима VESA VBE.

Убедитесь, что используете его правильно, цвет пикселя идет в al,

;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h

;Draw pixel
mov ax, 0c09h    ;09h = Blue
mov cx, 2 
mov dx, 3     
xor bx, bx   
int 10h

Технически, вы должны использовать Int 10h/AX=4F01h для получения информации о режиме видео, включая бит 2 (поддерживается 2 выхода BIOS) поля атрибутов режима, чтобы проверить, будут ли работать функции BIOS.

Запись изображения с высоким разрешением с использованием функции BIOS может быть слишком медленной, возможно, стоит инвестировать в запись непосредственно в линейный или оконный буфер кадров.
Для записи в линейный кадровый буфер, вероятно, потребуется использовать нереальный режим, этого можно избежать, используя оконный кадровый буфер.
Это, помимо того, что медленнее, также более громоздко.

Вот очень простая программа, которая заполняет 30 рядов ужасным оттенком серого.
Обратите внимание, что я снял все проверки ради компактности и ясности, я сделал много предположений, чтобы избежать математики.
Это плохая практика, я использовал ее только для прототипирования.
Я настоятельно рекомендую вам прочитать полную информацию, возвращенную Int 10h/AX=4F01h и используйте эту информацию, чтобы выбрать правильное окно, сделать правильное заполнение и вычисления.

BITS 16

ORG 100h

mov ax, ds
mov es, ax 

;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h

;Get video mode info
mov ax, 4f01h
mov cx, 105h
mov di, modeInfo 
int 10h

;Assume first window is valid 
mov ax, WORD [es:modeInfo + 08h]
mov es, ax

;Example of how to change the window 
mov ax, 4f05h
xor bx, bx
mov dx, 5       ;This is granularity units
int 10h

xor di, di 
mov al, 0f1h
mov cx, 3*1024*20

rep stosb

;Wait for key
xor ax, ax
int 16h

;Restore DOS text mode
mov ax, 0003h
int 10h

;Exit
mov ax, 4c00h
int 21h

modeInfo    TIMES 256 db 0

Это в синтаксисе NASM, я обычно использую TASM (без привязанности) для программ DOS, но на этот раз я спешил.
Результат

Серая полоса в более или менее середине черного экрана

Помните, что в общем случае каждая строка может быть дополнена (размер строки сканирования возвращается в информации о режиме видео).
Для линии развертки шириной 1024 пикселя, с 3x8bpp у нас есть 3072 байта / линия сканирования, так как это делится на 4, заполнение, вероятно, не произойдет.
Начальный адрес окна задается в единицах гранулярности (также в информации о режиме видео), общий кадровый буфер составляет 1024x768x3 байта = 2,25 МБ, при условии отсутствия заполнения.
Размер окна также можно найти в информации о режиме видео.

Всего этого достаточно для записи в фреймбуфер.
С линейным кадровым буфером легче обращаться (заполнение - все еще аспект, чтобы рассмотреть), как только нереальный режим был установлен.

Другие вопросы по тегам