Главная » Ассемблер, Железо » Рисование линий при линейной адресации памяти

0

Сегментация видеопамяти существенно замедляет рисование линий в режимах с высоким разрешением, особенно при использовании

для переключения страниц прерываний VESA BIOS: при рисовании прямых под большим углом к горизонтали переключение приходится осуществлять через каждые несколько десятков точек. Переключение через регистры видеоконтроллера могут выполнять только Windows-драйверы, написанные программистами фирмы-изготови- теля, поскольку документация контроллера доступна только для них. Драйверы для других операционных систем обычно не предоставляются, и, следовательно, вывод линий осуществляется в режиме сегментации очень медленно.

Линейная адресация позволяет избежать переключения страниц. Модель памяти, как было показано в предыдущих разделах, при линейной адресации очень простая: видеоконтроллер воспринимает свою оперативную память как прямоугольный массив (N строк, М столбцов), а процессор видит память контроллера как линейный массив размером NxMxK байт, где К — число байтов на точку изображения.

Рисование линии базируется на операции вывода точки. Вывод точки в современных видеорежимах заключается в том, что процессор записывает по соответствующему адресу видеопамяти код цвета точки, например, при помощи команды M0V. При использовании линейной адресации для обращения к памяти можно применять в качестве индексного любой из регистров общего назначения, а в качестве сегментного — регистр данных, настроенный на видеопамять (в защищенном режиме) или на линейную адресацию. Например, если для включения линейной адресации применялась процедура, описанная ранее в разделе «Функции VESA BIOS», вывод точки белого цвета в 256-цветном режиме может быть осуществлен следующей командой:

mov [byte ptr 6S:EDI],0Fh Здесь OFh — код белого цвета, а регистр EDI — абсолютный адрес точки, то есть сумма начального адреса видеопамяти и смещения точки от начала видеопамяти.

В режиме HiColor при выполнении такой же операции нужно записать не байт, а 16-разрядное слово:

mov [word ptr GS:EDI].OFFFFh В режиме TrueColor32 вывод точки белого цвета заключается в записи соответствующего 32-разрядного кода:

mov [word ptr GS:EDI].OFFFFFFh Процесс рисования горизонтальной линии заключается в циклическом выводе кода цвета линии в ячейки памяти, соответствующие

соседним точкам (после вывода каждой точки к значению индексного регистра прибавляется количество байтов на точку). Для 256- цветного режима указанный процесс выглядит так:

: Установить цвет линии

mov AL,[LineColor]

; Записать адрес начальной точки в индексный регистр

mov EDI,[StartPixelAddress]

; Задать длину линии в пикселах

mov СХ.[LineLength]

@@L:

mov [GS:EDI],AL :нарисовать пиксел

inc EDI loop

@@L

В режиме TrueColor32 та же операция выполняется следующим образом:

: Установить цвет линии

mov ЕАХ. [LineColor] : Записать адрес начальной точки в индексный регистр

mov EDI,[StartPixelAddress] : Задать длину линии в пикселах

mov СХ,[LineLength]

@@L:

mov [GS:EDI],EAX гнарисовать пиксел

add EDI,4 loop

@@L

Процесс рисования вертикальной линии отличается от описанного выше тем, что для перехода на одну точку вниз к содержимому индексного регистра прибавляется длина логической строки в байтах (которая вычисляется как произведение длины строки в пикселах на размер пиксела в байтах). Например, для 256-цветного режима цикл рисования выглядит так:

: Установить цвет линии

mov AL.[LineColor] : Записать адрес начальной точки в индексный регистр

mov EDI,[StartPixelAddress]

; Задать длину линии в пикселах

mov СХ,[LineLength]

@@L:

mov [GS:EDI],AL ;нарисовать пиксел : Прибавить длину строки в байтах

add EDI,LogicalStringLength loop

@@L

Так же легко реализуется алгоритм рисования наклонных линий, имеющих постоянный размер шага, то есть состоящих из отрезков одинаковой длины. Например, при выводе диагональной линии под углом 45 градусов одновременно выполняется перемещение на одну точку по горизонтали и по вертикали.

В режиме HiColor для горизонтальной линии получается следующий цикл:

; Установить цвет линии

mov АХ, [LineColor]

; Записать адрес начальной точки в индексный регистр

mov EDI,[StartPixe1Address]

; Задать длину линии в пикселах

mov CX,[LineLength] №L:

mov [GS:EDI],AX

; Прибавить сунну длины строки

; и размера пиксела в байтах

add EDI.(Logi calStri ngLength+l)*2 loop №L

Для вывода произвольных линий можно использовать целочисленный алгоритм Брезенхема, описанный во всех книгах по компьютерной графике. Наиболее простое описание алгоритмов рисования линий, окружностей и эллипсов приведено в книге [1], но перевод с языка С на ассемблер теперь выполняется гораздо проще, чем десять лет назад, так как уже не нужно манипулировать с масками точек (основная «головная боль» в 16-цветных режимах), а можно использовать 32-разрядные регистры процессора и линейную адресацию видеопамяти. Полностью листинги примеров рисования линий всех типов, в том числе по алгоритму Брезенхема, будут показаны ниже — вместе с выводом текста.

Источник: Кулаков В. К90 Программирование на аппаратном уровне: специальный справочник (+дискета). 2-е издание. — СПб.: Питер, 2003. — 847 е.: ил.

По теме:

  • Комментарии