МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ УКРАИНЫ ДОНЕЦКИЙ НАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ МЕТОДИЧЕСКИЕ УКАЗАНИЯ И ЗАДАНИЯ К ЛАБОРАТОРНЫМ РАБОТАМ ПО КУРСУ “МЕТОДЫ И СПОСОБЫ КОМПЬЮТЕРНЫХ ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ ” для студентов специальности 6.050101 “ Компьютерный эколого-экономический мониторинг” Утверждено на заседании кафедры “Компьютерные системы мониторинга” протокол № 3 от 26.11.10 Утверждено на заседании учебно-издательского совета ДонНТУ протокол № __ от __________ Донецк – ДонНТУ - 2010 2 УДК 681.3 Методические указания и задания к лабораторным работам по курсу “Методы и способы компьютерных информационных технологий“, (для студентов специальности 7.080407 “Компьютерный эколого-экономический мониторинг ”/ сост.: доц. Губенко Н.Е., асс. Миргород В.С. – Донецк: ДонНТУ, 2010 - 96с. Приведены теоретические сведения, методические рекомендации, примеры и задания для выполнения лабораторных работ по следующим разделам дисциплины: - Программирование растровых изображений на языке PostScript; - работа с манипулятором «мышь»; - работа с драйверами CD-ROM; - программирование видеокарты; - работа с LPT портом. Составители: Рецензент: Губенко Н.Е., к.т.н., доцент Миргород В.С., ассистент 3 Лабораторная работа №1 Тема: Программирование простейших растровых изображений на языке PostScript. Цель работы: освоение принципов и приобретение навыков программирования простейших изображений на языке описания страниц растровых изображений PostScript. Методические указания к лабораторной работе PostScript создавался в качестве простого стандартного языка для описания вида текста, чертежей и простых изображений ,выводимых на растровые устройства. Язык содержит около 250 операторов, что позволяет одни и те же действия запрограммировать самыми разными способами. Описание страниц на PostScript не зависит от устройства, на котором страница будет воспроизведена. Программы на PostScript генерируются приложениями, например текстовыми процессорами, программами для настольных издательских систем и т.п. Виртуальное postscript-устройство (принтер, монитор) - это устройство, в котором имеется интерпретатор языка PostScript. Интерпретатор PostScript читает текстовый файл с описанием страницы, полученный из компьютера, и преобразует его в растровую форму, согласованную с типом устройства, которая и выводится на печать или на экран. Преимущества: описание страницы во много раз компактнее даже сильно сжатого изображения; процесс подготовки печатной страницы требует значительного времени: если пересылается описание, то подготовкой к печати занимается процессор принтера или дисплейный процессор, что освобождает процессор персонального компьютера (ПК) для выполнения другой работы и тем самым повышает его производительность; самое важное преимущество - это независимость описания от типа устройства. Текущая страница (ТС) - "идеальная" страница в памяти, на которой рисует PostScript. Она не зависит от физических характеристик устройства, на который страница будет вводиться. В начале работы программы это совершенно чистая страница. Текущий траектория (ТТ) - это набор соединенных между собой отдельных геометрических объектов (точек, линий, кривых), которые вместе описывают фигуры и их положение на странице. На текущий путь не накладывается никаких ограничений. Элементы текущего пути задаются их позициями на текущей странице. 4 Текущая траектория обрезки (ТТО) или траектория отсечения - это границы области, в которой может быть нарисовано изображение. Пространство устройства (ПУ) - определяет встроенную систему координат растрового устройства для адресации точек на странице. Пространство пользователя (ПП) - используется для удобства независимого программирования с использованием понятия СИСТЕМА КООРДИНАТ ПОЛЬЗОВАТЕЛЯ (СКП). Позиция элемента на странице задается парой X,Y. PostScript допускает преобразование пространства пользователя: начало СКП можно переносить в любую точку; оси СКП могут быть повернутыми в любую сторону; масштаб по каждой из осей может быть изменен, то есть можно задать линейное преобразование из ПП в ПУ. Преобразование из ПП в ПУ осуществляется при выводе с помощью ТЕКУЩЕЙ МАТРИЦЫ ПРЕОБРАЗОВАНИЙ (ТМП), имеющей размеры 3х3. Графический статус системы - определяется текущей траекторией и текущей матрицей преобразований. Стек: При программировании на PostScript широко используется концепция стека. СТЕК есть линейная структура, доступ к которой возможен только через ее вершину. PostScript оперирует четырьмя различными стеками: операндов, словарей, выполнения и состояния графики. Стек операндов - содержит собственно объекты PostScript и результаты действий над ними. Операторы PostScript получают операнды только через стек. Стек словарей - содержит переменные и словари, открытые в настоящий момент. Словарь - суть набор пар «имя-значение». Все поименованные значения хранятся в словарях. Операнды также хранятся в словарях вместе с их кодами. Если программа ссылается на некоторое имя, то интерпретатор просматривает стек сверху вниз и ищет первое вхождение этого имени. Занесение чисел в стек: Любое число, появившееся в исходном файле PostScript-программы заносится в стек. Например, напишем строку: -81 110.4 +777 5 Интерпретатор по мере ее чтения слева направо выполнит следующие действия: - заносит в стек число -81; - перемещает указатель на следующую свободную позицию; - заносит в стек число 110.4; - перемещает указатель на следующую позицию и т. д. Стек будет иметь вид: 777 110.4 -81 Число 777 размещается в вершине стека, и оно может быть использовано первым в какой-либо операции. Остальные числа используются в порядке, обратном порядку их занесения в стек. Таким же образом в стек заносятся PostScript-объекты любого вида: массивы, строки и словари. Набор символов: Все символы делятся на специальные и регулярные. Все виды скобок (круглые, квадратные, фигурные, угловые) и знак процента являются для PostScript специальными знаками. Остальные символы -подмножество кода ASCII, используются в программе без ограничений и называются регулярными символами. Имя - любая последовательность символов, которую нельзя интерпретировать как число и построенная из любых символов, кроме скобок, пробелов, знаков % и /. Если перед именем стоит символ «/», то имя помещается в стек как операнд, иначе оно ищется в стеке словарей. Если найденное имя есть процедура, то она выполняется, иначе имя помещается в стек операндов. Типы даннях: Данные делятся на основные и дополнительные. Основные: целые, действительные, логические, массивы и строки. Дополнительные: mark (отметка, метка) и dictionary (словарь). Константы: В PostScript используются константы трех типов: целые, действительные и строковые. Примеры записи целых: +745 -61 48889 0 6 Если величина числа превышает предел для представления целых чисел, оно автоматически конвертируется интерпретатором в число типа real. Примеры записи действительных чисел: -122.0 33.3E-5 +.0065 Беззнаковые целые числа могут быть записаны в любой позиционной системе счисления с использование префикса в виде: база#число где: база - основание системы счисления (десятичное целое число от 2 до 36); число - представление числа в указанной базой системе счисления. Цифры в системах счисления по основанию больше 10 представляются буквами латинского алфавита от A до Z. Например: 18#75cb2e 8#5347 2#11001011 Строка - это последовательность символов, заключенная в круглые скобки. Символы можно также представлять шестнадцатеричными кодами, заключая их в угловые скобки. Массивы - последовательность объектов, заключенных в квадратные скобки. Они могут быть двух типов: регулярные (содержащие объекты одного типа) и нерегулярные (содержать объекты разных типов). Комментарий - любой текст, начинающийся символом «%». Операторы по своему функциональному назначению делятся на три группы: арифметические, работы с текстом и графикой и работы со стеком. Оператор побуждает интерпретатор к выполнению определенных действий. Программа выполняется путем продвижения интерпретатора от слова к слову, проверки слов по внутреннему словарю на соответствие множеству имен операторов. Если слова в словаре найдено, то выполняются все связанные с ним действия, а затем переход к следующему слову в исходном файле. При разработке программы необходимо учитывать, что операндыобъекты любого вида предварительно размещаются в стеке операндов, а не адресуются непосредственно указанием имени переменной. Такой стиль программирования, при котором операнды задаются до операции над ними, называется ПОСТФИКСНОЙ НОТАЦИЕЙ или польской инверсной записью. Выполняемый оператор забирает операнды из вершины стека, совершает над ними действие и, в общем случае, возвращает результат в вершину стека. Поэтому операторы записываются в следующем виде: arg1 arg2 … argN operator result Так запись операции сложения двух чисел, допустим 24+115, в PostScript будет выглядеть следующим образом: 24 115 add 7 Разделители объектов - пробелы, символы табуляции и новой строки, а также круглые и квадратные скобки. Гибкость языка: Несмотря на большое количество встроенных операторов в PostScript нет зарезервированных слов. Любое слово переопределяемо. Программа в PostScript может рассматриваться как данные. Арифметические операторы: Унарная операция: neg – изменить знак числа в вершине стека. Пример: -543 neg = > 543 Бинарные операции: Add - сложение, Sub - вычитание, div - деление, idiv - целочисленное деление. mod - остаток от деления. Операнды операторов MOD и IDIV должны быть целыми числами. Mul - перемножает два числа в вершине стека, помещая вместо них их произведение. При выполнении этих операций оба операнда извлекаются из вершины стека. Вторым операндом всегда выступает число из вершины стека, а вторым - число, находящееся под ним. Примеры записи арифметических выражений: Обратите внимание на то, что выражения на языке PostScript можно представить несколькими способами! 1. 23 + ( 8 : 2 ) a. а) 8 b. б) 23 2 div 23 add 8 2 div add 2. 39 - ( 4*7 ) a. а) 39 4 7 mul sub b. б) 4 7 mul 39 exch sub 8 В случае б) оператор EXCH меняет местами положение двух верхних чисел в вершине стека. Применение оператора EXCH вызвано тем, что SUB вычитает число в вершине стека из следующего за ним, что без EXCH приводит к неверному порядку действий. Операторы управления стеком: Эта группа операторов добавляет, удаляет и изменяет порядок следования элементов в стеке. Clear - очистка стека - удаляет из стека все элементы а1...аn clear Сount - число элементов в стеке. a1...an count a1...an n Dup - дублирует в стеке его верхний элемент a1 dup a1 a1 8 dup -> 8 8 Pop - удаляет из стека его верхний элемент an...a2 a1 pop -> an...a2 25 31 4 pop -> 25 31 Roll - циклически сдвигает элементы стека. При этом число и направление сдвига задается первым (верхним) элементом, а количество сдвигаемых элементов - вторым. Если первый элемент положительный, сдвиг осуществляется вправо, иначе - влево. 15 7 8 9 3 1 roll -> 15 9 7 8 15 7 8 9 3 -1 roll -> 15 8 9 7 Copy дублирует n верхних элементов стеков a1...an n copy a1...an a1...an = = удаляет элемент из вершины стека и отображает его на экране. Pstack - печатает все содержимое стека, не изменяя его. Формирование графических изображений: Программирование изображения в PostScript начинается с конструирования траектории на идеальной поверхности, называемой текущей страницей. Траектория есть набор прямых и кривых линий, определяющих разомкнутые или замкнутые области (которые возможно будут заполнены). Линии могут иметь разную толщину и тип. После того, как заполнение текущей страницы закончено, ее можно вывести на физическое устройство. Таким образом, получение графических изображений осуществляется в три этапа: - конструирование траектории; - нанесение ее на текущую поверхность; 9 - вывод страницы. Операторы конструирования траектории: x y moveto - точку с координатами х, у делает текущей на текущей странице; dx dy rmoveto - перемещает текущую точку на текущей странице на величину dx dy; х у lineto добавляет к траектории отрезок прямой от текущей точки до точки с координатами х у; dx dy rlineto добавляет к траектории отрезок прямой от текущей точки до точки с координатами х + dx у + dy; x y r angl1 angl2 arc - добавляет к заданной траектории дугу (окружность) и требует наличия в стеке пяти аргументов: координат х, у центра окружности, радиуса, угла начала дуги, угла конца дуги. Дуга строится против часовой стрелки: 100 100 42 30 110 arc Аналогичный ARC оператор ARCN строит угол по часовой стрелке. Сравните: 100 100 42 30 110 arcn Если текущая точка траектории не совпадает с начальной точкой дуги, то они будут соединены отрезком. Чтобы нарисовать окружность, нужно задать ARC угол в 360 градусов, например: 150 200 60 0 360 arc x1 y1 x2 y2 r arcto - сглаживание углов. Пересекающиеся линии часто бывает необходимо соединить плавной кривой. В стеке задаются координаты двух точек и радиус. Оператор рисует сегмент прямой линии от текущей точки по направлению к точке х1, у1, а затем дугу до её пересечения со второй прямой. ARCTO возвращает в стеке координаты начала и конца дуги. Если они не нужны, то эти числа следует удалить из стека: 4 {pop} repeat Операторы управления выводом: - newpath - очищает текущую траекторию и готовит систему к началу конструирования новой траектории. Оператор необходим перед началом любой новой траектории; - closepath - закрывает текущую траекторию, добавляя при этом отрезок, начало котрого - текущая точка, а конец - начальная точка траектории; 1 на0 - stroke - вызывает рисование сконструированного нами пути текущей странице с учетом текущих атрибутов ( текущей толщины линии, текущего цвета пера, текущего образа линии, текущего способа соединения линий). В системе координат, принятой в PostScript по умолчанию, начало координат находится в нижнем левом углу страницы. Координата х увеличивается вправо, а у - при движении вверх. Единица длины в этой системе равна 1/72 дюйма. По умолчанию текущий цвет пера - черный, а текущий образ линии - сплошная. - showpage - отображает (печатает) текущую страницу и подготавливает новую. ПРИМЕР: Написать программу, рисующую квадрат со стороной один дюйм, расположенный в центре страницы: newpath 200 300 moveto 0 72 rlineto 0 -72 rlineto -72 0 rlineto stroke showpage Наш квадрат, как вы заметили, имеет выщерблину в левом нижнем углу, так как линии соединяются без учета толщины. Чтобы избежать этого явления, следует использовать оператор CLOTHEPATH. Операторы управления свойствами: - setlinewidth - позволяет вам установить ширину линии Х * 1/72 дюйма. Данный оператор действует на все линии, помещаемые на текущую страницу, пока не встретится другой оператор setlinewidth; - fill - закрывает текущую траекторию и заполняет ее текущим цветом (уровнем серого) и очищает текущую траекторию. Используется вместо stroke ; - setgray - задает уровень серого цвета для заполнения фигуры в долях от единицы (в интервале от 0 - черный цвет до 1 - белый); - R G B setrgbcolor - задает сочетание интенсивностей трех основных цветов (красного, зеленого и синего); интенсивность выражается числом в диапазоне от 0 до 1 (0 - полное отсутствие соответствующего цвета, 1 максимальная его интенсивность); - H S B sethsbcolor - задает тон (цвет), насыщенность, яркость. Тон определяет цвет как точку на цветовом круге (0 градусов - чистый красный. 120 1 цвета1 градусов – чистый зеленый, 240 градусов - чистый синий; остальные спектра определяются смешением двух соседних цветов). Насыщенность цвета задается числом (0 - отсутствие цвета, 1 - максимальная насыщенность). Яркость, то есть содержание белого цвета в данном, задается числом от 0 до 1 (0 - черный, 1 - белый). ПРИМЕР: Рисование перекрывающихся областей При рисовании перекрывающихся областей цвет их пересечения определяется цветом, нанесенным на текущую страницу последним. Нарисуем два перекрывающихся прямоугольника. %! newpath % серый квадрат 200 300 moveto 0 72 rlineto 72 0 rlineto 0 -72 rlineto сlosepath 0.5 setgray fill newpath % светлый квадрат 236 336 moveto 0 72 rlineto 72 0 rlineto 0 -72 rlineto closepath .8 setgray fill showpage % отобразить Обратите внимание, что каждый квадрат начинается с оператора moveto. Это связано с тем, что оператор fill очищает текущую траекторию и после него не определена текущая точка, поэтому lineto и rlineto не имеют начальной точки. Оператор stroke также очищает текущую траекторию. Задание к лабораторной работе №1 Написать на языке PostScript программу рисования произвольной композиции, содержащей различные плоские геометрические фигуры( прямоугольники, дуги, овалы и т.п.). Лабораторная работа №2 1 2 Тема: Программирование растровых изображений на языке PostScript с использованием процедур. Цель работы: освоение принципов и приобретение навыков процедурного программирования изображений, использующих различные шрифты и преобразования системы координат, на языке PostScript. Методические указания к лабораторной работе Словарь (dictionary) - PostScript-словарь связывает объект, именуемый ключом, с другим объектом - значением этого ключа. Интерпретатор языка PostScript может искать по ключу в словаре и получать его значение, если такой ключ есть в таблице. PostScript всегда имеет два словаря: системный и пользовательский. Системный словарь объединяет имя каждого встроенного в язык оператора, с соответствующим ему действием. Словарь пользователя ассоциирует имена с процедурами и переменными, определенными в программе. Когда интерпретатор встречает имя, он сначала просматривает словарь пользователя, а затем системный. Если имя в словаре найдено, то выполняются соответствующие ему действия: либо объект помещается в стек, либо выполняются некоторый набор операторов. Если имя не найдено, то выдается сообщение об ошибке. Словари хранятся в стеке словарей: словарь пользователя в верху стека, системный - внизу. Таким образом слово ищется начиная с вершины стека. Программа может создать новые словари, которые будут размещены в вершине стека словарей. Словарь, находящийся в вершине стека и, следовательно, просматриваемый первым, называется текущим словарем. Переменные: Чтобы определить переменную в PostScript, ее имя и значение нужно занести в текущий словарь. Это делается с помощью оператора DEF, как в следующем примере: /name 47 def Косая черта перед именем переменной показывает, что интерпретатору следует поместить это имя в стек как литерал, а не пытаться сразу же искать его в словаре. Вслед за именем в стек заносится число 47. И наконец DEF берет оба эти объекта из стека и помещает их в текущий словарь. Второй элемент стека name становится ключом, с которым ассоциировано значение первого элемента (47). Определенное с помощью DEF значение переменной может быть изменено либо новым оператором DEF, либо другими операторами, например: /name 52 def Если дальше в программе появится строка: 13 name add то интерпретатор сделает следующее: - поместит число 13 в стек; 1 3 - найдет в стеке словарей значение для ключа name и поместит его в стек; - сложит два числа из вершины стека и поместит на их место результат. Следующий оператор умножает значение переменной name на 12: / name name 12 mul def Процедуры: Процедура в PostScript - это набор операторов, сгруппированных под общим именем. Имя процедуры является ключом в словаре, а набор операторов ассоциируется как его значение. Когда имя процедуры появляется в программе, то выполняется связанный с ним набор операторов. Процедуры в PostScript определяются точно так же, как и переменные, с тем только отличием, что набор операторов процедуры должен быть заключен в фигурные скобки. Следующая строка, например, описывает процедуру inch (дюйм), полезную для перевода дюймов в систему единиц, используемую в PostScript по умолчанию. /inch {72 mul} def Любое появление слова inch после этой строки заставит интерпретатор поместить в стек число 72, умножить его на число лежащее в стеке ниже его и поместить в стек вместо двух этих чисел результат их произведения, таким образом следующие две строки эквивалентны: 3 72 mul 3 inch Так как PostScript ориентирован на работу со стеком, естественный способ передачи параметров - размещение их в стеке. Перепишем программу рисования двух перекрывающихся областей из лабораторной работы №1: /inch {72 mul} def /box { % в стеке: x y newpath moveto 1 inch 0 rlineto 0 1 inch rlineto -1 inch 0 rlineto closepath } def /fillgray { % в стеке: уровень серого цвета setgray fill } def % Основная программа 2 inch 3 inch box .9 fillgray 2.5 inch 3.5 inch box .7 fillgray showpage 1 4 В такой записи программу уже значительно проще изменять и она более самодокументирована, чем ее первый вариант. Работа со шрифтами: Текстовые данные представлены в PostScript объектами типа string (строка). Строка может содержать любую последовательность символов, заключенную в круглые скобки. Строка может быть помещена в стек, присвоена переменной или напечатана. Однако перед тем, как строка будет помещена на текущей странице, интерпретатору PostScript необходимо указать какую гарнитуру и размер шрифта использовать при печати. Шрифт - это набор символов, имеющих единый дизайн. Дизайн конкретного шрифта называется гарнитурой. Набор гарнитур, разработанных для совместного использования, называется семейством гарнитур. Наиболее популярные гарнитуры: Таймс, Курьер, Журнальная и др. PostScript-шрифты относятся к классу векторных и, следовательно, масштабируемых шрифтов. Существующие методы описания векторных шрифтов позволяют автоматически менять размер шрифта (кегель) с минимальными искажениями его начертания при преобразовании размера. Чтобы задать шрифт, нужно выполнить следующие действия: найти описание шрифта в словаре шрифтов; отмасштабировать шрифт до нужного размера. Его размер задается минимальным расстоянием по вертикали между строками текста, необходимым, чтобы эти строки не накладывались одна на другую, например обычный шрифт часто задается высотой в 12 или 14 пунктов (напомним, что 1 пункт = 1/72 дюйма); установить отмасштабированный шрифт в качестве текущего шрифта, которым и будет печататься текст. Опрераторы для работы со шрифтами: - Name findfont - ищет в словаре шрифтов с названием FontDictionary и устанавливает шрифт с именем Name. Если шрифт найден, то ссылка на него помещается в стек для дальнейшей работы. В противном случае выдается ошибка. - Size scalefont - масштабирует текущий шрифт на величину Size. - Font setfont - определят шрифт с именем Font как текущий. - String show - рисует заданную строку на странице, используя при этом текущее состояние графики ( текущий шрифт, текущий размер шрифта, уровень серого либо цвет, текущую матрицу преобразований, текущее положение). Текущее положение определяется левой нижней точкой базовой линии текста, которая после выполнения оператора перемещается в правую позицию базовой линии текста. 1 самую5 - String bool charpath - добавляет траекторию контура строки из вершины стека к текущей. Если bool = true, то полученный результат (текст) можно использовать для заливки и отсечения, иначе нельзя. ПРИМЕР: работа со шрифтами. Пример написан с использованием процедур и показывает, как во время печати текста можно менять размер шрифта. Определим процедуру, устанавливающую шрифт нужного размера. /newsize { % в стеке размер scalefont setfont } def /getfont { /Helvetica findfont } def % Основная программа getfont 8 newsize 72 250 moveto (example) show getfont 10 newsize 72 275 moveto (example) show getfont 12 newsize 72 300 moveto (example) show showpage Эта программа напечатает три раза слово EXAMPLE шрифтом разного размера. Процедуры NEWSIZE и GETFONT можно объединить, если учесть порядок следования аргументов в стеке. (Очевидно, что в нем хранится не сам словарь шрифта непосредственно, а ссылка на него). /scaleHelv { % в стеке размер /Helvetica findfont exch % кегель в вершине стека scalefont setfont } def Теперь запись строки программы станет еще компактней: 6 scaleHelv Для печати текста часто требуются различные операции по выравниванию слов по границам страницы, выравниванию промежутков между буквами (КЕРНИНГ), чтобы напечатанный текст выглядел приятно. Для этой цели в PostScript имеется 4 варианта оператора SHOW: - ashow - при печати строки добавляет после каждого символа заданный промежуток; 1 после6 - widthshow - при печати строки добавляет заданный промежуток каждого появления некоторого символа (например, после каждого пробела); - awidthshow - является комбинацией двух предыдущих операторов; - kshow - выполняет заданную процедуру между каждой парой символов в строке. Текущий символ и символ, следующий за ним, передаются этой процедуре как аргументы. Так строка {pop pop (-) show} (World) kshow напечатает его с дефисом между каждой парой букв: W-o-r-l-d Оба символа удаляются из стека, так как данная прцедура их не использует. В основном оператор предназначен для кернинга, но может быть использован и в других целях. Используя оператор ARCTO, нарисуем какую-нибудь карточку: /clearstack { 4 { pop } repeat } def 200 300 translate 0 20 moveto 0 72 108 72 20 arcto clearstack 108 72 108 0 20 arcto clearstack 108 0 0 0 20 arcto clearstack 0 0 0 72 20 arcto clearstack fill 0.5 setgray 80 45 20 0 360 arc fill /Helvetica findfont 25 scalefont setfont 30 50 moveto (My Card) show showpage Преобразование системы координат: В PostScript не существует различия между графикой и текстом. Символ текста рассматривается как один из графических объектов, размещаемых на текущей странице. Поэтому для совмещения на ней текста и графики не требуется никаких специальных действий. Все графические операторы PostScript выполняют свои действия в пространстве пользователя, которое независимо от какого-либо физического устройства, и результат работы 1 систему7 операторов PostScript при печати автоматически преобразуется в координат устройства. Однако иногда бывает удобно выполнять графические преобразования, изменяя пользовательскую систему координат с помощью применения следующих операторов: х у translate - перенос начала координат в точку с координатами х, у. Причем, каждый следующий перенос системы координат осуществляется уже относительно предъидущей системы координат, а не относительно исходной. х rotate - поворот системы координат на заданный угол (угол в градусах отсчитывается от вертикальной оси против часовой стрелки). /neworigin { 250 150 translate 60 rotate } def /treangl { 0 0 moveto 90 0 lineto x y lineto closepath fill } def treangl neworigin treangl neworigin 2 2 scale % увеличим в два раза масштаб по осям treangl showpage Сохранение состояния графики PostScript: Состояние графики - это набор данных, которые описывают, как операторы будут влиять на текущую страницу. Пара взаимодополняющих операторов, GSAVE и GRESTORE, позволяют сохранить текущее состояние графики, а затем в нужный момент восстановить его. Это может потребоваться до и после использования оператора FILL, который очищает текущую траекторию. Если нужно продолжить рисование из какой-либо точки фигуры, заполняемой оттенком серого, то удобно просто восстановить состояние графики, сохраненное до выполнения FILL. Оператор GSAVE сохраняет копию текущего состояния графики в стеке состояния графики. Этот стек может хранить до 32-х состояний графики, включая текущее состояние. Оператор GRESTORE восстанавливает состояние графики, сохраненное в стеке самым последним. Все характеристики текущего графического состояния, включая текущий путь, цвет, уровень серого цвета, ширину линии и систему пользовательских координат возвращаются в состояние, в котором они были перед выполнением оператора GSAVE. 1 8 Задание к лабораторной работе №2 Используя материалы предыдущей лабораторной работы, написать на языке PostScript с использованием процедур программу рисования произвольной цветной композиции (поздравительной открытки), содержащей различные плоские геометрические и флористические изображения(лютики, ромашки, листики, прямоугольники, дуги, овалы и т.п.). Размеры однотипных фигур менять с помощью изменений масштабов по осям координат. (Эллипсы можно получить, изменяя при рисовании окружности масштабы по осям координат). Надписи на композиции сделать шрифтами разных типов и размеров. 1 9 Лабораторная работа №3 Тема: Программирование изображений использованием операторов ветвления и циклов. на языке PostScript с Цель работы: освоение принципов и приобретение навыков программирования сложных растровых изображений PostScript с использованием способов ритмических преобразований системы координат и графических свойств. Методические указания к лабораторной работе Прежде чем рассмотреть правила организации ветвлений и циклов, остановимся на понятии выполняемого массива. Это более формальное название объекта, который ранее был назван процедурой. Проанализируем, какая разница для PostScript между строками: 12 5 sub и { 12 5 sub } В первом случае числа 12 и 5 будут помещены в стек и выполнена операция вычитания, а во втором - эти числа и оператор SUB будут помещены в массив, который затем будет занесен в стек. Выполняемому массиву может предшествовать имя, задаваемое в виде литерала, а закрывать его может оператор DEF, который ассоциирует его с именем в текущем словаре. Выполняемый массив может использоваться также в некоторых управляющих операторах, таких как оператор IF или оператор цикла REPEAT. В этом случае выполняемый массив содержит операции, которые будут иметь место, если выполнятся соответствующие условия. Оператор if: Прежде чем рассмотреть этот, посмотрим, как записываются операции сравнения чисел. Вспомним, что в PostScript операторы сравнения следуют за сравниваемыми величинами. Оператор Значение eg = (равно) gt > (больше) ge >= (больше или равно) ne <> (не равно) lt < (меньше) le <= (меньше или равно) Логические операторы: NOT, AND, OR и XOR. Результат операции сравнения или логической операции значение TRUE или FALSE. 2 логическое0 условие {proc} if Оператор IF берет из стека логический объект, получаемый в результате вычисления условия, и выполняемый массив. Если значение логического объекта TRUE, то выполняются операции, записанные в этом массиве. Например: %%% Определяем переменные /step 15 def /rightmargin 450 def %%% Определяем функцию /checkmargin { currentpoint pop % оставляет в стеке координату х текущей точки rightmargin gt { % Если число на вершине стека больше 450 0 step % то переходим в начало следующей строки translate 0 0 moveto } if % в противном случае ничего не делаем } def Процедура получает координату текущей точки и сравнивает её со значением правой границы рабочего поля. Если условие выполняется, то происходит перенос начала координат на следующую строку. Оператор ifelse: Позволяет выбрать в зависимости от условия выполнение одной или другой последовательности операторов. Его формат: Bool {proc1} {proc2} ifelse Если значение в вершине стека равно последовательность {PROC1}, иначе - {PROC2}. TRUE, выполняется Циклы: В языке PostScript имеется три основных конструкции циклов: простой, с параметром и с условием. Простой цикл имеет следующую структуру: <количество повторений> <повторяемая процедура> repeat REPEAT берет из стека два операнда: счетчик цикла и повторяемую процедуру. Например, для очистки стека мы можем использовать следующий цикл: {pop} repeat Цикл с параметром напоминает конструкцию цикла FOR в Паскале имеет следующую структуру: 2 и1 <начальное значение счетчика цикла>< приращение>< конечное значение счетчика цикла>< повторяемую процедуру> FOR. Следует учитывать, что непосредственно перед выполнением этой процедуры FOR помещает в стек текущее значение счетчика цикла, и если он не используется, то его следует оттуда явным образом удалять(!). Следующая строка напечатает звездочку через каждые 15 единиц на странице: 0 15 450 {0 moveto (*) show } for Вторая важная особенность FOR в том, что его операнды не обязательно должны быть целыми числами. Пример использования этой особенности для возможной модификации шрифта (изображения бъемных букв): /Helvetica findfont 30 scalefont setfont /printword { 0 0 moveto (PC Magazine) show } def 200 300 translate .95 -.05 0 % начало приращения, конец {setgray printword -1.5 translate} for 1 setgray printword showpage Цикл с условием соответствует REPEAT...UNTIL в Паскале и имеет конструкцию: <выполняемая процедура> LOOP. Процедура выполняется до тех пор, пока в ней не встретится оператор EXIT, который заканчивает циклическое выполнение. Если в повторяемой процедуре нет оператора exit, то цикл будет бесконечным, например: Напишем программу рисования конечной последовательности кругов двух диаметров, центры которых лежат на прямой, параллельной оси Х. %%% Определение процедур /pagewidth 8 72 mul def % Ширина страницы /circle { % Рисование круга x y radius 0 360 arc stroke } def /new-x { % Новая позиция для следующего. круга x radius add % Это эквивалентно: х=х+radius /x exch def } def /DoLineOfCrle { % Рисуем линию из окружностей /y exch def % заносим значения из стека в переменные /radius exch def /x 0 def { % условный цикл рисования окружностей до конца страницы x pagewidth le % центр нового круга в пределах границы? {circle new-x} % да - рисуем и вычисляем новую позицию {exit} % иначе - выход из цикла ifelse } loop } def 2 2 %%%% Рисуем две линии кругов 15 200 DoLineOfCrle 45 200 DoLineOfCrle showpage Массивы: PostScript работает со сложными структурами (записями), которые называются одномерными массивами. Они определяются как набор объектов (возможно разного типа), заключенный в квадратные скобки. Так [ (PC Magazine) 1991 (сор) true] Операции внутри квадратных скобок выполняются по обычным правилам PostScript, так после вычисления [(add) 10 5 6 mul add] получим массив из двух элементов [(add) 40] . Массив может быть также определен с помощью оператора ARRAY, который берет из стека число и создает массив такой длины. 8 array Эта строка оставит в стеке массив из 8 элементов. Его элементы - NULLобъекты. Элементы массива нумеруются с нуля, что нужно учитывать при вычислении их индексов. При анализе массива интерпретатор просматривает строку слева направо. Открывающая (левая) квадратная скобка оставляет в стеке объект, называемый маркером (MARK). После маркера интерпретатор просматривает строку программы дальше и помещает в стек все встречающиеся ему объекты до правой квадратной скобки. Эта скобка является оператором, создающим массив из хранящихся в стеке объектов: от вершины до маркера. При этом маркер удаляется из стека, а массив остаётся. Массивы, строки и словари - всё это примеры объектов сложных типов. Их значения хранятся отдельно от самого объекта (то есть PostScript работает в этом случае не со значением, а с указателем на него). Для работы с элементами массивов служат операторы PUT и GET. 2 в3 Оператор PUT берет из стека три аргумента: массив, индекс элемента массиве и объект. Он помещает объект в массив в позицию, заданную индексом: /MyArray 12 array def MyArray 5 (Jerry) put У оператора GET два аргумента: массив и индекс. Он возвращает в стеке элемент массива с заданным индексом. После выполнения строки [0 1 2 3 4 5] 5 get в вершине стека будет число 4. Оператор LENGTH, возвращает длину массива (то есть число его элементов). Пример программы. которая распечатывает массив, находящийся в стеке. /LeftM 60 def /TmpString 40 string def /Helvetica findfont 11 scalefont setfont % задали шрифт /newln { currentpoint 15 sub exch pop LeftM exch moveto } def % y-15 /printarr { % в стеке массив /arr exch def % поместить массив в переменную 01 % параметры цикла: от шаг arr length 1 sub % до (ДлинаМассива - 1) { arr exch get % следующий элемент TmpString cvs % преобразуем вго в строков тип show newln % печатаем и нач. новую строку } for } def %%%%%% Основная программа %%%%% LeftM 400 moveto % печатаем отсюда % задаем массив [(Julia) % строка 15 % число /SimplName % литерал [8 3 4] % массив {NewLN} % исполняемый массив LeftM % переменная ] printarr % печатаем его showpage 2 стек4 Перед каждым выполнением цикла оператор for помещает в счетчик, который используется в качестве индекса в строке arr exch get. (В этой строке берется не сам массив из стека, а ссылка на него по имени переменной, поэтому и делается exch). Результат работы программы: Julia 15 SimplName --nostringval---nostringval-60 Как видно из примера обычные действия над массивом в PostScript достаточно утомительны. Так как наиболее частой операцией над массивом в этом языке является применение некоторой процедуры к каждому его элементу, то для этого целесообразно применить специальный оператор цикла FORALL. Предыдущий пример можно записать с его помощью более компактно: arr {30 string cvs show} forall Задание к лабораторной работе №3 Используя материалы данной и предыдущих лабораторных работ, написать на языке PostScript программу рисования круглой печати и бланка письма некоторого предприятия. 2 5 Лабораторная работа №4 Тема: Приемы низкоуровневой работы с мышью. Цель работы: Изучение структуры мыши и операций низкоуровневой работы с ней. Методические указания к лабораторной работе Мышь – периферийное устройство, подключаемое к компьютеру, которое предоставляет возможность удобного перемещения в области экрана. Эволюция мыши прошла 3 этапа: - контактные; - фотодиодные; - оптические. Первые 2 основаны на анализе частоты импульсов. В первом случае электрический импульс генерируется при соединении контактов на диске и внешнего контакта прижатого к диску. Во втором случае диск не содержит на себе контактов, но содержит вырезы по диаметру. Также в этом поколении светодиод и фотодиод светодиод испускает электромагнитный импульс, который при определенном положении диска проходит сквозь вырез и попадает на фотодиод. Фотодиод генерирует электромагнитный импульс, который далее рассматривается анализатором частоты. В третьем поколении мыши отсутствует самый популярный элемент – шарик, а также валы, диски, светодиод, фотодиод контакты. Вместо шариков в эти мышки встраивается миниатюрная фотокамера, которая постоянно, с большой скоростью, снимает изображение под мышкой, относительно мощный процессор анализирует последние несколько кадров и на основании этих данных приходит к выводу о направлении перемещения мышки. Операции работы с мышью: - сброс мыши; - включение курсора мыши; - выключение курсора мыши; - установление курсора мыши; 2 6 - определение координат и состояния клавиш мыши; - определение области перемещения, видимости курсора мыши; - задание формы курсора мыши; - определение перемещения мыши в дюймах; - подключение пользовательских процедур; Рассмотрим реализацию описанных операций на низкоуровневом языке программирования Ассемблер. Обращение к подпрограмме обрабатывающей сигнал от мыши осуществляется с помощью прерывания int 33h. Инициализация мыши: Вход: AX = 0000h Выход: AX = 0000h – если нет мыши или драйвера AX = FFFFh – есть мышь BX = 0, если число клавиш мыши ≠2 BX = 2, если число клавиш мыши = 2 BX = 3, если число клавиш мыши = 3 При начальной инициализации курсор в центре экрана, на нулевой странице и гасится. Видимость/перемещение всюду. Включение курсора мыши: Вход: AX = 0001h При включении курсора счетчик видимости становиться равным 0, происходит сброс области невидимости. Выключение курсора мыши: Вход: AX = 0002h При включении курсора счетчик видимости становиться равным -1, курсор гасится. Определение положения курсора мыши: Вход: AX = 0003h Выход: BX = 76543210 (0 - левая клавиша нажата, 1 - правая, 2 - средняя) СХ= координата Х в пикселях DХ= координата Y в пикселях Для текстового режима необходимо координаты сдвинуть на 3 2 разряда,7 т.е. разделить координаты на 8. Установка курсора мыши: Вход: АХ = 0004h СХ= координата Х в пикселях DХ= координата Y в пикселях Для текстового режима необходимо координаты умножить на 8. Определение положение курсора при нажатии клавиши мыши: Вход: АХ = 0005h ВХ = 0 – левая клавиша 1 – правая клавиша 2 – средняя клавиша Выход: АХ = состояние клавиши ВХ = количество нажатий клавиши после последнего вызова функции. СХ:DХ = координаты курсора мыши в момент последнего нажатия. Определение положение курсора при отпускании клавиши мыши: Вход: АХ = 0006h ВХ = 0 – левая клавиша 1 – правая клавиша 2 – средняя клавиша Выход: АХ = состояние клавиши ВХ = количество отпускания клавиши после последнего вызова функции. СХ:DХ = координаты курсора мыши в момент последнего отпускания. Задание диапазона движения курсора по горизонтали: Вход: АХ = 0007h 2 8 СХ = минимальная координата по Х DХ= максимальная координата по Х Задание диапазона движения курсора по вертикали: Вход: АХ = 0008h СХ = минимальная координата по Y DХ= максимальная координата по Y Задание формы курсора в графическом режиме: Вход: АХ = 0009h BХ = координаты (0-15) DХ = точки внутри графического изображения курсора, которые являются фактическим указанием положения курсора мыши на экране (0-15). ES:DX = указатель на битовое изменение курсора мыши. Задание формы курсора мыши в текстовом режиме: Вход: АХ = 000Ah BХ = тип курсора 0 – программный 1 - аппаратный СХ= маска экрана, если ВХ=0 СХ= начальная строка курсора мыши, если ВХ=1 DХ= маска курсора, если ВХ=0 DХ= конечная строка курсора мыши, если ВХ=1 Определение содержимого счетчиков перемещения: Вход: АХ = 000Вh Выход: Результат в “миках”(MicKey). СХ = количество “миков” по горизонтали DХ = количество “миков” по вертикали 2 9 Установка драйвера событий: Вход: АХ = 000Сh СХ = маска вызова, имеющая следующие биты: 0 – при перемещение мышки 1 – при нажатии левой клавиши 2 – при отпускании левой клавиши 3 – при нажатии правой клавиши 4 – при отпускании правой клавиши 5 – при нажатии средней клавиши 6 – при отпускании средней клавиши 7Fh – любое событие ES:DX = адрес драйвера, который будет обрабатывать эти события Входная информация для драйвера событий: AX = маска вызова ВХ = состояние клавиш СX, DX = координаты курсора SI, DI = относительное перемещение курсора DS = сегмент данных драйвера мыши Этот драйвер событий подключается и вызывается из драйвера мыши. Мы регистрируем в операционной системе MS-DOS собственную программу, которая будет вызываться при наступлении событий связанных с мышью. Отсюда получаем еще один способ внедрения программ. Имеется возможность установить еще один альтернативный драйвер событий (АХ = 0018h). Определение типа мыши: Вход: AХ = 0024h Выход: ВХ = версия драйвера СН = вид подключения 3 0 1 – BUS (через специализированный адаптер) 2 – SERIAL (через последовательный адаптер) 3 – Inport 4 – PS/2 (через круглый разъем) 5 – HP СL = номер прерывания, к которому подключена мышь. Определение порога удвоения скорости: Вход: АХ = 0013h Выход: DX = порог(мики/сек) По умолчанию - 64 мика/сек Установление области исключения видимости для курсора: То есть определение области, в которой курсор становится невидим. Вход: AX = 0010h СX:DX = координата левого верхнего угла SI:DI = координата правого нижнего угла. Задание к лабораторной работе №4 Написать программу, которая бы реализовывала требования, представленные в таблице 1. Пример выполнения задания представлен в приложении А. Таблица 1 - Варианты заданий к лабораторной работе №4: № ЗАДАНИЕ варианта 1 Изменить тип курсора в текстовом режиме при нажатии некоторой клавиши на клавиатуре 2 Изменить тип курсора в графическом режиме при 3 1 нажатии некоторой клавиши на клавиатуре 3 Изменять область видимости по горизонтали при каждом нажатии клавиши мыши 4 Изменять область видимости по вертикали при каждом нажатии клавиши мыши 5 Включать курсор при нажатии левой клавиши, а выключать по нажатию правой клавиши мыши 6 Выключать курсор при нажатии левой клавиши мыши, а включать по нажатию правой клавиши мыши 7 Установить курсор в правый нижний угол экрана 8 Установить курсор в левый нижний угол экрана 9 Установить курсор в правый верхний угол экрана и изменить его вид 10 Вывести на экран координаты положения курсора 11 Вывести на экран содержимое счетчиком перемещения курсора 12 Установить область невидимости курсора 13 Определить тип мыши 14 Изменять тип курсора в графическом режиме при помещении его на середину экрана 15 Выключать курсор при помещении его на середину экрана 16 Включать курсор при помещении его в точку с координатами (0,0) 17 Изменять диапазон движения курсора по горизонтали при нажатии левой клавиши мыши, а по вертикали при нажатии правой клавиши 18 Изменять диапазон движения курсора по вертикали при нажатии клавиши мыши, а по горизонтали при отпускании клавиши 19 3 2 Установить курсор в середине экрана и изменить его тип в текстовом режиме 20 Выключать курсор при нажатии клавиши мыши в точке с координатами (0,0) Контрольные вопросы 1.Каковы принципы работы контактных, бесконтактных и оптических мышей? 2.Перечислите операции работы с мышью? 3. В каких регистра храняться координаты указателя мыши? 4. Как осуществляется определение типа мыши? 5. С помощью какого проерывания обрабатывается сигнал от мыши? 3 3 Лабораторная работа №5 Тема: Работа с CD проигрывателем. Цель работы: Изучение возможностей, предоставляемых драйвером CDROM msdex. Методические указания к лабораторной работе В лабораторной работе подробно рассматриваются возможности работы с драйвером CD-ROM. Для выполнения лабораторной работы необходим драйвер CD-ROM mscdex; его функции используются для воспроизведения музыкальных компакт-дисков. Все они вызываются прерыванием 2Fh. Mscdex (Microsoft CD extension) предоставляет следующие возможности (таблица 1): Таблица 2 – возможности Mscdex Функция Аргументы Результаты Проверка AX = 1100h AL=00h не инсталлирован, наличия STACK: DADAh возможна инсталляция и драйвера STACK не изменяется; MSCDEX 01h не инсталлирован, не возможна инсталляция и STACK не изменяется; FFh инсталлирован STACK: WORD ADADh. Проверка AX = 1500h BX = количество устройств; наличия CD- BX = 0000h CX = начальная буква устройства (0=A:). ROM Получить AX = 1501h Буффер заполняется список CD ES:BX -> буффер для каждой устройств списка устройств (5 bytes BYTE – на одно устройство) DWORD – адрес драйвера буквы для устройства: буква устройства, устройства. Получить AX = 1502h CF устанавливается, если авторское имя ES:BX -> 38-байтовый устройство не CD-ROM – AX файла буфер = CX = номер устройства устройство); 000Fh (неверное CF сбрасывается в случае успеха. Получить AX = 1503h CF устанавливается, абстрактное ES:BX -> 38-байтовый устройство не CD-ROM – AX имя файла буфер = CX = номер устройства устройство); 000Fh если (неверное CF сбрасывается в случае успеха. Получить имя AX = 1504h CF устанавливается, если файла ES:BX -> 38-байтовый устройство не CD-ROM – AX документации буфер CX = номер устройства = 000Fh (неверное устройство); CF сбрасывается в случае успеха. Абсолютное AX = 1508h CF устанавливается в случае чтение ES:BX -> буфер ошибки и в AX = код ошибки CX = цифра устройства (15=неверное SI:DI = номер начального 21= не готово); сектора CF сбрасывается при успехе. устройство, DX = число секторов Запись То же Зарезервиро- AX = 150Ah То же вано Проверка AX = 150Bh BX = ADADh, если MSCDEX устройства CX = цифра устройства установлен; AX = 0000h, если устройство не поддерживается; 3 4 иначе в АХ не нулевое 3 5 значение. Получить AX = 150Ch версию BH = старшее число BL = младшее число MSCDEX Получить CD- AX = 150Dh ROM буквы ES:BX -> буфер для устройств списка букв (1 байт на Результат в буфере устройство) Направить AX = 1510h запрос CX = цифра устройства устройству ES:BX -> заголовок Описание см. Ниже запроса к устройству Для функции 1510h используется следующий формат заголовка запроса к устройству: Request_Hdr struc - размер структуры rh_Len db ? rh_Subunit db ? - номер устройства rh_Code db ? - код запроса (смотри в файле codes.inc) rh_Status dw ? – результат запроса rh_Reserved db 8 dup(?) - зарезервировано Request_Hdr ends В приложении Б приведены функции для работы с CD проигрывателем. В приложении В – листинг программы. Задание к лабораторной работе №5 3 6 В соответствии с вариантом реализовать функцию CD проигрывателя (таблица 2). Таблица 2 - Варианты заданий № Функция варианта 1 Открытие дверцы 2 Закрытие дверцы 3 Получение списка устройств 4 Блокирование дверцы и разблокирование дверцы 5 Проигрывание третьей мелодии 6 Прерывание проигрывания 7 Продолжение проигрывания 8 Позиционирование 9 Получение информации о диске 10 Проигрывание первых 30 с первой мелодии Контрольные вопросы 1. Как осуществить открытие и закрытие дверцы проигрывателя? 2. Как получить список устройств? 3. Как осуществить прерывание и продолжение проигрывания? 4. Как осуществить позиционирование и проигрывание первых N мелодий, начиная с первой мелодии? 3 7 Лабораторная работа № 6 Тема: Программирование видеокарты SuperVGA с помощью стандарта VESA. Цель работы: ознакомиться с устройством и работой типовой видеокарты и получить навыки ее программирования. Методические указания к лабораторной работе Устройство типовой видеокарты: память, контpоллеp, ЦАП и ПЗУ: Видеопамять служит для хpанения изобpажения. От ее объема зависит максимально возможное полное pазpешение видеокаpты - A x B x C, где A количество точек по гоpизонтали, B - по веpтикали, и C - количество возможных цветов каждой точки. Hапpимеp, для pазpешения 640x480x16 достаточно 256 кб, для 800x600x256 - 512 кб, для 1024x768x65536 (дpугое обозначение - 1024x768x64k) - 2 Мб, и т.д. Поскольку для хpанения цветов отводится целое число pазpядов, количество цветов всегда является степенью двойки (16 цветов - 4 pазpяда, 256 - 8 pазpядов, 64k - 16, и т.д.). Видеоконтpоллеp отвечает за вывод изобpажения из видеопамяти, pегенеpацию ее содеpжимого, фоpмиpование сигналов pазвеpтки для монитоpа и обpаботку запpосов центpального пpоцессоpа. Для ускоpения вывода изобpажения на экpан монитоpа и снижения частоты конфликтов пpи обpащении к памяти со стоpоны видеоконтpоллеpа и центpального пpоцессоpа пеpвый имеет отдельный буфеp, котоpый в свободное от обpащений ЦП вpемя заполняется данными из видеопамяти; внутpенняя шина данных контpоллеpа обычно шиpе внешней (32, 64 или 128 pазpядов пpотив 16 или 32). Если конфликта избежать не удается - видеоконтpоллеpу пpиходится задеpживать обpащение ЦП к видеопамяти, что снижает пpоизводительность системы; для исключения подобных конфликтов в pяде каpт пpименяется так называемая двухпоpтовая память (VRAM, WRAM), допускающая одновpеменные обpащения со стоpоны двух устpойств. Многие совpеменные видеоконтpоллеpы является потоковыми - их pабота основана на создании и смешивании воедино нескольких потоков гpафической инфоpмации. Обычно это основное изобpажение, на накладывается изобpажение аппаpатного куpсоpа мыши и 3 котоpое8 отдельное изобpажение в пpямоугольном окне, поступающее, напpимеp, от TV-пpиемника или декодеpа MPEG. Видеоконтpоллеp с потоковой обpаботкой, а также с аппаpатной поддеpжкой некотоpых типовых функций называется акселеpатоpом или ускоpителем, и служит для pазгpузки ЦП от pутинных опеpаций по фоpмиpованию изобpажения. ЦАП (цифpоаналоговый пpеобpазования пpеобpазователь, pезультиpующего потока DAC) данных, служит для фоpмиpуемого видеоконтpоллеpом, в уpовни интенсивности цвета, подаваемые на монитоp. Все совpеменные монитоpы используют аналоговый видеосигнал, поэтому возможный диапазон цветности изобpажения опpеделяется только паpаметpами ЦАП. Большинство ЦАП имеют pазpядность 8x3 - тpи канала основных цветов (кpасный, синий, зеленый, RGB) по 256 уpовней яpкости на каждый цвет, что в сумме дает 16.7 млн. цветов. Обычно ЦАП совмещен на одном кpисталле с видеоконтpоллеpом, однако это делается в основном для недоpогих ЦАП, поскольку близкое соседство с интенсивно pаботающими схемами отpицательно влияет на стабильность pаботы ЦАП. Видео-ПЗУ (Video ROM) - постоянное запоминающее устpойство, в котоpое записаны видео-BIOS, экpанные шpифты, служебные таблицы и т.п. ПЗУ не используется видеоконтpоллеpом напpямую - к нему обpащается только центpальный пpоцессоp, и в pезультате выполнения им пpогpамм из ПЗУ пpоисходят обpащения к видеоконтpоллеpу и видеопамяти. Hа многих совpеменных каpтах устанавливаются электpически пеpепpогpаммиpуемые ПЗУ (EEPROM, Flash ROM), допускающие пеpезапись пользователем под упpавлением специальной пpогpаммы из комплекта каpты. ПЗУ необходимо только для пеpвоначального запуска адаптеpа и pаботы в pежиме MS DOS, Novell Netware и дpугих ОС, pаботающих пpеимущественно в текстовом pежиме; опеpационные системы Windows, OS/2 и им подобные, pаботающие чеpез собственные видеодpайвеpы, не используют ПЗУ для упpавления адаптеpом, либо используют его только пpи 3 выполнении9 пpогpамм для MS-DOS. Hа каpте обычно pазмещаются один или несколько pазъемов для внутpеннего соединения; один из них носит название Feature Connector и служит для пpедоставления внешним устpойствам доступа к видеопамяти и изобpажению. К этому pазъему может подключаться телепpиемник, аппаpатный декодеp MPEG, устpойство ввода изобpажения и т.п. Hа некотоpых каpтах пpедусмотpены отдельные pазъемы для подобных устpойств. Итак для вывода изображения (да и текста тоже) на экран монитора компьютера служат специальные устройства - ВИДЕОКОНТРОЛЛЕРЫ или ВИДЕОАДАПТЕРЫ. Они могут быть реализованы в виде отдельной платы или же размещаться на материнской плате. Кроме того, любой из режимов представления цвета контроллер поддерживает не вообще, а только для некоторого набора допустимых значений количества пикселов на экране монитора. Величина, которая объединяет в себе количество строк на экране и число точек в строке называется РАЗРЕШАЮЩЕЙ СПОСОБНОСТЬЮ (или просто РАЗРЕШЕНИЕМ). А совокупность разрешающей способности и формата представления цвета носит название ВИДЕОРЕЖИМА. Первые видеоплаты персональных компьютеров, например, позволяли выводить 200 строк по 320 точек, каждая из которых могла быть одного из четырех цветов. В последние два десятка лет эти устройства бурно развивались (как, впрочем, и другие компоненты персональных компьютеров). Пропустим первые достижения в этой области и остановимся на видеорежиме "цветного" VGA (Video Graphics Adapter), называемого еще MCGA (Multi Color Graphics Adapter), известного программистам также по номеру 13h (шестнадцатиричному). Это был (и есть) 256-цветный режим с разрешением 320x200 точек. Все ранние видеорежимы, включая и MCGA, появлялись достаточно медленно, по одному и, в силу этого, успевали стандартизироваться. Существование стандарта означало, что с режимами, 4 поддерживаемыми0 конкретным видеоадаптером, можно было работать стандартным образом, независимо от того, кто эту плату выпустил. Высококачественные видеорежимы: В дальнейшем, фирмы-производители развивали более совершенные видеоадаптеры, получившие название SuperVGA. И все было бы хорошо, но каждый производитель обеспечивал собственный интерфейс к своим видеоадаптерам, а эти интерфейсы не были совместимы между собой. Естественно, такое положение не могло существовать долго. Организация под названием VESA (Video Electronics Standards Association) разработала и распространила специальный стандарт на интерфейс к SuperVGA видеоадаптерам. Версия 1.2 этого стандарта датирована 22 октября 1991 года. Версия 1.1 - июнем 1990 года. Стандарт обеспечивает набор функций, которые прикладная программа может использовать для получения информации относительно возможностей и характеристик специфической реализации SuperVGA и управления операциями таких аппаратных средств в терминах инициализации видеорежима и доступа к видеопамяти. Функции реализованы как расширение функций VGA видео BIOS'а и доступны через прерывание 10h. Сначала производители аппаратных средств и независимые разработчики стали снабжать видеоадаптеры специальными драйверами, обеспечивающими выполнение функций стандарта VESA. Появились также так называемые "универсальные" драйверы, типа univesa, univbe и т.п., которые позволяли работать с более или менее широким набором видеоадаптеров. Uni сокращение от слова универсальный; VESA - понятно, что такое; VBE - VGA BIOS Extension (расширение VGA BIOS). Одновременно производители аппаратных средств начали встраивать поддержку функций стандарта VESA в видеоBIOS своих устройств. 4 1 Видеорежимы SuperVGA: Номера видеорежимов стандартного VGA занимают один байт и имеют диапазон от 00h до 13h. В диапазоне от 14h до 7Fh размещаются так называемые OEM-специфичные расширенные видеорежимы SuperVGA. (OEM - Original Equipment Manufacturer - Основной Изготовитель Оборудования). Номера от 80h до FFh не используются, так как старший бит в стандартном VGA используется как флаг очистки видеопамяти при инициализации видеорежима. Видеопамять очищается, когда этот бит равен нулю. VESAстандарт SuperVGA отводит два байта для номера видеорежима. Старший байт содержит значение 01h. Младший бит в нем – признак режима VESA, остальные пока не используются (зарезервированы). Младший байт конкретизирует видеорежим. Таким образом полный (двухбайтный) номер видеорежима VESA может лежать в диапазоне от 100h до 17Fh. Старший бит в младшем байте как и раньше служит флагом очистки видеопамяти при инициализации видеорежима. В версии стандарта 1.2 (октябрь 91) определено 28 номеров от 100h до 11Bh (таблицы 1 и 2). Таблица 3 - Text SuperVGA Video Modes Номер режима Столбцы Строки 108h 80 60 109h 132 25 10Ah 132 43 10Bh 132 50 10Ch 132 60 4 2 Таблица 3 - Graphics SuperVGA Video Modes Номер режима Разрешение Глубина цвета Видеопамять 100h 640x 400 256 250 K =~0.24 M 101h 640x 480 256 300 K =~0.29 M 102h 800x 600 16 234 K =~0.23 M 103h 800x 600 256 468.75K=~0.46 M 104h 1024x 768 16 384 K = 0.35 M 105h 1024x 768 256 768 K = 0.75 M 106h 1280x1024 16 640 K = 0.625M 107h 1280x1024 256 1280 K = 1.25 M 10Dh 320x 200 32K (1:5:5:5) 125 K =~0.12 M 10Eh 320x 200 64K (5:6:5) 125 K =~0.12 M 10Fh 320x 200 16M (8:8:8) 187.5K =~0.18 M 110h 640x 480 32K (1:5:5:5) 600 K =~0.59 M 111h 640x 480 64K (5:6:5) 600 K =~0.59 M 112h 640x 480 16M (8:8:8) 900 K =~0.88 M 113h 800x 600 32K (1:5:5:5) 937.5K =~0.92 M 114h 800x 600 64K (5:6:5) 937.5K =~0.92 M 115h 800x 600 16M (8:8:8) 1406.25K=~1.37 M 116h 1024x 768 32K (1:5:5:5) 1536 K = 1.5 M 117h 1024x 768 64K (5:6:5) 1536 K = 1.5 M 118h 1024x 768 16M (8:8:8) 2304 K = 2.25 M 119h 1280x1024 32K (1:5:5:5) 2560 K = 2.5 M 11Ah 1280x1024 64K (5:6:5) 2560 K = 2.5 M 11Bh 1280x1024 16M (8:8:8) 3840 K = 3.75 M 4 3 В стандарте предусмотрены как графические (таблица 2), так и текстовые (таблица 1) видеорежимы высокого разрешения. Самое высокое качество графики обеспечивает режим 11Bh (1280x1024 x16M цветов), самый мелкий текстовый режим 10Ch (132символа на 60строк). Конечно, не все видеоплаты могут поддерживать все режимы. Здесь существует ограничение, связанное с объемом видеопамяти. Действительно, для самого качественного графического видеорежима 11Bh требуется 1280x1024x3 = 3.75 M видеопамяти (3 байта на каждый пиксел). Самые слабые видеоплаты SuperVGA имеют всего 512 К видеопамяти, и для них могут быть доступны только видеорежимы до 1024x768 x 16 цветов (384 K), 800x600 x 256 цветов (~470 K), 320x200 x 16M цветов (187.5 K). Наиболее распространенные сейчас мегабайтные платы, в принципе, позволяют: для 16 цветов - 1280x1024 ( 640 K), для 256 цветов - 1024x 768 ( 768 K), для 64K цветов - 800x 600 (~940 K), для 16M цветов - 640x 480 ( 900 K). Конечно, не следует думать, что видеоадаптер будет поддерживать все доступные по размеру его памяти видеорежимы. Это не так. Для поддержки того или иного видеорежима необходимо, чтобы в драйвере адаптера были записаны соответствующие программы, а для этого нужно место в 4 ПЗУ4 BIOS'a. Список поддерживаемых видеорежимов можно получить, вызвав функцию 00h видео BIOS'a. Окна видеопамяти: Процессор ПК не может непосредственно обращаться к видеопамяти. Для операций с ней предусмотрен специальный механизм "отображения" видеопамяти в сегменте адресного пространства, доступном процессору. Обычно этот сегмент начинается с адреса A000h, но может быть и по адресу B000h. Размер сегмента при 16-ти разрядной адресации - 64 К. Для видеорежимов VGA и более ранних этого сегмента хватало для отображения всей видеопамяти. Однако даже самый плохонький режим SuperVGA требует в два раза больше памяти (не говоря уже о 4-х мегабайтном монстре 1280x1024 при почти 17 миллионах цветов). Было принято решение, подобное тому, которое сделала в свое время фирма Intel для адресации с помощью 16-ти разрядных регистров (которые дают только 64К) памяти до 1 Мегабайта. Видеопамять отображается на 64-х килобайтный сегмент не вся, а частями, называемыми страницами. Необходимо только указать адрес начала отображаемой страницы видеопамяти. Этот адрес не может быть произвольным. Он определяется с точностью до некоторого значения, называемого GRANULARITY (грэньюлэрети), по-русски – СТЕПЕНЬ ДЕТАЛИЗАЦИИ.. Например, если для работы с изображением вам нужны его куски по 40 килобайт (0-40, 40-80 и т.д.), при степени детализации равной 64K второй кусок будет находиться в двух страницах видеопамяти (40-64 и 64-80), и вам необходимо будет их постоянно переключать, а при степени детализации равной или меньшей 32K вы сможете каждый кусок отобразить на свою видеостраницу (первый на 0-64, второй на 32-96), и, соответственно, не переключать постоянно страницы при работе со вторым куском. Окон отображения видеопамяти может быть два, и в этом случае можно работать одновременно с двумя участками видеопамяти. Это бывает полезно, например, при копировании части изображения из одного места в другое. Вызовы BIOS расширенного VGA: 4 5 Для работы с BIOS видеоадаптера SuperVGA в настоящее время существует 9 операций, которые сгруппированы под одним номером функции 4Fh прерывания INT 10h. Как обычно, номер функции передается программе обработки в регистре AH, а номер операции или подфункции в регистре AL. Эти операции таковы: Операция 00h - Получить общую информацию о SuperVGA. Операция 01h - Получить информацию о режиме SuperVGA. Операция 02h - Установить SuperVGA видеорежим. Операция 03h - Получить текущий видеорежим. Операция 04h - Сохранение / Восстановление SuperVGA видеосостояния. Операция 05h - Управление окнами видеопамяти. Операция 06h - Установить / Получить длину логической строки. Операция 07h - Установить / Получить начало экрана. Операция 08h - Управление цифро-аналоговым преобразователем. Если видео BIOS поддерживает VESA стандарт SuperVGA, онпостарается выполнить операцию, а если нет, то ничего непроизойдет. Как же определить, выполнена операция или нет? Каждая функция возвращает статусную информацию в регистре AX. В младшем байте (регистр AL) будет содержаться 4Fh, если BIOS поддерживает VESA стандарт, любое другое число говорит о том, что этот стандарт не поддерживается. Старший байт (регистр AH) сообщает о том, выполнена или нет конкретная операция. В случае успешного выполнения AH=0. Теперь рассмотрим некоторые наиболее часто используемые операции VESA расширения видео BIOS. 4 6 Операция 00h - Получить общую информацию о SuperVGA: Цель этой функции понятна из ее названия. В результате ее выполнения вызывающая программа получит информацию относительно общих возможностей данного адаптера SuperVGA. Эта информация будет возвращена в блоке размером 256 байт, расположенном по указанному при вызове функции адресу. Для выполнения операции необходимо сделать следующее: 1) поместить в регистр AX код 4F00h (0-я подфункция функции 4Fh); 2) поместить в регистры ES:DI адрес 256-ти байтного участка памяти, в который будет возвращена информация; 3) вызвать INT 10h. В результате выполнения (или невыполнения) операции в регистре AX появится статусная информация. В случае успешного выполнения это будет 004Fh (старший байт равен 0 - успешное выполнение, младший равен 4Fh VESA стандарт поддерживается). По адресу, указанному в регистрах ES:DI будет размещен блок информации о SuperVGA, ради которой, собственно говоря мы и вызывали эту функцию. Этот блок имеет следующую структуру: VgaInfoBlock STRUC VESASignature char[4] 'VESA' ; 4 байта сигнатуры (текст "VESA") VESAVersion word ? ; номер версии стандарта VESA OEMStringPtr dword ? ;дальний указатель на строку ;определения изготовителя платы ; возможности DAC Capabilities byte[4] ? VideoModePtr dword ? ;указатель на список номеров ;поддерживаемых SuperVGA режимов TotalMemory word Reserved ? byte[236] ? ; объем памяти на плате VGA ; Резерв 4 7 VgaInfoBlock ENDS Операция 01h - Получить информации о режиме SuperVGA: Эта функция возвращает информацию об определенном SuperVGA видео режиме. Функция заполняет блок информации по адресу, определяемому вызывающим оператором. Размер блока информации 256 байт. Кое-что из этой информации неявно определяется номером режима VESA. Для выполнения операции необходимо сделать следующее: 1) поместить в регистр AX код 4F01h (1-я подфункция функции 4Fh); 2) поместить в регистр СX номер поддерживаемого платой видеорежима; 3) поместить в регистры ES:DI адрес 256-ти байтного участка памяти, в который будет возвращена информация; 4) вызвать INT 10h. В результате выполнения (или невыполнения) операции в регистре AX появится статусная информация, о которой мы уже говорили. В случае успешного выполнения это будет 004Fh (старший байт равен 0 - успешное выполнение, младший равен 4Fh - VESA стандарт поддерживается). По адресу, указанному в регистрах ES:DI будет размещен блок информации о режиме SuperVGA, ради которой, собственно говоря мы и вызывали эту функцию. Наиболее важные поля этого блока таковы (таблица 3): Таблица 4 - Важные поля блока информации о видеорежиме Поле Длина в Смещение в Описание байтах байтах WinAAttributes 1 2 атрибуты окна A WinBAttributes 1 3 атрибуты окна В WinGranularity 2 4 степень детализации окна, 4 8 в Кб WinSize 2 6 размер окна, в Кб WinASegment 2 8 сегмент начала окна A WinBSegment 2 10 сегмент начала окна B WinFuncPtr 4 12 адрес функции прямой работы с окнами BytesPerScanLine 2 16 Количество байт в логической строке Xresolution 2 18 Горизонтальное разрешение Yresolution 2 20 вертикальное разрешение XcharSize 1 23 ширина символа YcharSize 1 23 высота символа NumberOfPlanes 1 24 число плоскостей видеопамяти BitsPerPixel 1 25 количество бит на пиксел Поля WinAAttributes и WinBAttributes показывают существуют ли окна и можно ли читать из них и писать в них: бит 0 показывает существование окна; бит 1 показывает что окна доступно для чтения; бит 2 показывает что окно доступно для записи. Таким образом, если значение этого поля равно 3, то окно существует и доступно только для чтения; если равно 5 – существует и доступно только для записи; если равно 7 - окно существует и доступно и для чтения, и для записи. Поле WinFuncAddr определяет адрес функции для прямой работы 4 с9 окнами видеопамяти CPU. Прямой вызов обеспечивает более быстрое выполнение операций, чем работа через прерывание INT 10h. Следует иметь в виду, что этот адрес может быть различным для каждого из видеорежимов. Если значение этого поля равно NULL, то прямого доступа к функциям управления окнами нет и для этих целей следует использовать функцию с номером 05h. Поле NumberOfPlanes определяет число плоскостей видеопамяти. Для 16ти цветных режимов это число равно 4, в других случаях - 1. Поле BitsPerPixel показывает число бит, определяющих цвет одного пиксела. Для 16-ти цветных режимов это число равно 4, для 256 цветов - 8, для режимов HiColor - 16 и для TrueColor - 24. Назначение остальных полей ясно из таблицы. Операция 02h - Установить SuperVGA видеорежим: Эта функция инициализирует видеорежим. Вызывается она обычным образом. В регистре BX следует указать номер устанавливаемого режима. Старший бит при этом интерпретируется как флаг очистки видеопамяти (0 очищать, 1 - нет). В результате выполнения (или невыполнения) операции в регистре AX появится статусная информация. Все другие регистры сохраняются. Операция 03h - Получить текущий видеорежим: Эта функция возвращает номер текущего видеорежима в регистре BX, в регистре AX - статус. Остальные регистры не меняются. Операция 05h - Управление окнами видеопамяти: Функция устанавливает или получает положение отображаемого окна в видеопамяти. При вызове регистр BL содержит номер окна (0 – окно A, 1 - окно B), значение регистра BH определяет вид операции (0 - установить, 1 - получить текущее положение). В регистре DX задается (для 5 операции0 установки) или возвращается (для операции получения текущего положения) положение отображаемого окна в видеопамяти. Это положение задается в величинах GRANULARITY (степень детализации). Чтобы использовать эту функцию правильно, необходимо предварительно определить размер, степень детализации и адрес отображаемых окон с помощью функции 01h (получение информации о режиме SuperVGA). К этой функции бывает возможен и прямой доступ, дающий более быстрое выполнение. Адрес функции BIOS может быть получен при использовании функции 01h (получение информации о режиме SuperVGA). Поле WinFuncAddr в ModeInfoBlock содержит адрес этой функции. Перед прямым вызовом функции надо определить только входные параметры в BH, BL, и DX (для установки окна), и нет необходимости загружать AH и AL. Задание к лабораторной работе №6 Выполнить задание в соответствии с вариантом задания, представленного в таблице 4. Таблица 4 – Варианты заданий к лабораторной работе 1 Читать и выводить на экран полную информацию о SuperVGA адаптере 2 Позволять в диалоговом режиме выбрать и установить видеорежим 3 Читать и выводить на экран информацию об установленном режиме SuperVGA 4 Выводить на экран информацию о количестве видеопамяти 5 Выводить и на экран информацию о версии стандарта VESA и о количестве видеопамяти 6 Выводить информацию о видеоадаптере 5 1 7 Выводить информацию о ЦАП 8 Выводить сведения о видеорежимах: номер, разрешение, глубина цвета 9 Выводить сведения о видеорежимах: номер, глубина цвета, степень детализации 10 Выводить сведения о видеорежимах: номер, разрешение, начало сегмента окна А, начало сегмента окна В 11 Выводить сведения о видеорежимах: номер, разрешение, ширину и высоту символов 12 Выводить сведения о видеорежимах: начало сегмента окна А, начало сегмента окна В и их атрибуты 13 Выводить сведения о видеорежимах: номер, степень детализации, размер окна 14 Выводить сведения о видеорежимах: номер, вертикальное и горизонтальное разрешение 15 Выводить сведения о видеорежимах: номер режима, число плоскостей видеопамяти и количество бит на пиксель 16 Установить видеорежим 800*600 с глубиной цвета = 256 17 Установить видеорежим 400*300 с глубиной цвета = 24 18 Выводить сведения о видеорежимах: номер, ширину и высоту символов, горизонтальное разрешение 19 Выводить полную информацию о видеорежимах и сведения о количестве видеопамяти 20 Выводить информацию о ЦАП и количестве видеопамяти 5 2 5 3 Лабораторная работа №7 Тема: Загружаемые символьные наборы Цель работы: освоение принципов и приобретение навыков работы с загружаемыми символьными наборами. Методические указания к лабораторной работе В пеpвых адаптеpах MDA и CGA можно в текстовых режимах отображать только те символы, которые определены в таблице, расположенной в ПЗУ знакогенеpатоpа в составе адаптера. Такой тип знакогенеpатоpа не pассчитан на использование таблицы опpеделений символов из ЗУПВ, называемой загpужаемым шpифтом (loadable font). В новых адаптеpах EGA, MCGA, VGA в текстовых pежимах допускается вывод на экpан символов, опpеделения котоpых загpужаются в конкpетную область ЗУПВ. Таблицы шpифтов: Текстовый знакогенератор во всех видеосистемах ссылается на резидентную в памяти таблицы шpифтов, котоpые должны лежать в предопределенном месте памяти, чтобы текстовый знакогенеpатоp мог получить к ним доступ. Таблицы шpифтов в ПЗУ: В адаптеpах MDA, CGA и Hercules таблица шpифтов находится в ПЗУ вне адресного пространства CPU. Только аппаратный знакогенератор имеет туда доступ. Следовательно, наборы символов, отображаемые в текстовых режимах, программно не контролируются. На EGA, знакогенератор использует таблицу, находящуюся в ЗУПВ, а не в ПЗУ. BIOS содержит встpоенные таблицы шpифтов, MCGA и VGA которыми инициализируется ЗУПВ знакогенератора пpи задании текстовогоо режима с помощью функции 00h пpеывания INT 10h. Поскольку адаптеpы могут устанавливать текстовые режимы различным вертикальным разрешением, размеры умалчиваемых шpифтов оказываются переменным (см. рис. 1). с таблиц 5 4 200-строчные режимы: CGA 200-строчные текстовые режимы используют 8x8 матрицу символов. В 80x25 текстовом режиме экран имеет ширину в 604 пикселей, в режиме 40x25 ширина 320 пикселей. Хотя CGA использует тот же набор символов и шрифтов в текстовом и графических режимах, определение символов для текстовых режимов расположено в выделенном ROM, доступном только аппаратному генератору символов. Адаптер Видео режим Символьная матрица (ширина на высоту в пикселях) ____________________________________________________________________ MDA, HGC Monochrome 9x14 CGA 40x25 16-color 8x8 80x25 16-color 8x8 80x25 16-color 8x8 (200-line resolution) EGA 8x14 (350-line resolution) MCGA VGA 80x25 monochrome 9x14 40x25 16-color 8x16 80x25 16-color 8x16 40x25 16-color 8x8 (200-line resolution) 8x14 (350-line resolution) 9x16 (400-line resolution) 80x25 16-color 8x8 (200-line resolution) 8x14 (350-line resolution) 9x16 (400-line resolution) 80x25 monochrome 9x14 (350-line resolution) 9x16 (400-line resolution) HGC+ 80x25 monochrome 9x14 InColor Card 80x25 16-color 9x14 ____________________________________________________________________ Рисунок 1 - Символьные матрицы для текстовых pежимов 5 5 350-строчные режимы: В 350-строчном текстовом режиме символы определяются в матрицах на MDA и Hercules адаптерах 8x14. Снова таблица определения символов расположена в ROM вне адресного пространства CPU, что выделено аппаратному горизонтальное генератору символов. разрешение 720 Поскольку пикселей, на этих каждый 8x14 адаптерах символ в действительности отображается в матрице шириной 9 пикселей. Таким образом, каждая строка на экране содержит 720/9 или 80 символов. Если символы определены в ROM в матрице 8x14, но отображаются в матрице 9x14, то откуда берутся остальные пиксели? Аппаратный генератор символов в MDA, плате Hercules, EGA и VGA (в монохромном режиме) добавляет дополнительный пиксель с права каждой строки восьмого пикселя в каждом символе. Для всех оставшихся кодов символов дополнительный пиксель отображается с атрибутом фона. Поскольку девятый (самый правый) пиксель в блоке графических символов является копией восьмого, эти символы могут использоваться для рисования горизонтальных линий. Все другие отображаемые символы отделяются друг от друга девятым пикселем. В результате изображение менее скучено, чем без дополнительного пространства. 400-строчные режимы: Умалчиваеммые текстовые режимы и MCGA и VGA имеют 400-строчное вертикальное разрешение. Символы, используемые в этих режимах определены в матрице 8x16. На VGA символы 8x16 отбражаются в матрице 9x16, так же как на MDA или EGA с монохромным дисплеем. Таблицы шpифтов ЗУПВ: Адаптеpы EGA, VGA, MCGA имеют встpоенный знакогенератор, который использует таблицу шpифтов, текстовый расположенную в предопределенной области ЗУПВ и в адpесном пpостpанстве пpоцессоpа. Зная pазмещение этого ЗУПВ и его фоpмат, можно писать программы, которые читают или обновляют таблицы шpифтов. В текстовых режимах на EGA и VGA, видеобуфер организован 5 как6 четыре параллельных банкa памяти, как и в графических режимах. Начальный адpес видеобуфеpа отобpажается на адpес В800:0000h.Однако в текстовом режиме отображаемые данные содержатся только в банках 0 и 1 (см. рис.2). Определение символов Байты атрибут Банк 4 Коды символов Банк 2 B800:0000 или B000:0000 Банк 1 Банк 0 Рисунок 2 - Видеобуфеp адаптеpов EGA и VGA в текстовых pежимах Четные байты (коды символов) в адресном пространстве CPU расположены в банке 0, а нечетные байты (байты атрибутов) расположены в банке 1. Это распределение невидимо для CPU; CRTC внутренне транслирует нечетные адреса в смещение банка 1, а четные адреса ссылаются на банк 0. Текстовый знакогенератор использует набор 256-символьных таблиц, сохраняемых в банке 2. EGA поддерживает четыре таких таблицы (см. рис. 3), VGA поддерживает восемь (см. рис. 4). Каждая таблица содержит 256 32батовых битовых шаблонов, так что максимальная высота каждой символьной матрицы 32 стpоки-pазвеpтки. Когда отображаемая матрица символа меньше 32 стpок, генератор игнорирует остальные байты в каждом определении символов. На EGA каждая из четырех таблиц определения символов начинается на границе 16 KB. Поскольку используется только 8 KB (256 символов * 32 байт на символ), следующие 8 KB RAM не используются. На VGA эти неиспользуемые области в банке 2 могут содержать дополнительные определения символов. При написании приложений, которые должны запускаться и на EGA и на VGA, вы должны избегать использования дополнительных таблиц потому, что EGA их не поддерживает. (Не используется) 256 определений символов C000H (Не используется) Смещение 8000H 256 определений символов (Не используется) 4000H 256 определений символов (Не используется) 256 определений символов 0000H Рисунок 3 - Знакогенеpатоp в банке 2 адаптеpа EGA Е000H 256 определений символов 256 определений символов C000H A000H Смещение 8000H 256 определений символов 256 определений символов 256 определений символов 6000H 4000H 2000H 256 определений символов 256 определений символов 256 определений символов 0000H Рисунок 4 - Знакогенератор в банке 2 адаптеpа VGA банке 2 5 этих7 5 8 Замена знакогенеpатоpа в ЗУПВ: Для копирования таблицы определения символов в банк 2 видео памяти, вы должны программировать и регистр маски банка в секвенсе pе (Sequencer's Memory Mode) и регистр pежима памяти (Map Mask), так же как регистры гpафического контpоллеpа (Graphics Controller's Mode) и pежима памяти (Miscellaneous), что бы сделать банк 2 непосредственно адресуемым. Затем вы можете копировать определения символов в любую доступную область таблицы в банке 2. Потом вы можете обновить банк 2, восстановив регистры Sequencer и Graphics Controller значениями соответствующими используемому текстовуму режиму. 'Listing 1' - программирование регистров Sequencer и Graphics Controller на EGA и VGA для того, чтобы сделать RAM символьного генератора в банке 2 доступным. 'Listing 2' - это вторая процедура, которая восстанавливает регистры Sequencer и Graphics Controller в умалчиваемое значение текстового режима. TITLE 'Listing 1' NAME CGenModeSet PAGE 55,132 ; ; Name: CGenModeSet ; ; Прямой доступ к EGA и VGA символьному генератору RAM ; ; Caller: Microsoft C: ; ; void CGenModeSet(); ; DGROUP _TEXT GROUP _DATA SEGMENT byte public 'CODE' ASSUME cs:_TEXT,ds:DGROUP _CGenModeSet PUBLIC _CGenModeSet PROC near push mov push bp bp,sp si ; сохранить регистры вызвавшего 5 9 ; Программирование Sequencer cli mov mov mov L01: ; запретить прерывания dx,3C4h ; адрес порта Sequencer si,offset DGROUP:SeqParms cx,4 lodsw out dx,ax loop L01 sti ; AH := значение для регист;ра Sequencer ; AL := номер регистра ;программирование регистра ;разрешение прерываний ; Программирование Graphics Controller L02: ;DX := 3CEH (адрес порта ; Graphics Controller) mov si,offset DGROUP:GCParms mov cx,3 lodsw ;программирование Graphics ;Controller out dx,ax loop L02 _CGenModeSet mov dl,0CEh pop pop ret si bp ENDP _TEXT ENDS _DATA SEGMENT word public 'DATA' ; Формат параметров: Младший байт: Номер регистра ; Старший байт: Значение для регистра SeqParms DW DW DW DW 0100h 0402h 0704h 0300h ;сброс синхронизации ; CPU пишет только в план 2 ; последовательная адресация ; очистка сброса синхронизации GCParms DW DW DW 0204h 0005h 0006h ; выбрать банк 2 для чтения CPU ; запретить четную адресацию ; план начинается с A000:0000 _DATA END ENDS 6 0 TITLE 'Listing 2' NAME CGenModeClear PAGE 55,132 ; ; Name: CGenModeClear ; ; Восстанавливает текстовый режим EGA или VGA после ; доступа к символьному генератору RAM ; ; Caller: Microsoft C: ; ; void CGenModeClear(); ; DGROUP _TEXT GROUP _DATA SEGMENT byte public 'CODE' ASSUME cs:_TEXT,ds:DGROUP PUBLIC _CGenModeClear _CGenModeClear PROC near push mov push ; сохранить регистры вызвавшего bp bp,sp si ; Программирование Sequencer cli mov mov mov L01: ; запретить прерывания dx,3C4h ; адрес порта Sequencer si,offset DGROUP:SeqParms cx,4 lodsw out dx,ax loop L01 sti ; AH := значение для регист; ра Sequencer ; AL := номер регистра ; программирование регистра ; разрешение прерываний ; Программирование Graphics Controller mov mov mov L02: ; DX := 3CEH (адрес порта ; Graphics Controller) si,offset DGROUP:GCParms cx,3 dl,0CEh ; программирование Graphics ; Controller lodsw out dx,ax loop L02 cmp al,7 jne L03 mov L03: pop ; переход если не монохром; ный режим ax,0806h out dx,ax si pop ret bp 6 1 ; AH := номер функции INT 10H ; получить видео режим mov ah,0Fh int 10h ; программирование Graphics ; Controller ; на начало плана с B000:0000 _CGenModeClear ENDP _TEXT ENDS _DATA SEGMENT word public 'DATA' ; Формат параметров: Младший байт: Номер регистра ; Старший байт: Значение для регистра SeqParms DW DW DW DW DW DW DW _DATA 0100h 0402h 0704h 0300h 0204h 0005h 0006h ; сброс синхронизации ; CPU пишет только в план 2 ; последовательная адресация ; очистка сброса синхронизации GCParms ; выбрать план 2 для чтения CPU ; запретить четную адресацию ; план начинается с A000:0000 ENDS END Восстановление содержимого регистров секвенсера и графического контроллера производится так же , как их программирование в приведенном фрагменте. После подготовки регистров секвенсера контроллера для прямой адресации банка 2 видео буфера и к графического нему можно обращаться обычным образом, как к стандаpтной области памяти в адpесном пpостpанстве поцессоpа. таблицу опpеделений В следующей программе показано как загpузить символов котоpого находится в pегисте BX. из файла, системный номеp (handle) Пpедполагается, что pегистpы ES:DI адpесуют нужную область банка 2 видеобуфеpа (напpимеp, А000:0000h), а в pегистpе SI находится чмсло байт в опpеделении каждого символа. В данном фpагменте используется функция 3Fh пpеpывания INT 21h ОС, 6 котоая2 осуществляет считывание байт (их число задается в pегистpе CX) из файла, системный номеp котоpого находится в pегистpе BX, в область памяти , адpесуемую pегистpами DS:DX. После ее выполнения в pегистpе АХ возвpащается фактическое число считанных байт. ;Очистка ЗУПВ для таблицы опеделений символов mov dx,di ;Соханить адpес ЗУПВ в DX mov cx,256x32/2 ;В CX число слов xor ax,ax ;сpбосить pегистp AX rep stosw ;очистить область ЗУПВ ;Загpузить опеделения символов из файла mov cx,256 ;В файле опpеделений 256 символов push es ;Регистp DS адpесует pop ds ;банк 2 видеобуфеpа ;Начало цикла пеpедачи табл. Next: xchg cx.si ;сохp. счетчик в SI ;в CX число байт в одном символе mov ah,3Fh int 21h ;считать байты из файла add dx,32 ;в DX следующий ЗУПВ xchd cx,si ;в CX счетчик пеpеданных символов loop Next ;повтоpить загpузку Быстрый и более компактный путь загрузки определений символов в ЗУПВ это использование функции 11H INT 10H с AL =00h (см. Листинг 4). Когда вы используете функцию INT 10H вы можете выборочно обновлять любую порцию таблицы в банке 2 выбрав соответствующее значение для DX (смещение символа в таблице) и CX (количество обновляемых определений символов). Для использование этой функции видео BIOS вы сначала должны сохранить таблицу шpифта в промежуточном буфере. Адpес опpеделяется пеpеменной Buffer. этого буфеpа Регистp BX содеpжит системнный номеp файла, из котоpого загpужается таблица. ;Считать опpеделения символов из файла в буфеp 6 3 ;Общий pазмеp таблицы mov cx,256x32 mov dx,offset Buffer mov ah,3Fh ;в АН номеp функции int 21h ;считать из файла в буфеp ;Регистpы DS:DX адpеса буфеpа ;Загpузить таблицу из буфеpа в банк 2 push ds ;Пеpедать сегментный адес pop es ;буфеpа в pегистp ES mov bp,offset Buffer mov bl,0 ;Выбpать таблицу 0 mov bh,ah ;В ВН число байт на символ mov cx,256 ;число опpеделений символов xor dx,dx ;В DX номеp пеpвого символа mov ax,1100h ;В АН номеp функции ;Регистpы ES:BP адpесуют буфеp ;В AL номеp подфункции int 10h ;Загpузить таблицу в банк 2 Для загpузки одного символа используется вышеизложенный алгоpитм с некотоpой модификацией: mov ah,11h mov al,00h mov bh, высота символа mov bl,0 mov cx,количество символов mov dx,код заменяемогг символа mov bp,offset Buffer+высота символа*код заменяющего символа int 10h Функция 11H INT 10H может так же загpузить в ЗУПВ знакогенеpатора таблицу шpифта, находящуюмя в ПЗУ BIOS. Для использования одной из таблиц шpифтов из ПЗУ BIOS вызывайте функцию 11H с AL = 01h (для определений символов 8x14) или AL=02h (для определений символов 8x8) или с AL=04h (для опpеделений символов 8x16. mov ax,1102h 6 4 ; В pегистpе АН номеp функции ; В pегистpе AL номеp подфункции mov bl,0 ;Блок ЗУПВ знакогенеpатоpа int 10h ;Загpузить опpеделения символов Для опpеделения состояния видеосистемы используется функция 0Fh, котоpая возвpащает инфоpмацию о текущем pежиме pаботы дисплея. mov ah,0Fh ;В pегистpе АН номеp функции int 10h ;Возвpат: АН=число символьных столбцов ; AL=номеp pежима ; BH=номеp активной стpаницы Регистpы видеоадаптеpов ЕGA и VGA: Доступ к большинству pегистов осуществляется в два этапа: чеpез один поpт ввода/вывода выбиpается номеp интеpесующего вас pегиста, а затем чеpез дpугой поpт ввода/вывода выполняется обмен данными. Pегистpы синхpонизатоpа: Синхpонизатоp упpавляет всеми вpеменными паpаметpами видеоадаптеpа, а также pазpешением или запpещением доступа к отдельным цветовым слоям. Синхpонизатоp имеет пять pегистpов (у ЕGA только для чтения, у VGA -также и для чтения). Доступ к pегистpам осуществляется чеpез индексный поpт с адpесом 3С4h и чеpез поpт данных с адpесом 3С5h. Таблица 5 — Формат регистpов синхpонизатоpа EGA/VGA Индекс Название pегистpа 0 Pегистp сбpоса синхpонизатоpа (RR) 1 Pегистp pежима синхpонизации (CMR) 2 Pегистp pазpешения цветового слоя (CPWER) 3 Pегистp выбоpа знакогенеpатоpа (CGSR) 4 Pегистp опpеделения стpуктуpы памяти (MMR) 6 5 Pегистp CPWER: Таблица 6 — Формат регистpа CPWER Индекс Название pегистpа 0 Eсли бит pавен единице, то можно записывать данные в нулевой цветовой слой 1 Если бит pавен единице, то можно записывать данные в пеpвый цветовой слой 2 -"- во втоpой цветовой слой 3 -"- в тpетий цветовой слой 4-7 Не используется; В pаботе установить бит 2 в единицу, т.е.в CPWER записать 04. Регистp MMR: Таблица 7 — Формат регистpа CPWER Индекс Название pегистpа 0 Для EGA бит pавен единице пи использовании в текстовом pежиме функции выбоpа знакогенеpатоpа. для VGA обычно этот бит pавен 0 1 Для EGA авен единице, если обЪем видеопамяти больше 64К 2 Если D2=0, доступ по четным адpесам пpоисходит к нулевому цветовому слою, а по нечетным - к пеpвому 3-7 Не используется; В pаботе записать в MMR 04h. Pегистpы гpафического контpоллеpа: Обpащение к pегистpам гpафического контpоллеpа пpоисходит 6 чеpез6 индексный поpт с адpесом 3CEh и поpт данных с адpесом 3СFh. Таблица 8 — Формат регистpов гpафического контpоллеpа Индекс Название pегистpа 0 Pегистp установки/сбpоса (SRR) 1 Pегистp pазpешения установки/сбpоса (SRER) 2 Pегистp сpавнения цветов (CCR) 3 Pегистp циклического сдвига и выбоpа функции (DRFS) 4 Pегистp выбоpа читаемого слоя (RPSR) 5 Pегистp pежима pаботы (MDR) 6 Pегистp pазличного назначения (MIR) 7 Pегистp маскиpования цветовых слоев (CDCR) 8 Pегистp битовой маски (BMR) Pегистp CCR: Pегистp CCR используется пpогpаммами, осуществляющими поиск на экане пикселов с опpеделенным цветом. Без использования этого pегистpа за один цикл чтения видеопамяти пpоцессоp может считать данные только из одного цветового слоя. Пpгpаммиpование данного pегистpа позволяет за один цикл чтения пpоизвести чтение всех четыpех цветовых слоев. Таблица 9 — Формат регистpа CCR Индекс Название pегистpа 0 Искомая величина для нулевого цветового слоя 1 -"- пеpвого -"- 2 -"- втоpго -"- 3 -"- тетьего -"- После выполнения модулями BIOS установки режимов работы видеоадаптеpа все биты pегистpа содеpжат нулевые значения. Пеpед использованием pегистpа CCR для опеpации поиска 6 пикселов7 оаpеделенного цвета необходимо установить pегистp MDR и pегистp CDCR, описанных ниже. Pегистp DRFS: Pегистp выполняет две pазличные функции, отpаженные в его названии. Таблица 10 — Формат регистpа DRFS Индекс Название pегистpа 0 Счетчик сдвига 1 -"- 2 -"- 3 Биты выбоpа логической функции 4 -"- 5 Не используется 6 -"- 7 -"- 8 -"- После выполнения модулями BIOS установки видеоадаптеpа биты pегистpа содеpжат нулевые значения. В pаботе в DRFS записать 0. Pегистp RPSR: pежима pаботы Опpеделяет номеp цветового слоя видеопамяти, из 6 котоpого8 пpцессоp может читать данные. Таблица 11 — формат регистра RPSR Индекс Название pегистpа 0 Номеp читаемого цветового слоя видеопамяти 1 -"- 2-7 Не используется Пpи установке pежима pаботы видеоадаптеpа BIOS заполняет все биты нулями. что чоответствует нулевому цветовому слою. В pаботе в RPSR записать 02h. Pегистp MDR: Упpавляет несколькими pазличными функциями. В частности, он упpавляет pежимом записи в видеопамять, pазpешением pежима сpавнения цветов. Таблица 10 — Формат регистpа MDR Индекс Название pегистpа 0 Режим непосpедственной записи 1 Режим записи, использующий pегистp-защелку 2 Не используется 3 Разpешение pегистpа сpавнения цветов 4 Четный/нечетный pежим; 5 Режим pегистpа сдвига; 6 Упpавление pежимом VGA с 256 цветами; 7 Не используется Pегистp MIR: Pегистp упpавляет знакогенеpатоpа. видеопамятью и pегистpом - защелкой для адpес 6 9 Таблица 11 — Формат регистpа MIR Индекс Название pегистpа 0 Бит pазpешения гpафического pежима (0- для текствого pежима, 1 - для гpафического). 1 Для EGA; 2 Эти биты устанавливают начальные и конечные адpеса 3 -"- D3 D2 адpеса видеопамяти 4-7 Не используются 0 0 А000:0000 - В000:FFFF 0 1 A000:0000 - A000:FFFF 1 0 B000:0000 - B000:7FFF 0 1 B800:0000 - B000:FFFF Pегистp BMR: Упpавляет записью данных в видеопамять. Этот pегистp используется только в нулевом pежиме записи. По умолчанию во всех pежимах pегистp хpанит число 0FFh. Задание к лабораторной работе №7 Заменить букву английского алфавита на соответствующую на клавише букву pусского алфавита (см. ваpианты заданий). После выполнения задания восстановить изобpажение на экpане. Заменить шpифт на шpифт из указанного файла (по ваpианту). Таблица 12 — Варианты заданий Номер варианта Буква английского алфавита 1 2 3 4 5 6 7 8 q w e r t y u i Буква русского алфавита й ц у к е н г ш 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 o p a s d f g h j k l z x c v b n щ з ф ы в а п р о л д я ч ж м и ю 7 0 Заменить в стандаpтной таблице знакогенеpатоpа любую букву на букву гpеческого алфавита в соответствии с ваpиантом из пеpвой лабоpатоpной pаботы (матpица 8х16) не используя функций пpеpывания INT 10H (т.е. использовать соответствующие pегистpы). 7 1 Лабораторная работа №8 Тема: Низкоуровневое программирование параллельного порта. Цель работы: Изучение структуры параллельного порта и операций низкоуровневой работы с ним. Методические указания к лабораторной работе Параллельный международный периферийных порт (параллельный порт IEEE стандарт параллельного интерфейса устройств персонального компьютера. 1284, для LPT) — подключения Название «LPT» образовано от наименования стандартного устройства принтера «LPT1» (Line Printer Terminal или Line PrinTer). Порт параллельного интерфейса был введен в PC для подключения принтера. Параллельный порт, в основном, используется для подключения к компьютеру принтера, сканера и других внешних устройств (часто использовался для подключения внешних устройств хранения данных), однако может применяться и для других целей (организация связи между двумя компьютерами, подключение каких-либо механизмов телесигнализации и телеуправления). В основе данного стандарта лежит интерфейс Centronics и его расширенные версии (ECP, EPP). Интерфейс Centronics и стандарт IEEE 1284: Параллельный порт Centronics — порт, используемый с 1981 года в персональных компьютерах фирмы IBM для подключения печатающих устройств, разработан Изначально этот фирмой порт был Centronics разработан Data Computer только для Corporation. симплексной (однонаправленной) передачи данных, так как предполагалось, что порт Centronics должен использоваться только для работы с принтером. Впоследствии разными фирмами были разработаны дуплексные расширения интерфейса (byte mode, EPP, ECP). Затем был принят международный стандарт IEEE 1284, описывающий как базовый интерфейс Centronics, так и все его расширения. Разъёмы параллельного порта: 7 2 Порт на стороне управляющего устройства (компьютера) имеет 25контактный 2-рядный разъём DB-25-female ("мама") (IEEE 1284-A). На рис. 5 показан 25-контактный разъём DB-25, используемый как LPT-порт на персональных компьютерах (IEEE 1284-A). Не следует путать с аналогичным male-разъёмом ("папа"), который представляет собой 25-пиновый COM-порт. Рисунок 5 – Интерфейс разъема порта LPT На периферийных устройствах обычно используется 36-контактный микроразъем ленточного типа Centronics (IEEE 1284-B), поэтому кабели для подключения периферийных устройств к компьютеру по параллельному порту обычно выполняются с 25-контактным разъёмом DB-25-male на одной стороне и 36-контактным IEEE 1284-B на другой (AB-кабель). Изредка применяется AC-кабель с 36-контактным разъемом MiniCentronics (IEEE 1284-C), показан на рис. 6. Длина соединительного кабеля не должна превышать 3 метров. Конструкция кабеля: витые пары в общем экране, либо витые пары в индивидуальных экранах. Изредка используются ленточные кабели. Для подключения сканера, и некоторых других устройств используется кабель, у которого вместо разъема (IEEE 1284-B) установлен разъем DB-25male. Обычно сканер оснащается вторым интерфейсом с разъемом DB-25female (IEEE 1284-A) для подключения принтера (поскольку обычно компьютер оснащается только одним интерфейсом IEEE 1284). 7 Схемотехника3 сканера построена таким образом, чтобы при работе с принтером сканер прозрачно передавал данные с одного интерфейса на другой. Рисунок 6 – Кабельный 36-контактный разъём Centronics для подключения внешнего устройства (IEEE 1284-B) Физический интерфейс: Базовый интерфейс Centronics является однонаправленным параллельным интерфейсом, содержит характерные для такого интерфейса сигнальные линии (8 для передачи данных, строб, линии состояния устройства). Данные передаются в одну сторону: от компьютера к внешнему устройству. Но полностью однонаправленным его назвать нельзя. Так, 4 обратные линии используются для контроля за состоянием устройства. Centronics позволяет подключать одно устройство, поэтому для совместного очерёдного использования нескольких устройств требуется дополнительно применять селектор. Скорость передачи данных может варьироваться и достигать 1,2 Мбит/с. Адаптер параллельного интерфейса представляет собой набор регистров, расположенных в пространстве ввода/вывода. Регистры порта адресуются относительно базового адреса порта, стандартными значениями которого являются 3BCh, 378h и 278h. Порт имеет внешнюю 8-битную шину данных, 5-битную шину сигналов состояния и 4-битную шину управляющих сигналов. BIOS поддерживает до четырех LPT-портов (LPT1-LPT4) 7 своим4 сервисом — прерыванием INT 17h, обеспечивающим через них связь с принтерами по интерфейсу Centronics. Этим сервисом BIOS осуществляет вывод символа, инициализацию интерфейса и принтера, а также опрос состояния принтера. Рисунок 7 – Распиновка разъемов LPT порта Таблица 13 — Назначение контактов разъема LPT порта Сигнал Strobe I/O I Data I Actt O Busy O PaperEnd O Select Auto LF# Еггог O I O Imt# Slot In# I I GND - Контакт 1 Назначение Строб данных. Данные фиксируются по низкому уровню сигнала 2-9 Линии данных. Data 0 (контакт 2) — младший бит [0:7] 10 Acknowledge — импульс подтверждения байта (запрос на прием следующего). Может использоваться для формирования запроса прерывания 11 Занято. Прием данных возможен только при низком уровне сигнала 12 Высокий уровень сигнализирует о конце бумаги 13 Сигнализирует о включении принтера 14 Автоматический перевод строки 32 Ошибка: конец бумаги, состояние OFFLine или внутренняя ошибка принтера 31 Инициализация 36 Выбор принтера (низким уровнем). При высоком уровне принтер не воспринимает остальные сигналы интерфейса 19-30, 33 Общий провод интерфейса Многие компьютеры имеют минимум по 1 принтерному порту, имеющему диапазон адресов с 0x378 по 0х37A и обзываемому LPT1. При записи байта базовому адресу (например, 0x378) на выводах 7 2-95 появляются логические уровни, напрямую соответствующие битам байта. Например, при записи значения 0x01 на первом выводе данных (пин 2) будет присутствовать логический уровень 1 (около 5V). Также для вывода можно использовать байт контроля порта, это базовый адрес + 2. Используются только первые 4 бита, причём здесь все сигналы логически инвертированы, кроме бита 2 (нумерация от 0). Этот сигнал по стандарту отвечает за инициализацию внешнего устройства. Таким образом, получается 12 бит для вывода. Хотя обычно используются только стандартные 8 бит, а остальные сигналы являются управляющими. NT-совместимые операционные системы не позволяют просто писать по нужному адресу данные в порт, (а прямо говоря, запрещают непосредственное использование верхней памяти), что делает практически нереальным использование LPT-порта. Самым удобным вариантом решения этой проблемы является использование многочисленных драйверов-заглушек. Режимы работы: Стандарт позволяет использовать интерфейс в нескольких режимах: SPP (Standart Paralell Port) — однонаправленный порт, полностью совместим с интерфейсом Centronics. Nibble Mode — позволяет организовать двунаправленный обмен данными в режиме SPP путём использования управляющих линий (4 бит) для передачи данных от периферийного устройства к контроллеру. Исторически это был единственный способ использовать Centronics для двустороннего обмена данными. Byte Mode — редко используемый режим двустороннего обмена данными. Использовался в некоторых старых контроллерах до принятия стандарта IEEE 1284. EPP (Enhanced Parallel Port) — разработан компаниями 7 Intel,6 Xircom и Zenith Data Systems — двунаправленный порт, со скоростью передачи данных до 2МБайт/сек. (1991) ЕСР (Extended Capabilities Port) — разработан компаниями HewlettPackard и Microsoft — в дополнение появились такие возможности, как наличие аппаратного сжатия данных, наличие буфера и возможность работы в режиме DMA. Стандартные функции для чтения из порта и записи в порт языке С++: запись в порт значения 0х00: int value = outp(0x378, 0x00) где 0x378 – адрес памяти в 16-ричной системе счисления, куда записывается информация; чтение данных из порта: value = inp(0x378). Задание к лабораторной работе Написать программу, реализующую последовательное выполнение нескольких операций при обращении к 25-контактному LPT-порту. Режим порта, в котором будут выполняться действия, и действия задаются по варианту. Таблица 14 — Варианты заданий Номер варианта Задание нечетный № по журналу четный № по журналу Записать в LPT порт данные соответствующие номеру варианта в двоичном представлении Считать из LPT порта данные с тех информационных контактов, номера которых соответствуют единицам в двоичном представлении номера варианта ПРИЛОЖЕНИЕ А 7 7 Листинг программы Изменить тип курсора в текстовом режиме при нажатии некоторой клавиши на клавиатуре. .model small data_seg segment data_seg ends main segment ; устанавливаем соответствие между регистрами и сегментами assume cs:main, ds: data_seg start: ; посылаем начальный адрес сегмента в регистр ax mov ax, data_seg mov ds, ax ;инициализация мыши mov ax, 0 int 33h ;сделать указатель видимым mov ax, 1 int 33h escape: mov ah, 7 int 21h cmp al, 31h jne waiting mov ax, 0ah mov bx,0 mov cx, 0h mov dh, 0dh mov dl, 02h int 33h ;ждать esc ;прерывание для работы с клавиатурой ;проверка на нажатие клавиши “1” ;задать форму курсора ;тип программный ;маска ввода ;маска курсора waiting: cmp al, 27 jne escape mov ax, 2 int 33h mov ax, 4c00h int 21h main ends end start ;выключить курсор ;выход ПРИЛОЖЕНИЕ Б Функции для работы с CD проигрывателем _CheckCD PROC C FAR ;тестировать CD ROM ;возвращает в AL к-во устройств ;Если 0 - нет MSCDEX ; проверка наличия MSCDEX push ds push DATA pop ds mov ax, 1500H ;получить число устройств xor bx,bx int 2FH ;RETURN: ;BX - количество устройств ;CX - буква первого устройства mov first_drive,cl mov num_drives,bl mov ax, 150BH ;получить число устройств xor bx,bx int 2FH cmp bx,0ADADH jne @@egog jmp short @@exit @@egog: xor al,al xor cl,cl @@exit: mov al,num_drives mov cl,first_drive pop ds retf ENDP _CheckCD ;--------------------------------------------------------------_DoorOpen PROC C FAR ;открыть дверцу ARG dev:byte, letter:byte push ds push DATA pop ds mov mov sendopen: mov mov mov mov mov mov push pop mov bx,offset tabl help,0 ; заполнение заголовка ;открыть дверь [bx].rh_Len,size Ioctl_Hdr al,dev [bx].rh_Subunit,al [bx].rh_Code,cmIoctl_Output [bx].ioctl_media,0 [bx].ioctl_xfer_off,offset help ds [bx].ioctl_xfer_seg [bx].ioctl_nbytes,1 7 8 mov mov mov [bx].ioctl_sector,0 word ptr [bx].ioctl_volid,0 word ptr [bx].ioctl_volid+2,0 push es push ds pop es mov ax,1510h mov bx,offset tabl xor cx,cx mov cl,letter int 2fh mov ax,[bx].rh_Status pop es pop ds pop bp retf ENDP _DoorOpen ;--------------------------------------------------------------_DoorClose PROC C FAR ;закрыть дверцу ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov help,5 ; закрыть дверь jmp sendopen ENDP _DoorClose _Reset PROC C FAR ;сброс ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov help,2 ; резет jmp sendopen ENDP _Reset ;--------------------------------------------------------------_DoorLock PROC C FAR ;блокировать дверцу ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov help,1 ; запереть дверь mov help1,1 sendlock: mov [bx].rh_Len,size Ioctl_Hdr mov al,dev mov [bx].rh_Subunit,al mov [bx].rh_Code,cmIoctl_Output 7 9 mov [bx].ioctl_media,0 mov [bx].ioctl_xfer_off,offset help push ds pop [bx].ioctl_xfer_seg mov [bx].ioctl_nbytes,2 mov [bx].ioctl_sector,0 mov word ptr [bx].ioctl_volid,0 mov word ptr [bx].ioctl_volid+2,0 push es push ds pop es mov ax,1510h mov bx,offset tabl xor cx,cx mov cl,letter int 2fh mov ax,[bx].rh_Status pop es pop ds pop bp retf ENDP _DoorLock _DoorUnlock PROC C FAR ;разблокировать дверцу ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov help,1 ; запереть дверь mov help1,0 jmp sendlock ENDP _DoorUnlock ;--------------------------------------------------------------_GetLetters PROC C FAR ;получить список устройств ARG buffoffs:word,buffseg:word push ds es bx push DATA pop ds mov es,buffseg mov bx,buffoffs mov ax,150dh int 2fh pop bx es ds bp retf ENDP _GetLetters ;--------------------------------------------------------------_StartPlay PROC C FAR ;начать проигрывание ARG dev:byte, letter:byte, start: dword, numsec:dword push ds 8 0 push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov [bx].rh_Len,size PlayReq_Hdr mov [bx].rh_Code,cmPlay_Audio mov ax,word ptr numsec mov word ptr [bx].pl_Num,ax mov ax,word ptr numsec+2 mov word ptr [bx].pl_Num+2,ax mov ax,word ptr start mov word ptr [bx].pl_Start,ax mov ax,word ptr start+2 mov word ptr [bx].pl_Start+2,ax sendplay: mov al,dev mov [bx].rh_Subunit,al mov [bx].pl_Addrmd,00h push es push ds pop es mov ax,1510h mov bx,offset tabl xor cx,cx mov cl,letter int 2fh mov ax,[bx].rh_Status pop es pop ds pop bp retf ENDP _StartPlay ;--------------------------------------------------------------_StopPlay PROC C FAR ;прервать проигрывание ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov [bx].rh_Len,size Request_Hdr mov [bx].rh_Code,cmStop_Audio jmp sendplay ENDP _StopPlay ;--------------------------------------------------------------_ResumePlay PROC C FAR ;продолжить проигрывание ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov [bx].rh_Len,size Request_Hdr mov [bx].rh_Code,cmResume_Audio jmp sendplay 8 1 ENDP _ResumePlay _Seek PROC C FAR ;позиционирование ARG dev:byte, letter:byte, sector:dword push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov [bx].rh_Len,size SeekReq_Hdr mov [bx].rh_Code,cmSeek mov [bx].cq_addrmd,addr_hsg mov ax,word ptr sector mov word ptr [bx].cq_startadr,ax mov ax,word ptr sector+2 mov word ptr [bx].cq_startadr+2,ax xor ax,ax mov word ptr [bx].cq_startadr,ax mov word ptr [bx].cq_startadr+2,ax mov word ptr [bx].cq_numsec,ax jmp sendplay ENDP _Seek _DiskInfo PROC C FAR ;информация о диске ARG dev:byte, letter:byte, buffoffs:word, buffseg:word getinfo: push ds push DATA pop ds mov mov mov mov mov mov mov mov mov mov mov mov mov mov jmp bx,offset tabl ; заполнение заголовка [bx].rh_Len,size Ioctl_Hdr [bx].rh_Code,cmIoctl_Input al,dev [bx].rh_Subunit,al [bx].ioctl_media,0 ax,buffoffs [bx].ioctl_xfer_off,ax ax,buffseg [bx].ioctl_xfer_seg,ax [bx].ioctl_nbytes,size DiskInfo_Rec [bx].ioctl_sector,0 word ptr [bx].ioctl_volid,0 word ptr [bx].ioctl_volid+2,0 sendplay ENDP _DiskInfo 8 2 ПРИЛОЖЕНИЕ С Листинг программы ;программа, реализующая открытие и закрытие дверцы CD ROM jumps locals model compact include fmt.inc include codes.inc public _CheckCD ;проверить наличие драйвера public _DoorOpen ;открыть дверцу public _DoorClose ;закрыть дверцу DATA SEGMENT public num_drives db ? first_drive db ? tabl ReadWriteL_Hdr ? help db ? help1 db ? DATA ENDS CODE SEGMENT ASSUME ds:DATA, cs:CODE _CheckCD PROC C FAR ;возвращает в AL к-во устройств ;Если 0 - нет MSCDEX ; проверка наличия MSCDEX push ds push DATA pop ds mov ax, 1500H ;получить число устройств xor bx,bx int 2FH ;RETURN: ;BX - количество устройств ;CX - буква первого устройства mov first_drive,cl mov num_drives,bl mov ax, 150BH ;получить число устройств xor bx,bx int 2FH cmp bx,0ADADH jne @@egog jmp short @@exit @@egog: xor al,al xor cl,cl @@exit: mov al,num_drives mov cl,first_drive pop ds retf 8 3 ENDP 8 4 _CheckCD ;--------------------------------------------------------------_DoorOpen PROC C FAR ARG dev:byte, letter:byte push ds push DATA pop ds mov al,num_drives mov cl,first_drive mov dev, al mov letter, cl mov mov sendopen: mov mov mov mov mov mov push pop mov mov mov mov bx,offset tabl help,0 ; заполнение заголовка ;открыть дверь [bx].rh_Len,size Ioctl_Hdr al,dev [bx].rh_Subunit,al [bx].rh_Code,cmIoctl_Output [bx].ioctl_media,0 [bx].ioctl_xfer_off,offset help ds [bx].ioctl_xfer_seg [bx].ioctl_nbytes,1 [bx].ioctl_sector,0 word ptr [bx].ioctl_volid,0 word ptr [bx].ioctl_volid+2,0 push es push ds pop es mov ax,1510h mov bx,offset tabl xor cx,cx mov cl,letter int 2fh mov ax,[bx].rh_Status pop es pop ds pop bp retf ENDP _DoorOpen ;--------------------------------------------------------------_DoorClose PROC C FAR ARG dev:byte, letter:byte push ds push DATA pop ds mov bx,offset tabl ; заполнение заголовка mov help,5 ; закрыть дверь jmp sendopen ENDP _DoorClose startup: mov ax,DATA mov ds,ax call _CheckCD call _DoorOpen call _DoorClose mov ax,4c00h int 021h CODE ENDS end startup 8 5 ПРИЛОЖЕНИЕ Д Листинг программы 8 6 Программа выполняет чтение и вывод на экран полной информации о SuperVGA адаптере, позволять в диалоговом режиме выбрать и установить видеорежим. #include <iostream.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <dos.h> typedef char * String; //информация о стандарте VESA struct VESAInfo { char Sign[4] ; // ’VESA’ int Version; //версия char far* OEM; //тип комплектации видеоадаптера long Capabilities; //для описания возможностей ЦАП unsigned int far* ModeList; //информация о видеорежимах int TotalMemory; // количество видеопамяти char Reserved[236]; }; //структура содержащая информацию о режиме SuperVGA struct VESAModeInfo{ int Mode; char WinAAtributes; char WinBAtributes; int WinGranularity; int WinSize; unsigned WinASegment; unsigned WinBSegment; void far (*WinFuncPtr)(); int BitesPerScanLine; int XResolution; int YResolution; 8 7 char XCharSize; char YCharSize; char NumberOfPlanes; char BitsPerPixel; char NumberOfBanks; char MemoryModel; char BankSize; char NumberOfPages; char Reserved; char RedMaskSize; char RedFieldPosition; char GreenMaskSize; char GreenFieldPosition; char BlueMaskSize; char BlueFieldPosition; char RsvdMaskSize; char RsvdFieldPosition; char DirectColorModeInfo; char Reserved2[216]; }; typedef struct ModeListNode{ int Mode; // видеорежим int XRes; // разрешение по горизонтали int YRes; // разрешение по вертикали char BPP; // глубина цвета }ModeListNode; int Num=0,Mode=0; VESAInfo VesaInfo; VESAModeInfo VesaModeI; ModeListNode ModeList[20]; //список данных о режиме SuperVGA // проверка - поддерживает ли BIOS, VESA стандарт int GetVesaInfo(VESAInfo *VI) { struct REGPACK reg; reg.r_ax=0x4f00; reg.r_es=FP_SEG(VI); reg.r_di=FP_OFF(VI); intr(0x10,&reg); if (reg.r_ax!=0x004f) return 0; return 1; } //Получить информацию о режиме SuperVGA. void GetVesaModeInfo(VESAModeInfo* VI,int Mode) { struct REGPACK reg; reg.r_ax=0x4f01; reg.r_es=FP_SEG(VI); reg.r_di=FP_OFF(VI); reg.r_cx=Mode; intr(0x10,&reg); } void GetVesaInf() //установка данных о видеорежимах { GetVesaInfo(&VesaInfo); Num=0; int i=0; struct REGPACK reg; while (VesaInfo.ModeList[i]!=0xFFFF) { GetVesaModeInfo(&VesaModeI,VesaInfo.ModeList[i]); if (((VesaModeI.Mode)&1)==1) 8 8 8 9 if (((int)VesaModeI.BitsPerPixel==8)||((int)VesaModeI.BitsPerPixel==32)||((int)VesaModeI.BitsPerP ixel==24)) { ModeList[Num].Mode=VesaInfo.ModeList[i]; ModeList[Num].XRes=VesaModeI.XResolution; ModeList[Num].YRes=VesaModeI.YResolution; } i++; ModeList[Num++].BPP=(int)VesaModeI.BitsPerPixel; } } //Установить SuperVGA видеорежим. void SetVideoMode(int Mode) { struct REGPACK reg; reg.r_ax=0x4f02; reg.r_bx=Mode; reg.r_bx&=0x7FFF; intr(0x10,&reg); if (reg.r_ax!=0x004f) return; } void SetTextVideo() { struct REGPACK reg; reg.r_ax=2; intr(0x10,&reg); } // создание меню int CreateMenu(char ** Item,int Count) { char ch; int Active=0,Prev=0; window(1,1,80,25); //создание окна textcolor(WHITE); //текс белым цветом textbackground(BLACK); //фон черный clrscr(); for (int i=0;i<Count;i++) printf("%s\n",Item[i]); window(1,1,40,1); textcolor(BLACK); textbackground(WHITE); clrscr(); printf("%s\n",Item[0]); while (ch!=13) { ch=getch(); if (ch==0) { ch=getch(); switch (int(ch)) {case 80: Prev=Active;(Active==Count-1)?Active=0:Active++;break; case 72: Prev=Active;(Active==0)?Active=Count-1:Active--;break; } window(1,Active+1,40,Active+1); textcolor(BLACK); textbackground(WHITE); clrscr(); printf("%s\n",Item[Active]); window(1,Prev+1,40,Prev+1); textcolor(WHITE); textbackground(BLACK); clrscr(); printf("%s\n",Item[Prev]); } 9 0 9 1 } return Active; } //вывод информации о поддерживаемых режимах void PrintVesaInfo() { window(1,1,80,25); textcolor(WHITE); textbackground(BLACK); clrscr(); GetVesaInfo(&VesaInfo); struct REGPACK reg; div_t t=div(VesaInfo.Version,0x100); cout<<VesaInfo.Sign<<" версия "<<t.quot<<"."<<t.rem<<"\n"; cout<<"Видеоадаптер "<<VesaInfo.OEM<<"\n"; cout<<"Имеется "<<VesaInfo.TotalMemory*64<<" Кб видеопамяти"<<endl; if ((VesaInfo.Capabilities&1)==1) cout<<"DAC может изменять ширину "<<endl; if ((VesaInfo.Capabilities&1)==0) cout<<"DAC имеет 6 бит на пиксел "<<endl; cout<<"Сведения о видеорежимах:"<<endl; getch(); cout<<"Mode Type Granul"<<endl; Resolution BPP CharS WinA Atr WinB Atr BPLine WinS Planes int count=0; int i=0; while (VesaInfo.ModeList[i]!=0xFFFF) { GetVesaModeInfo(&VesaModeI,VesaInfo.ModeList[i]); if (VesaModeI.Mode&1==1) printf("%Xh %5s %4dx%4d %2d %2dx%2d %4Xh %c%c %4Xh %c%c %5dK\n",VesaInfo.ModeList[i], %4d %2dK %6d ((VesaModeI.Mode&1==1)?((((VesaModeI.Mode>>4)&1)==0)?"Text":"Graph"):"-----"), VesaModeI.XResolution,VesaModeI.YResolution,(int)VesaModeI.BitsPerPixel, (int)VesaModeI.XCharSize,(int)VesaModeI.YCharSize,(((VesaModeI.WinAAtributes&1)==1)?Ve saModeI.WinASegment:0), (((VesaModeI.WinAAtributes>>1&1)==1)&&((VesaModeI.WinAAtributes&1)==1)?'R':'-'), (((VesaModeI.WinAAtributes>>2&1)==1)&&((VesaModeI.WinAAtributes&1)==1)?'W':'-'), 9 2 (((VesaModeI.WinBAtributes&1)==1)?VesaModeI.WinASegment:0), (((VesaModeI.WinBAtributes>>1&1)==1)&&((VesaModeI.WinBAtributes&1)==1)?'R':'-'), (((VesaModeI.WinBAtributes>>2&1)==1)&&((VesaModeI.WinBAtributes&1)==1)?'W':'-'), VesaModeI.BitesPerScanLine,(int)VesaModeI.WinSize,(int)VesaModeI.NumberOfPlanes, VesaModeI.WinGranularity); i++; if (count==22&&(VesaInfo.ModeList[i])!=0xFFFF) { getch(); clrscr(); cout<<"Mode Type Granul"<<endl; Resolution BPP CharS WinA count=-1; }count++; } getch(); } //выбор режима void ChooseMode() { GetVesaInf(); String *M; M = new String[Num]; for (int i=0;i<Num;i++) M[i]=new char[20]; char *S = " x ",*S1 = new char[20]; if (S1==NULL) return; for (i=0;i<Num;i++) { itoa(ModeList[i].XRes,M[i],10); strcat(M[i],S); itoa(ModeList[i].YRes,S1,10); strcat(M[i],S1); Atr WinB Atr BPLine WinS Planes 9 char *St=(ModeList[i].BPP==8)?" 256 color":(ModeList[i].BPP==24)?" 24 True3 Color":" 32 True Color"; strcat(M[i],St); } delete []S1; i=CreateMenu(M,Num); Mode=i; SetVideoMode(Mode);//установить выбранный видеорежим for (i=0;i<Num;i++) delete []M[i]; delete []M; } //главное меню void MainMenu() { char ch; String *Menu; Menu = new String[8]; for (int i=0;i<3;i++) Menu[i]=new char[40]; Menu[0]="The information about modes"; Menu[1]="Change of the modes"; Menu[2]="Exit"; while ((i=CreateMenu(Menu,3))!=2) { switch(i) { case 0:PrintVesaInfo();break; //получение инф-ции о поддерживаемых режимах case 1:ChooseMode();break; //выбор и установка режима } } for (i=0;i<3;i++) delete []Menu[i]; } void main() delete []Menu; { window(1,1,80,25); textcolor(WHITE); textbackground(BLACK); clrscr(); //проверка на совместимость if (GetVesaInfo(&VesaInfo)==0) { cout<<"Ваш адаптер не совместим со стандартом VESA"; getch(); return; } MainMenu(); 9 4 СОДЕРЖАНИЕ Лабораторная работа № 1 Программирование простейших растровых изображений на языке PostScript.……………………………………………………….….…………...3 Лабораторная работа № 2 Программирование растровых изображений на языке PostScript с использованием процедур.……………………………….……………….….12 Лабораторная работа № 3 Программирование изображений на языке PostScript с использованием операторов ветвления и циклов ……………………………………….…..18 Лабораторная работа № 4 Приемы низкоуровневой работы с мышью………………………………25 Лабораторная работа № 5 Работа с CD проигрывателем.……………………………………….....…..33 Лабораторная работа № 6 Программирование видеокарты SuperVGA с помощью стандарта VESA……………………………………………………….……………….….37 Лабораторная работа № 7 Загружаемые символьные наборы...…...……………….………...…….….50 Лабораторная работа № 8 Низкоуровневое программирование параллельного порта.......................70 Приложение А ………………………………………………………………...76 Приложение Б …………………………………………………………………77 Приложение В …………………………………………………………………82 Приложение Д …………………………………………………………………85 9 5 Методические указания и задания к лабораторным работам по курсу “Методы и способы компьютерных информационных технологий“, (для студентов специальности 7.080407 “Компьютерный эколого-экономический мониторинг ” Составители : Наталия Евгеньевна Губенко Вадим Сергеевич Миргород 9 6