Глава 10. Введение в графическое программирование.

Когда б вызнали, из какого сора Растут стихи, не ведая стыда.

Анна Ахматова

В данной главе на примере всего лишь одного графического режима, который су­ществовал еще для EGA-адаптеров, будут рассмотрены основные принципы создания графических изображений на экране. На более высоком уровне программирование видеосистем будет рассмотрено в главе 27.

Операционная система MS DOS в отличие от Windows (см. главы 24,25), к сожа­лению, не поддерживает доступ к графическим возможностям компьютера. В BIOS есть не слишком эффективный графический интерфейс - подфункции прерывания ЮН. Вещь в значительной степени прискорбная, т.к. приходится программировать видеоадаптер самому. Это приводит к непереносимости программ на различных ти­пах компьютеров. Кроме того, программировать видеоадаптер - достаточно сложная задача. Здесь есть две стороны. Мне, как программисту, нравятся сложные задачи, программирование адаптеров, нестандартные подходы. Однако если Вы пишите ком­мерческую программу, то решающее слово здесь за потребителем. Ему же необхо­димы: быстрота программирования, удобство пользования и совместимость. На мой взгляд, однако, плох программист, который мыслит тот, кому предназначены его программы. Пользователь должен возвращать нас на землю, по своей же воле не стоит этого делать.

Для языков высокого уровня существуют графические библиотеки, которые реша­ют большинство задач, необходимых для успешной работы с графическим экраном.

Кроме того, стандартные библиотеки, как правило, рассчитаны на работу с разными адаптерами и в разных графических режимах. Однако никакая библиотека не может охватить всех возможностей графических адаптеров (особенно VGA и SVGA). Кроме того, часто требуются специальные эффекты, добиться которых можно лишь, работая с адаптером напрямую.

Прежде чем перейти к программированию на низком уровне, рассмотрим графи­ческие возможности BIOS, которые будут касаться только VGA-адаптеров (см. [8]). В главе 7 мы коснулись вопроса определения типа видеоадаптера.

I.

Ниже перечисляются основные графические функции прерывания 1 ОН.

Установка режима.

Вход:

ЛН О,     - номер режима.

Режимы для EGA и VGA-адаптеров изменяются в промежутке 14-19 (режимы 17-19 для VGA только). Для определенности в дальнейшем мы будем рассматривать только режиме номером 16-разрешение 640*350,16 цветов.

Доступ к регистрам палитры. АН-ЮН

AL - 0 - изменить регистры палитры. регистра,

ВН- цвет (6 бит). AL -1 - изменить регистры бордюра. ВН- регистр бордюра.

AL - 2 - изменить регистры палитры и бордюра.

ES:BX - 17 байт (регистры палитры 16,17-й бордюра).

AL - 3 - интенсивность.

BL - 0 интенсивный фон (16 - цветов).

BL- 1 мерцание (8 цветов + мерцание пер. плана).

Структура байта палитры имеет следующий вид:

X

X

R

G

В

Г

а

 

Последние два бита в байте не используются. Биты Rr определяют интенсивность красного цвета (red), биты Gg - интенсивность зеленого цвета (green), биты Bb - ин­тенсивность синего цвета (blue). Таким образом, любой цвет получается смешением трех чистых цветов, причем каждый цвет представлен с определенной интенсивнос­тью (отОдоЗ).

Поставить точку. АН-ОСН

ВН - номер видеостраницы.

- строка. СХ-столбец.

AL - значение цвета. Читать точку. AH-0DH.

Регистры работают аналогично предыдущему в AL возвращается цвет.

Выбрать активную страницу (переключение страниц).

АН-5

- номер активной страницы (для рассматриваемого нами режима их всего 2).

Рис.    демонстрируются возможности функций BIOS. При запуске Вы легко

убедитесь, что вывод точки работает чрезвычайно медленно. То же можно сказать о выводе символа, поскольку символ выводится как набор точек. Однако такая функция, как смена активной страницы, работает практически мгновенно. Этот механизм частоиспользуют в играх и мультипликации. Замечу, что в графическом режиме нет курсора в обычном понимании (мы его не видим). Однако именно в его позицию выводится символ. Причем позицию графического курсора можно изменить при помощи обыч­ных функций установки курсора. Использование русского текста возможно лишь в том случае, если это обеспечивает используемый драйвер экрана. Как правило, хоро­шие графические библиотеки для языков высокого уровня содержат наборы шрифтов, а также функции управления их выводом.

CODE SEGMENT

ASSUME CS:CODE ORG 100H

BEGIN:

;в  графический режим MOV AX,001OH

INT 10H

;вывод прямоугольника  по точкам

MOV

вн, о

 

MOV

АН,OCH

 

MOV

SI,120

;горизонталь

MOV

DI, 50

;вертикаль

MOV

AL, 13

прямоугольника

MOV

DX, 10

;строка

MOV

CX, 30

;колонка

INT

10H

 

INC

CX

 

DEC

SI

 

JNZ

LO

 

INC

DX

 

MOV

CX, 30

 

MOV

SI,120

 

DEC

DI

 

JNZ

LO

 

;изменение палитры MOV CX, 64 MOV АХ,1000Н MOV BL,13 MOV ВН,0

LOO: '

PUSH AX ;ждем нажатия клавиши XOR    АН,АН INT 16Н CMP AL,27

POP AX

JZ OUT_C

INT ЮН

INC BH

LOOP LOO /выводим символ на страницу О OUT_C:

XOR ВН,ВН MOV DH, 15 MOVDL, 35 MOV АН, 2

INT ЮН

MOV AL, 128     ;А - русское MOV АН,0АН MOV СХ, 1

INT 10H ;теперьла страницу 1 MOV ВН,1 MOV DH,15 MOV DL,35 MOV АН,2 INT 10H

MOV AL,129       ;Б - русское

MOV AH,OAH

MOV CX, 1

INT 10H

XOR AH,AH

INT 16H ;выбираем активную страницу

MOV АН,05

MOV AL,1

int юн

XOR AH,AH .   INT 16H ;в  текстовый режим

MOV AX,0002H

INT 10H ; выходим в DOS

RET

CODE ENDS

END BEGIN

Рис. 10.1. Демонстрация графических возможностей прерывания ЮН.п.

Длятого чтобы овладеть всеми графическими возможностями адаптера, нам не избе­жать подробного рассмотрения всех его регистров, а также режимов чтения и записи.

При использовании графических режимов VGA адрес видеобуфера расположен, начиная с адреса А000:0000. Однако адресное пространство видеобуфера составляет всего 64 К. Реальный же размер видеобуфера составляет до 256 К. Для хранения од­ной страницы экрана в режиме 16требуется 640*350/2= 122500 байт. Ясно, что адрес­ного пространства явно не хватает и для чтения и записи в видеобуфере приходится делать некоторые ухищрения.

Реально содержимое видеопамяти формируется содержимым четырех битовых плоскостей. Каждая битовая плоскость отвечает за свой цвет. Байт битовой плоскости соответствует восьми пикселям экрана. Таким образом, цвет каждой точки формиру­ется четырьмя битами, и мы получаем 16 цветов. Четырем битовым плоскостям соот­ветствуют четыре регистра-защелки. При чтении из видеопамяти регистры-защелки заполняются соответствующим содержимым - цветами восьми пикселей. При записи в видеопамять регистры-защелки участвуют в формировании цветов восьми пиксе­лей. Для микропроцессора непосредственный доступ в регистры-защелки закрыт. Однако при записи необходимо учитывать содержимое этих регистров.

Из сказанного выше следует, что для формирования экранной области требуется 122500/4=30625 байт адресного пространства. 64К адресного пространства хватит для двух страниц видеопамяти.

Рассмотрим основные регистры адаптера и их краткую характеристику (в главе 27 будет дан полный справочник видеорегистров).

Регистр 0 (установки/сброса). Позволяет установить или сбросить значение байта

в четырех битовых плоскостях.

Регистр 1 (разрешение установки/сброса). Управляет работой регистра установ­ки/сброса. Записывая в какой-либо бит этого регистра единицу, мы разрешаем исполь­зование соответствующего битарегистраустановки сброса.

Регистр 2 (регистр сравнения). Определяет цвет для режима чтения 1 (см. ниже).

Регистр 3 (регистр циклического сдвига данных/регистр выбора функций). В этом регистре независимо друг от друга работают две битовые группы: группаизтрех битО. .2 определяет циклический сдвиг байта, передаваемого из микропроцессора в видеопамять; сдвиг осуществляется слева направо. Группа из двух битов 3 и 4 определяет логическую функцию(операцию),выполняемуюприпередачеввидеопамятьнадбайтомданных мик­ропроцессора и содержимым буфера данных видеопамяти. Если биты равны 0, то байт передается без изменений, если бит 3 равен 1, а бит4 равен 0, то выполняется операция логического "И", если бит 4 равен 1, а бит 3 равен 0, то выполняется операция логического "ИЛИ", если оба бита равны 0, то выполняется операция исключающего "ИЛИ".

Регистр 4 (регистр выбора битовой плоскости). Используется для выбора битовой

плоскости в операциях чтения из видеопамяти.

Регистр 5 (регистр режима). Предназначен для выбора режима чтения/записи. Биты 0-1 устанавливают режим записи (режим 3 толькодля VGAh выше). ВитЗ уетанавли-

вает режим чтения (0 или

Регистр 6 (регистр добавочных функций). Бит 0 равен 0 при работе в алфавитно-цифровом режиме. Бит 1 - выбор отображаемой на экран страницы. Биты 2-3 опреде­ляют, какие адреса памяти отображаются на экран:

БИТЗ

БИТ 2

Адрес видеобуфера

О

О

OA0000H-0BFFFFH

0

1

0A0O00H-OAFFFFH

1

0

OB0OO0H-0B7FFFH

І

І

0b8000H-0BFFFFH

Регистр 7 (регистр запрещения чтения цвета или регистр фильтрации). В режиме чтения 1 запрещает передачу цвета или набор цветов в микропроцессор.

Регистр 8 (регистр битовой маски). Если бит в этом регистре установлен в 1,то соответствующий пиксель байта видеобуфера модифицируется операцией записи. Этот регистр работает во всех режимах записи.

Перечисленные регистры выбираются записью его номера в порт ЗСЕН. После этого значение, которое мы собираемся поместить в регистр, помещается в порт 3CFH.

Нам понадобится еще один важный регистр адаптера - регистр маски карты. Этот регистр имеет адрес порта ЗС5Н. Перед посылкой данных в порт ЗС4Н следует по­слать число 2 (произвести индексацию). Данный регистр позволяет маскировать от­дельные битовые плоскости и тем самым задавать цвет выводимой точки (чаще ис­пользуется в режиме записи 0).

Ниже (Рис. 10.2-10.7) представлены схемы всех режимов чтения-записи адаптера EGA. Рассмотрим каждый рисунок.

Режим чтения 0. Данный режим устанавливается по умолчанию во время загрузки машины. Процессор получает байт, содержащийся в одной из битовых плоскостей.

Номер битовый плоскости помещается в регистр выбора битовой плоскости.

Регистр выбора битовой плоскости

Битовые плоскости

 

 

 

Регистры

зашелки

 

->

O11OO111

з

 

11OO111O

2

 

OOO11O11

1

 

O1O1OOOO

O

 

Выбрана плоскость 2

микропроцессор

11OO111O

Рис. 10.2. Режим чтения 0.

Режим чтения 1. В этом режиме результат сравнения содержимого регистра срав­нения цвета с цветом каждого из восьми пикселей передается микропроцессору. Если сравнение показало идентичность, то соответствующий бит будет равен 1. Перед срав­нением над цветом каждого пикселя производится логическая операция "и" с содер­жимым регистра маскирования битовых плоскостей.

Режим записи 0(а). Если в регистре разрешения установки/сброса содержится ОЕН, то байт в видеопамять передается из регистра установки/сброса. При этом меняются битовые плоскоститолькоуразрешенныхпикселей (регистр битовой маски). Приэтом берется во внимание содержимое регистра сдвига: биты сдвига 0-2, биты операции 3-4. На Рис. 10.4все эти биты равны 0, поэтому ни сдвига, ни операции не производится.

Регистры защелки

1

1

0

0

1

1

1

0

0

0

1

1

1

0

0

0

0

0

1

1

1

1

0

1

0

1

1

0

Регистр маскирования битовых плоскостей (логическое "и" с пикселями из защелок)

0000000 1

Микропроцессор

Регистр сравнения Цвета

Сравнение

Рис. 10.3. Режим чтения 1.

Режим записи 0(6). В данном режиме байт передает микропроцессор. В нашем слу­чае передается 11111И1В. Это значит, что для каждого пикселя передается число 15 (1111). Однако регистр маски карты маскирует некоторые биты. В результате к пикселям направляется число 1001 В, Разумеется, реально это число доходит лишь до пикселей, разрешенных регистром битовой маски. Наконец, не забудьте еще о регистре сдвига.

Режим 0(6) позволяет формировать изображение на экране двумя способами:

1. Цвет для каждой точки помещается в регистр маски карты. Точка определяется содержимым регистра битовой маски. Т.е. изображение есть последовательность ат­рибутов точек. Пример постановки точки этим способом будет дан в главе 27.

2. Цвет определяется сразу для восьми точек последовательностью четырех байт. При этом регистр битовой маски должен содержать ЕЕН, т.е. разрешается запись для всех точек. Формирование цвета восьми точек осуществляется последовательной запи­сью в четыре битовые плоскости. Номер битовой плоскости определяется содержимым регистра разрешения записи битовых плоскостей (1,2,4,8 соответственно для плоско­стей 0,1,2,3). Легко видеть, что для формирования изображений второй способ пред­почтительнее, тогда как первый способ удобнее для задания цвета отдельных точек.

Регистр сдвига

Выбор операцИИ не Работает Сдвиг данных

Регистры защелки

00011010

11000110

00111011

11111110

'00000

Логическая операция-перезапись

Регистр установки/сброса

Регистр разрешения установки/сброса

*  *  * *

0 0 0 1

*    *    * *

1111

Битовые плоскости

00011000

10000000

00011000

1111111

01100111

Регистр битовой маски

Если регистр разрешения установки / сброса равен 0РН, циклический сдвиг не работает

Рис. 10.4, Режим записи 0(а).

Режим записи 1. При этом режиме данные передаются из регистров защелки не­посредственно в видеопамять. Режим хорош для передачи данных из одной области видеопамяти в другую.

Режим записи 2. Цвет точки передается непосредственно процессором: биты 0-3 (с учетом регистра сдвига, разумеется).

Выбор операции

Регистр сдвига не работает

Сдвиг данных

 

 

 

 

 

 

 

***00000

 

Регистры защелки

00011010

11000110

00111011

11111110

Регистр

1001

разрешение записи битовой плоскости

Логическая операция-перезапись

11111111

Процессор

Битовые плоскости

00011010

11000110

00001011

11111110

\ 00010000 |

Регистр битовой маски

Рис.10.5. Режим записи 0(6). Ставим одну точку. Цвет 9 (1001).

6 - 4072

Регистры защелки

Битовые

плоскости

 

 

 

 

 

 

 

00011010

 

 

11000110

 

00111011

 

11111110

 

00011D10

11000110

00001011

11111110

Рис. записи 1.

Регистр сдвига не работает

Выбор операции Сдвиг данных

'00000

Регистры защелки

Логическая операция-

перезапись

 

 

 

 

 

 

 

 

 

 

OlOllOlO

 

 

 

llOOOllO

 

 

OOlllOll

 

 

OllllllO

 

 

Битовые

плоскости

01011010

11000110

00010101

01111110

ІНШІ

I 00010000 |

Регистр битовой

маски

* * * 1 0 1 1

Процессор

Рис. 10.7. Режим записи 2. Ставим точку. Цвет 11 (1011).

Регистр сдвига не работает

Выбор операции Сдвиг данных

* о о о о о

Регистры защелки

00011010

11000110

00111011

11111110

Логическая операция-

перезапись

Регистр установки/сброса

Регистр разрешения

установки/сброса * * * *

0 0 0 1

1111

Битовые

плоскости

00011000

10000000

00011000

11111111

I 01100111 I

Регистр битовой

маски

И

процессор

11111111 |

Рис. 10.4. Режим записи 3.

Режим записи 3. Работает только для адаптеров VGA и выше. Похож на режим записи 0 (а). Но здесь участвует и байт от процессора. Предварительно над этим бай­том производится сдвиг согласно регистру сдвига. Далее над и байтом регистра битовой маски производится операция "И". Результирующий байти будет байтом для маскирования пикселей. Кроме того, регистр разрешения установки/сброса больше не влияет на то, какие биты регистра участвуют в формировании

битовых плоскостей.

Пример использования такого типа записи будет дан в главе 27. В следующем примере (Рис. 10.7) на экран выводится точка цвета DH. Использу­ется режим записи 0(6). Вот моменты, на которые следует обратить внимание:

1. Вывод в регистр адаптера производится всего тремя командами. Например, для установки режима чтения-записи:

MOV DX,3CEH MOVAX,0005H OUT DX,AX

Более привычны для Вас были бы команды:

MOV DX,3CEH MOV AL, 5 OUT DX,AL inc dx MOVAL,0 OUT DX,AL

Первый способ более краток и быстр и потому предпочтительнее второго.

2. Перед записью мы читаем из видеобуфера для того, чтобы содержимое регист­ров защелки соответствовало содержимому видеобуфера. В противном случае при выполнении операции записи может измениться цвет как раз у тех точек, которые мы замаскировали в регистре битовой маски.

3. В нашем примере мы выводим точку на черном фоне. Т.е. содержимое битовых плоскостей было нулевым. Если бы это было не так, то нам перед посылкой

нужного цвета следовало бы вначале обнулить битовые плоскости.

CODE SEGMENT

ASSUME CS:CODE ORG 100H

BEGIN:

;в графический режим MOV AX, 0010H

INT 1ОН,-выводим точку,  режим 0;выбор режима MOV DX,3CEH

MOV АХ,0005Н ;режим записи-чтения О

OUT DX,AX /регистр сдвига

MOV АХ,0003Н ;запись без изменения

OUT DX,AX ;выбор точки в байте

MOV АХ,8008Н ,-первая точка байта   (слева направо)

OUT DX,AX ;выбор цвета

MOV DX,ЗС4Н

MOV АХ,0D02H /второй регистр,   цвет DH .

OUT DX,AX

; устанавливаем указатель на нужный байт MOV АХ,ОАОООН MOV ES,AX

MOV BX,80*20+2 /двадцатая строка

MOV AL,BYTE  PTR ES:[BX] /вначале читаем

MOV BYTE   PTR ES:[BX],OFFH

/ждем нажатия клавиши

MOV АН, О

INT 16H /в  текстовый режим

MOV АХ,0002Н

INT 10H /выходим в DOS

RET

CODE ENDS

END BEGIN

Рис. 10.8, Вывод точки на экран в режиме записи 0.

Обратимся теперь к Рис. 10.9, который демонстрирует режим записи 2. Видно, что данный режим проще предьщущего, т.к. не используется регистр маски карты.

CODE SEGMENT

ASSUME CS;CODE

ORG 100HBEGIN:/b графический режим MOV АХ,0010Н INT 10H

точку,   режим 2 режима MOV DX,3CEH MOV AX, 0205H OUT DX,AX

/регистр сдвига

MOV AX,0003H OUT DX,AX

/выбор точки в байте MOV АХ,8008Н OUT DX,AX

/устанавливаем указатель   на  нужный байт MOV  АХ,ОАОООН MOV ES,AX MOV BX,80*20+2 MOV AL,BYTE  PTR ES:[BX] MOV AL,13

MOV BYTE   PTR ES : [BX] , AL

INT l6H

/В  текстовый режим MOV АХ,0002Н INT 10H выходим в DOS

RET

CODE ENDS

END BEGIN

Рис. 10.9.Вывод точки на экран в режиме записи 2.

Вообще говоря, в Вашем распоряжении две страницы видеопамяти. Вторая страница (номер 1) начинается на середине адресного пространства (а не сразу после страницы с номером 0), т.е. с адреса: (БРЕГН ВГУ2)+1=8000Н. Вы можете писать непосредственно на эту страницу и, используя быстрое их переключение (см. Рис. 10.1), оживлять свои изображения.

ш.

В вышеприведенных примерах точка ставится в заранее определенный байт. На практике, однако, задаются координаты точки и ее цвет. Следовательно, нужна еще процедура для расчета байта в видеобуфере и положение в байте (байт для регистра битовой маски). Смещение в буфере байта легко вычислить по формуле: (640*У+Х) БГУ 8 или, упрощая выражение, получим 80*У+Х БГУ 8. Пусть координата X нахо­дится в регистре СХ, а координата У - в регистре БХ. Следующие ассемблерные ко­манды решают данную проблему:

PUSH СХ /сохранить регистр СХ

MOVAX, 80 MUL DX SHRCX, 1 SHR СХ, 1 SHR СХ,1 ADDAX,CX POP СХ

/количество байт в строке /смещение с учетом целых строк /делим координату X на 8

смещение в буфере регистр

В регистре АХ будет находиться нужное смещение. Теперь найдем смещение в байте: MOV ВХ,АХ

AND СХ,0111В  /получаю смещение  в байте MOV АН,1

SHRAH,CL        /бит в месте,   где стоит точка Теперь в ВХ нужное смещение, а в АН байт для регистра битовой маски.

IV.

Рассмотрим теперь программу, демонстрирующую копирование страницы 0 на страницу 1. Процедура COPY сделана так, что ее можно использовать в других про-граммахили вязыках высокого уровня. Обращаю Ваше внимание, что режим записи 1 идеально подходит для целей копирования из одной области видеопамяти в другую. Как уже ранее отмечалось, страница 1 начинается со смещения 8000Н видеобуфера.

CODE SEGMENT

ASSUME CS:CODE ORG 100H

BEGIN:

;в  графический режим MOV AX, 001 OH

INT 10H

;вывод символа 1

 

XOR

BH,BH

 

MOV

DH,24

 

MOV

DL,20

 

MOV

AH, 2

 

INT

10H

 

MOV

BL,11

;цвет символа

MOV

AL, 65

;код символа

MOV

AH,OAH

 

MOV

CX,1

 

INT

10H

 

;копируем

страницу

О на страницу 1

CALL

COPY

 

нажатия клавиши

MOV

AH,0

 

INT

16H

 

;вывод символа 2

 

XOR

BH,BH

 

MOV

DH, 14

 

MOV DL,20

 

MOV AH, 2

 

INT

ЮН

 

MOVBL,09 ;цвет символа

MOVAL,166        ;код символа MOV АН,0АН

MOV CX, 1

INT 10H ; ждем нажатия клавиши MOV АН, 0

ASSEMBLER.   Учебный куре

INT 16H ;показать   страницу 1 MOV АН, 05 MOV AL, 1

INT ЮН ;ждем нажатия клавиши

MOV АН,О

INT 16H ; в текстовый режим

MOV АХ,0002Н

INT 10H ;выходим в DOS

RET

;процедура копирования COPY   PROC NEAR

PUSH AX

PUSH ВХ

PUSH СХ

PUSH DX

PUSH ES

;режим чтения-записи

MOV    DX,3CEH

MOV   AL,05

OUT    DX,AL

MOV   AL, 1

INC DX

OUT    DX, AL

DEC   ' DX ' ;регистр сдвига

MOV   AX,0003H

OUT DX,AX ;видеобуфер

MOV    AX,0А000Н

MOV ES,AX ■    XOR BX,BX /количество байт

MOV   CX,80*350 ;регистр маски карты

PUSH DX

MOV    DX,3C4H MOV AL,2

OUT ■ DX, AL MOV    AL,OFH

INC DX страницы О на страницу І

; режим чтения О,   режим записи І

все плоскости

OUT DX,AL POP DX ;копируем POVT:

MOV AL,ES:[BX]

MOV ES:[BX+8000H],AL

INC BX

LOOP POVT

; восстанавливаем режим чтения-записи

MOV AX,0005H

OUT DX,AX

POP ES

POP DX

POP CX

POP BX

POP AX RET

COPY ENDP CODE ENDS

END BEGIN

Пример копирования видеостраницы О на І.

Как видно из программы, мы используем в ней режим чтения 0 и режим запи­си    Это максимально подходит для всевозможных операций копирования.

V. Программа вывода на экран изображения в PCX формате.

Ниже представлена программа считывания PCX формате из файла

на экран. Но прежде кратко изложим основу PCX-кодирования. Файлы в PCX формате имеют фиксированньш заголовок длиной 128 байт. После заголовка идет само изобра­жение в закодированном виде. Рассмотрим сначала заголовок. Его поля приводятся ниже. Для большей наглядности они представлены в ассемблерном формате.

MANUF DB ?  ; обычно 10

HARD    DB ?  ; номер версии,   наше изложение касается вер­сии 5

ENCOD DB ? ; обычно  1,   означает,  что сжатие выполнялось BITPX DB ?   ;число бит на точку  (1 или 2) /размеры картинки XI        DW ?

Yl        DW ? "• - .....

х2        DW ?

ASSEMBLER. Учебный курс

Y2

DW

?

 

HRES

DW

?

;горизонтальное разрешение дисплея

VRES

DW

?

;вертикальное разрешение дисплея

PAL

DB

48

оир(?)    ;палитра

VMODE

DB

?

;резерв

NPLAN

DB

?

;количество плоскостей  (обычно 4)

BPLIN

DW

?

;байт на строку

PALINFO DW ? /информация о палитре (1 - и»., 2-сер.)

сканера,  если изображение получалось с помощью /этого устройства SHRES DW ?

SVRES DW ?

XTRA   DB 54 DUP(?) /резерв

Если используется адаптер EGA или VGA в режиме эмуляции EGA, то палитра

кодируется в 48 байтах (см. заголовок). Для специальных режимов VGA и SVGA па­литра хранится после изображения. Суть кодирования палитры (см. расшифровку па­литры в программе ниже) заключается в следующем. Как известно EGA-адаптер спо­собен давать на экране одновременно 16 цветов. Каждый цвет составляется из трех чистых цветов: красного, зеленого и голубого. Интенсивность каждого из них опреде­ляется двумя битами. Таким образом, палитра для каждого цвета представляется шес­тибитным полем (см. выше) и соответственно может принимать 64 значения. В заго­ловке тройка байт представляет собой палитру для одного цвета Каждый байт принимает значение от 0 до 255, причем значение от 0 до 6З дает нулевой уро­вень цвета, от 64 до     - первый уровень яркости т.д.

Чтобы понять алгоритм сжатия изображения вспомним материал, изложенный выше. Последовательность из восьми точек кодируется четырьмя байтами. Каж­дый байт соответствует своей плоскости. Каждая строка изображения кодируется последовательностью байт: сначала для плоскости 0, затем 1 и т.д. Сжатие проис­ходит для каждой строки пикселей. Если имеются повторяющиеся байты, то они кодируются следующим образом: вначале идет а затем повторя-

ющийся байт. Признаком байта повторителя является наличие у него двух стар­ших бит. Таким образом, можно закодировать до 64 повторяющихся байт. В случае неповторяющихся байт, поступают следующим образом: со значением, мень­шим СОН, пишут в строку без изменения, в противном случае кодируют его с по­вторителем, равным

Ниже представлена программа, производящая загрузку раскодировку файла в РСХ формате. Для того чтобы читателю проще было разобраться в программе, сове­тую разделить ее на следующие части и разобраться с каждой отдельно: блок началь­ных установок, блок анализа командной строки, открытие файла и попытка выделе­ния для него памяти, установка палитры, чтение файла в буфер, расшифровка с пере­носом в видеопамять. Особо обратите внимание на то, как обыгрывается вариант, ког-дадлина файла больше 64К. В книге [12] указывается, что сжатая последовательность не может переходить границы строки (границу плоскости может). В других источниках, однако, такая возможность не исключается. Наш алгоритм построен таким образом, что будет правильно работать и в том, и в другом случае.

Для того чтобы разобраться с тем, как программа работает с памятью, Вам, воз­можно, придется обратиться к материалу главы 11.

Конечно, представленная здесь программа не учитывает все нюансы РСХформа-та26 (см. [12]), но Вы можете усовершенствовать ее. В частности, следовало бы учесть возможность различных графических режимов, втомчисле VGAh SVGA-режимов.

DATA SEGMENT

PATH DB, 80 DUP(O)

MES1 DB   'Ошибка памяти. ', 13,10, '$ •

MES2 DB   'Ошибка при считывании. ',13,10,'$'

MES3 DB  'Ошибка в структуре файла. 1, 13,10, ' $ '

MES4 DB   'Нет имени файла.',13,10, '$'

MES5 DB   'Много параметров.',13,10, '$*

MES6 DB   'Файл не найден.1,13,10,'$'

DATA ENDS

SSEG   SEGMENT STACK DB   100 DUP(?)

SSEG ENDS CODE SEGMENT

ASSUME   CS:CODE, DS:DATA,SS:SSEG

BEGIN:

;начальные установки

/обрезать выделенную  программу  по   концу программы MOV АХ, DS MOV BX,SEG RR SUB ВХ,АХ MOV АН,4АН INT 21H

/установка  сегментных регистров

MOV АХ,DATA

MOV DS,AX

MOV AX,SSEG

MOV SS,AX /анализ командной строки

MOV DL,1

XOR  SI, SI

XOR DI,DI

* В принципе PCX формат уже устарел, и им пользуются достаточно редко. Я вижудве основ­ные причины: 1. Изначально в формате не были заложены возможные пути развития графи­ческих адаптеров. 2. Механизм сжатия, используемый в PCX формате, достаточно слаб и значительно уступает сжатию в таких форматах, как GIF, JPG и др.

PROO:

CMP BYTE   PTR ES:   [81H] [SI],ODH JZ K0N_1

CMP BYTE  PTR ES : [81H] [SI], 32

JZ KON_6 CMP DL, 2 ■   JNZ KON_4 MOV DL, 1

JMP  SHORT KON_2

KON_4:

MOV AL,ES:[81H][SI] MOV  PATH[DI],AL

INC DI MOV DL,0

KON_5:

INC SI

JMP SHORT PROO

KON_6:

CMP  DI,0

JZ KON_5 MOV DL,2

JMP  SHORT KON_5

KON_l:

CMP DI,0

JNZ KON_2 LEA DX,MES4

JMP PROD3

KON_2:

CMP  DL, 1

JNZ KON_3 LEA DX,MES5 JMP PROD3

KON_3:

/установим графический режим экрана MOV АН,О MOV AL, ЮН

int юн

;вызов процедуры  загрузки и  вывода картины LEA   DX, DS:PATH

CALL LOAD_PCX PUSH AX CMP AH,0

JNZ ERR

;ждем нажатия клавиши

MOV АН, О

INT 16H /возвратимся в

ERR:

MOV АН,О

MOV AL,3 INT ЮН POP AX CMP АН,О JZ WYH CMP AH,1 JNZ PRODI LEA DX,MES1 JMP   SHORT PROD3

текстовый режим

PRODI:

CMP

JNZ LEA JMP

PROD2

DX,MES2

SHORT PROD3

PROD2:

LEA DX,MES3

PROD3:

;вывод строки MOV AH,9 INT 21H ; выход в ДОС WYH:

MOV AH,4CH

INT 21H

/процедура считывания и расшифровки PCX файла

/вход DS:DX - путь к файлу,  в BL 0 или 1 /выход АН - 0 -нормально,   1-ошибка памяти, / 3-ошибка структуры LOAD_PCX PROC

PUSH DS

PUSH ES

PUSH BX PUSH CX PUSH DX

/Открыть файл

MOV AX,3D00H

INT 21H JNC NORM1

(страницы)

2-ошибка считывания,

MOV

JMP KON

NORM1:

MOV BX,AX /описатель в BX найдем длину MOV АХ,4202Н XOR СХ,СХ XOR DX,DX

INT 21H /длина в DX:AX

MOV CX, 16

DIV CX

INC АХ

/теперь в AX  количество необходимых параграфов MOV CS:_PAR,AX

на начало файла MOV AX,4200H XOR CX,CX XOR DX,DX

INT 21H

/читаем первые   128   байт (заголовок) MOV СХ,128 MOV АН,3FH

PUSH CS POP DS

LEA DX,CS:BLOK

INT 21H

CMP CX,AX

JZ NORM2

MOV    AH, 2 .

JMP KON

NORM2:

попробуем выделить буфер

PUSH ВХ

MOV BX,CS:_PAR MOV AH,48H INT 21H

POP BX

JNC NORM3

выделить  не удалось MOV   AH, 1

JMP KON

NORM3:

MOV

палитры XOR BL,BL LEA SI,CS:PAL

MOV СХ,1б

PAL_D:

PUSH

; RED

XOR MOV MOV SHR MOV DIV MOV SHL MOV SHL ADD MOV

CX

AH, AH AL,CS:[SI]

CL, 6

AL,CL

CL,2

CL

CL, 5 AH, CL CL,2 AL, CL AL, AH BH, AL

;GREEN

XOR MOV MOV SHR MOV DIV MOV SHL SHL ADD ADD

AH, AH AL,CS: CL, 6 AL, CL CL, 2 CL

CL,4 AH, CL AL, 1 AL, AH BH, AL

[SI+1]

; BLUE

XOR AH,AH

MOV AL,CS:[SI+2]

MOV CL, 6

SHR AL, CL

MOV CL, 2

DIV CL

MOV CL, 3

SHL AH, CL

■ ADD AL,AH

ADD BH,AL ;вызов функции установки

MOV AX,10Q0H

INT ЮН палитры

INC BL ADD SI,3

POP CX LOOP PAL_D POP BX

;теперь в DS сегментный адрес буфера MOV DS,CS:_SEG XOR DX,DX

POVT :

MOV CX,60000 MOV AH,3FH

INT 21H CMP AX,CX

JNZ NORM4

;делим на  16,   чтобы определить добавку к DS MOV CX,DS

ADD СХ,3750     ;параграфы, а в DX остаток ;(вообще говоря 0) MOV DS,CX MOV AL, 0

JMP  SHORT POVT

NORM4:

MOV

MOV DS,AX ;закроем файл

MOV АН,3EH •

INT 21H

;здесь копируем в видеобуфер

;теперь файл  в  буфере  количество строк

MOV AX,CS:Y2

SUB AX,CS:Y1

INC AX

MOV CS:KOL_STROK,AX ;здесь обработка,   если не PAINTBRUSH NORM5:

MOV

SUB AX,CS:X1

INC AX MOV CL,8 DIV CL

MOV CS:KOL_BYTE,AL ;здесь определяем смещение   в видеобуфере MOV AX,CS:X1 MOV CL,8

DIV CL XOR    АН,АН PUSH AX XOR DX,DX MOVCX, 80 MOV AX,CS: Yl mul cx pop bx ADD BX,AX MOV CS:_BX,BX

MOV CL,CS:NPLAN SHL CS:N_PL,CL ; готовим регистры MOV DX,3CEH MOV AX,0005H OUT DX,AX MOVAX,0003H OUT DX,AX MOV AX,0FF08H OUT DX,AX MOV AX,OA0O0H MOV ES,AX XOR SI,SI

/здесь начинается раскрутка,   при этом ES:BX на видеобуфер, ;DS:SI на содержимое файла,   KOL_STROK -  количество строк MOV AL,2

MOV CX,СS:KOL_STROK LOOP1: ;цикл строк

PUSH CX cmp    SI,60000

JB КО

PUSH AX PUSH PUSH CX PUSH BX MOV

XOR DX, DX MOV CX,16

DIV CX MOV

ADD AX,BX

MOV

MOV     SI, DX

КО:

POP POP POP POP

MOV

BX CX DX AX

LOOP2:

AH, 1

плоскостей

AX

DI,CS:BPLIN  ;количество байт для

PUSH

MOV

;одной плоскости MOV DX,3C4H OUT DX,AX MOV    DL, CS:KOL_BYTE MOV BX,CS:_BX

LOOP3:

MOV CL,DS:[SI]

CMP CL,OCOH

JB LOOP4 ;с повторителем

SUB CL,OCOH

MOV CH,DS:[SI+1]

LOOP5:

CMP DL,0

JZ LOY

MOV    ES:[BX],CH

INC BX DEC DL

DEC DI JZ WOWO DEC CL JNZ LOOP5 ADD    SI,2 JMP     SHORT LOOP3

DEC CL JNZ WOWOWO ADD     SI,2 JMP     SHORT   LOOP 6

LOY:

WOWO:

WOWOWO:

ADD CL,0C0H MOV     DS: [SI],CL

JMP     SHORT  LOOP б

; устанавливаем плоскость

г цикл в одной плоскостина языке ассемблера

LOOP4:

LOOP7:

LOOP6:

CMP

DL, 0

JZ

LOOP?

MOV

ES:[BX] ,CL

INC

BX

DEC

DL

INC

SI

DEC

DI

JNZ

LOOP3

POP

AX

SHL

AH, 1

CMP

AH,CS:N_PL

JNZ

LOOP2

POP

CX

DEC

CX

JZ

KONN

MOV

BX,CS:_BX

ADD

BX, 80

MOV

CS:_BX,BX

JMP

LOOP1

KONN:

MOV BX,DS MOVES,BX MOV АН, 4 9H

INT 21H

MOV  AH, 0

JMP    SHORT KON

; во временный буфер

/закроем буфер

CLOS_BUF:

MOV BX,DS MOV ES,BX MOV АН, 49H

INT 21H

KON:

POP DX POP CX POP BX

POP ES

POP DS RET

байт

ISO

ASSEMBLER. Учебный курс

DW ?

_BX DW ?

;=(Xl/8)+Yl*80

DB ?

N_PL DB 1

PAR DW ?

_SEG DW ?

;заголовок PCX файла BLOK:

строк

/начало буфера  (в( ;байтах)і =

/количество необходимых параграфов /сегментный адрес буфера

MANUF

DB

?

/10 для  PAINTBRUSH '

HARD

DB

 

/информация о версии (

ENCOD

DB

 

/закодировано (1)

ВІТРХ

DB

?

/бит на точку (4)

/координаты

картинки

XI

DW

?

 

Y1

DW

?

 

Х2

DW

?

 

Y2

DW

?

 

HRES

DW

?

/горизонтальное разреш

VRES

DW

?

/вертикальное разрешен

PAL

DB

48

БИР(?)   /палитра

VMODE

DB

•>

/игнорируется

NPLAN

DB

->

/количество плоскостей

BPLIN

DW

■>

/байт на строку

PALINFO

DW

■}

/информация о палитре

SHRES

DW

•>

сканера

SVRES

DW

?

 

XTRA

DB

54

ГОР(?)

(5)

LOAD__PCX ENDP

CODE ENDS /сегмент для

ZSEG SEGMENT RR     DB ? ZSEG ENDS

END BEGIN

определения конца программы

Рис. 10.11. Пример вывода па экран файла в PCX формате (16 цветов).