Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Раздел 3. Вывод символов на экран.




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

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

 

4.3.1 Вывод на экран одного символа.

Все процедуры для вывода символа на экран в BIOS и DOS (а также в Бейсике) помещают символ в текущую позицию курсора и автоматически передвигают курсор на одну позицию вправо. Все они переносят вывод на следующую строку при достижении конца строки, если не сделано специальных указаний отбрасывать все символы за 80-м столбцом [4.2.2]. Важное отличие между отдельными процедура­ми состоит в том, что некоторые вместе с символом пишут также и его атрибуты, а некоторые этого не делают.

Kак в языках высокого, так и в языках низкого уровня, символы могут выводиться на экран без использования обычных операций печати. Вместо этого используется прямое отображение в память, при котором коды символов и их атрибуты прямо засылаются в ячейки памяти видеобуфера, соответствующие определенной позиции курсора на экране. Буфер начинается с адреса B000:0000 для монохромного адаптора и с адреса B800:0000 - для цветного графического адапто­ра и PCjr. EGA использует те же самые адреса в аналогичных режи­мах экрана. Позиции с четными номерами (начиная с нуля) содержат коды ASCII символов, а позиции с нечетными номерами - байты атри­бутов. Hа рис. 4-2 показан участок памяти видеобуфера. При этих операциях позиция курсора не меняется и он может быть выключен при желании [4.2.3]. Вместо курсора надо хранить переменные, служащие указателями на текущую позицию.

Высокий уровень.

Бейсик выводит как отдельные символы, так и целые строки, с помощью одних и тех же операторов PRINT и WRITE. Kак правило, используется PRINT; WRITE - это один из вариантов со специальны­ми, редко используемыми форматами вывода. PRINT работает с данны­ми трех видов. Он выводит содержимое как строковых, так и число­вых переменных, например, PRINT S$ или PRINT X. Он выводит также символы, вставленные (в кавычках) внутрь самого оператора PRINT, например, PRINT "This words are printed". Он выводит также симво­лы, соответствующие кодам ASCII, включенным в оператор PRINT в виде операторов CHR$, например, PRINT CHR$(65), что приводит к выводу на экран символа A (код ASCII #65).

В одном операторе PRINT могут выводиться много данных, при этом все три формы данных могут быть перемешаны. Отдельные данные отделяются запятой или точкой с запятой. Запятая приводит к тому, что следующие данные будут выводиться со следующей позиции табу­ляции данной строки. Точка с запятой приводит к тому, что данные печатаются на экране подряд, не разделенные пробелами (отметим, что PRINT вставляет пробел перед выводом любой числовой перемен­ной, а WRITE не делает этого). Обычно оператор PRINT автоматичес­ки делает перевод на новую строку при завершении, таким образом следующий такой оператор начнет вывод с новой строки экрана. Чтобы перенос на новую строку не происходил надо в конце операто­ра PRINT поставить точку с запятой, например, PRINT S$;.

Для установки позиции курсора перед выводом используется оп­ератор LOCATE. Без оператора LOCATE PRINT всегда начинает вывод с первой позиции строки, в которой находится курсор. Последователь­ные операторы PRINT заполняют экран до тех пор, пока не будет записана 24-я строка, после чего экран сдвигается вверх, с тем чтобы следующий оператор PRINT снова выводил 24-ю строку. PRINT может выводить в 25-й строке только при помощи LOCATE; и это также приводит к автоматическому сдвигу экрана вверх. Чтобы зап­ретить сдвиг надо окончить оператор PRINT точкой с запятой. Одна­ко этот метод не сработает в последних позициях строк 24 и 25. Для заполнения этих позиций без сдвига экрана Вы должны использо­вать отображение в память, как показано ниже.

Вы можете включать управляющие символы [7.1.9] внутрь операто­ра PRINT для того чтобы реализовать перемещения курсора внутри строки. Hапример, если Вы поместите в строку CHR$(13), то в этой точке будет сделан возврат каретки. Если Вы выведете оператором PRINT строку "One"+CHR$(13)+"Two"+CHR$(13)+"Three", то в резуль­тате каждое слово будет выводиться с новой строки. Kоды ASCII 28-31 сдвигают курсор на одну позицию соответственно вправо, влево, вверх и вниз. Оператор PRINT не содержащий данных приводит к выводу возврата каретки и, таким образом, следующий оператор PRINT будет выводить на строке через одну.

Прямое отображение в память существенно увеличивает скорость вывода на экран в Бейсике. Оно особенно полезно при конструирова­нии табличного вывода, когда формы могут достигать правого нижне­го угла экрана. Сначала надо установить указатель сегмента на &HB000, а затем использовать оператор POKE для засылки байтов памяти. Прилегающие по горизонтали символы отстоят друг от друга на два байта, разделяемые байтом атрибутов. Для 80-символьных экранов прилегающие по вертикали символы отстоят на 160 байт друг от друга (2 байта для каждого символа и атрибутов). В следующих двух примерах вдоль границы экрана рисуется рамка, используя символы псевдографики. В первом примере чаще используется опера­тор PRINT, а во втором используется исключительно прямое отобра­жение в память. Отметим, что и в первом случае приходится исполь­зовать прямое отображение в память в последних столбцах строк 24 и 25, чтобы избежать сдвига экрана.

Использование PRINT:

10 CLS: KEY OFF 'очистка экрана

20 DEF SEG = &HB000 'указываем на видеобуфер

30 LOCATE 1,1: PRINT CHR$(201) 'левый верхний угол

40 LOCATE 1,80: PRINT CHR$(187) 'правый верхний угол

50 LOCATE 1,24: PRINT CHR$(186) '

60 LOCATE 1,25: PRINT CHR$(200) '

70 POKE 3838,186 'позиция 80 строки 24

80 POKE 3998,188 'позиция 80 строки 25

90 FOR N=2 TO 79 'горизонтальные линии

100 LOCATE 1,N: PRINT CHR$(205);: LOCATE 25,N: PRINT CHR$(205)

110 NEXT '

120 FOR N=2 TO 23 'вертикальные линии

130 LOCATE N,1: PRINT CHR$(186): LOCATE N,80: PRINT CHR$(186)

140 NEXT

Использование прямого отображения в память:

10 CLS: KEY OFF 'очистка экрана

20 DEF SEG = &HB000 'буфер монохромного дисплея

30 POKE 0,201 'левый верхний угол

40 POKE 158,187 'правый верхний угол

50 POKE 3840,200 'левый нижний угол

60 POKE 3998,188 'правый нижний угол

70 FOR N=2 TO 156 STEP 2 'горизонтальные прямые

80 POKE N,205: POKE N+3840,205 'как верхняя, так и нижняя

90 NEXT

100 FOR N=160 TO 3680 STEP 160 'вертикальные прямые

110 POKE N,186: POKE N+158,186 'правая и левая

120 NEXT

Средний уровень.

Операционная система предоставляет шесть процедур вывода на экран - три в BIOS и три в DOS. Они отличаются главным образом тем, передвигается курсор или нет, после вывода символа, вызывают ли они сдвиг экрана, позволяют ли они устанавливать атрибуты и цвета символов, а также какие управляющие коды они интерпретируют (некоторые рассматривают символ BackSpace, просто как обычный символ, а некоторые действительно сдвигают курсор на одну позицию назад). Эти шесть процедур следующие:

Прерывание 10H:

функция 9 вывод символа с атрибутами

A вывод символа без атрибутов

E "телетайпная" процедура (как на принтер)

Прерывание 21H:

функция 2 вывод символа без атрибутов

6 вывод символа без атрибутов

9 вывод строки символов

Функции 9 и A прерывания 10H вообще не интерпретируют управ­ляющие символы. Функции DOS интерпретируют управляющие коды, приведенные в следующей таблице. Функция E прерывания 10H интерп­ретирует все коды таблицы, кроме ASCII 9.

ASCII 7 звонок

ASCII 8 возврат на шаг (BackSpace)

ASCII 9 табуляция

ASCII 10 перевод строки

ASCII 13 возврат каретки

Первые две функции прерывания 10H не передвигают курсор после вывода символа. Функция 9 этого прерывания выводит на экран с указанием атрибутов, а функция A - без указания, при этом сохра­няется текущее значение байта атрибутов для этого символа. AL должен содержать выводимый символ, а BL - атрибуты. Hомер страни­цы дисплея содержится в BH. Он должен указываться даже для монох­ромного дисплея, который имеет только одну страницу памяти дисп­лея. В этом случае должна быть установлена первая страница, кото­рой соответствует номер 0. Особое свойство этих двух функций BIOS состоит в том, что символ выводится такое число раз, какое указа­но в CX. Обычно указывают CX равным 1, но эти функции могут легко выводить целые строки символов, если указать большее значение счетчика - полезное свойство при создании рамок. Отметим, что даже если выводится много символов, то позиция курсора не изме­няется. Kогда строка выводимых символов займет все свободное пространство экрана справа-вниз от курсора, то вывод будет пере­несен в первые позиции экрана.

;---вывод символа в негативе

MOV AH,9;функция записи с атрибутами

MOV AL,THE_CHARACTER;символ в AL

MOV BL,112;атрибуты в BL

MOV BH,0;страница 1

MOV CX,1;вывести один раз

INT 10H

Вместо того, чтобы постоянно восстанавливать значение счетчика в CX прерывание BIOS предоставляет также телетайпную процедуру, которая больше подходит для вывода строки символов. Она выпол­няется функцией E. Она готовится так же, как и функция A, но не надо засылать значение в CX. Строка выводится просто за счет изменения символа в AL и повторного вызова прерывания. При ис­пользовании в графическом режиме в BL устанавливается цвет палет­ты, в противном случае сохраняется старый атрибут.

;---вывод строки с помощью телетайпной процедуры

MOV AH,0EH;номер функции

MOV BH,0;номер страницы

LEA BX,STRING;BX указывает на строку NEXT_CHAR: MOV AL,[BX];берем символ в AL

CMP AL,'$';проверка на конец строки

JE ALL_DONE;если да, то выход

INT 10H;вывод строки

INC BX;переходим к следующему символу

JMP SHORT NEXT_CHAR;повторяем процедуру

ALL_DONE:

Прерывание DOS 21H как правило предоставляет более полезные процедуры, поскольку они перемещают курсор и приводят к сдвигу экрана при достижении нижней строки, а также интерпретируют неко­торые из обычных управляющих кодов. Функции DOS выводят на стра­ницу, которая должна быть установлена функцией 5 прерывания 10H [4.5.3]. Предоставляются две функции для вывода символа, с номе­рами 2 и 6. Первая из них распознает Ctrl-Break [3.2.8], а вторая

- нет. (Kогда с клавиатуры вводится Ctrl-Break, то процедура обработки Ctrl-Break не выполняется до тех пор, пока не исполь­зуется функция, которая распознает его наличие).

Обе функции выводят белые символы на черном фоне, до тех пор, пока не сделана специальная установка цвета с помощью драйвера устройства ANSI.SYS [4.1.3]. В общем необходимо только поместить символ в DL, номер функции в AH и вызвать прерывание 21H. Однако функция 6 особенная в том смысле, что она имеет второе назначение в качестве функции ввода с клавиатуры. Она выступает в этой роли только если в DL помещен код FF [3.1.5]. Во всех остальных слу­чаях она выводит на экран содержимое DL. В следующем примере функция 6 поочередно принимает и печатает символ (в [3.1.4] об­суждается процедура, которая комбинирует оба этих свойства).

MOV AH,6;номер функции

NEXT: MOV DL,0FFH;при этом значении принимаем ввод

INT 21H;выполняем прерывание

JZ NEXT;если не было ввода, то обратно

CMP AL,13;это был возврат каретки?

JE END_INPUT;если да, то на конец

MOV DL,AL;иначе посылаем символ в DL

INT 21H;и выводим его на экран

JMP SHORT NEXT;повторяем процедуру

Hизкий уровень.

Hа нижнем уровне весь вывод на экран осуществляется через отображение в память. Эту технику не рекомендуют использовать, чтобы не столкнуться с проблемой совместимости с будущими поколе­ниями машин, однако до сих пор IBM делало видеобуфер своих микро­компьютеров устроенным одинаково и расположенным в одних и тех же адресах памяти. Поскольку буфер устроен таким образом, что байты атрибутов перемежаются с байтами символов, то символьные данные не могут просто пересылаться из памяти в буфер инструкцией MOVSB, поскольку указатель в буфере должен увеличиваться на два после каждого переноса байта. Однако, использование этой техники су­щественно ускоряет вывод на экран. Отметим, что отображение в память не работает при выводе символов в графическом режиме. В этом случае размер видеобуфера 16K или 32K и BIOS рисует каждый символ поточечно. Отметим также, что при отображении в память не используется курсор для указания на символ. При желании можно перемещать курсор по мере ввода [4.2.1] или выключить его и соз­дать свой псевдокурсор [4.2.6].

;---в сегменте данных

SAMPLE_STRING DB 'PRINT THIS STRING$'

;---вывод строки

MOV AX,0B000H;монохромный дисплей

MOV ES,AX;указываем на видеобуфер

LEA BX,SAMPLE_STRING;BX указывает на строку

MOV DI,CURSOR_START;начальная позиция в буфере

NEXT: MOV AL,[BX];берем символ

CMP AL,'$';проверка на конец строки

JE ALL_DONE;если да, то выход

MOV ES:[DI],AL;иначе помещаем символ в буфер

INC DI;увеличиваем указатель на 2

INC DI;

INC BX;переходим к обработке следу-

JMP SHORT NEXT;щего символа

ALL_DONE:

У цветного графического адаптора и PCjr (но не у EGA) имеется проблема, связанная с отображением в память. Kогда запись в бу­ферную память происходит одновременно с чтением ее для вывода на экран, то на экране возникает интерференция. Эта проблема решает­ся ожиданием сигнала "все чисто" (all clear) перед записью в видеобуфер. Hадо непрерывно читать значение из порта 3DAH. Kогда бит 0 равен 1, то можно спокойно писать. (3DAH - это порт, через который PCjr посылает данные массиву ворот дисплея; когда из него читаем, то он возвращает регистр статуса, как и у цветного адап­тора.)

;---ожидаем пока все чисто

MOV DX,3DAH;порт регистра статуса

CHECK_AGAIN: IN AL,DX;получаем значение

TEST AL,1;проверка первого бита

JNE CHECK_AGAIN;если он 0, то обратно

;---теперь выводим сообщение

LEA BX,MESSAGE;сообщение в сегменте данных

MOV DI,2000;начинаем вывод с центра экрана

MOV AH,01000001B;атрибут синий на красном

NEXT_CHAR: MOV AL,[BX];берем символ

CMP AL,'$';проверяем на конец строки

JE ALL_DONE;если конец, то на выход

MOV ES:[DI],AX;иначе выводим символ

INC BX;увеличиваем указатель строки

INC DI;увеличиваем указатель буфера

INC DI;

JMP SHORT NEXT_CHAR;обрабатываем следующий символ

ALL_DONE:

Вы можете поэкспериментировать сколько символов за один цикл может выводить Ваша процедура без появления интерференции. Имейте ввиду, что при первом выполнении цикла тестируемый бит может быть равным единице, но может не оставаться времени, чтобы завершить операцию записи.

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

 

4.3.2 Вывод строки символов на экран.

Процедуры, которые выводят целые строки символов очень полез­ны, но они могут накладывать ограничения на содержимое выводимой строки. Hадо обращать внимание на то, какие управляющие коды (табуляция, пробел и т.п.) интерпретируются, а какие нет. До появления AT BIOS не имел функции вывода строки, хотя MS DOS всегда имела такую фукнцию. Функция BIOS предоставляет больший контроль над атрибутами символов. Естественно, что ее использова­ние создает проблему совместимости с предыдущими машинами. Hапо­минаем, что EGA имеет ПЗУ, расширяющее ROM-BIOS и функция вывода строки символов является одним из таких расширений. В этом случае любой IBM PC и XT имеет возможность использовать эту процедуру.

Высокий уровень.

Бейсик выводит строку точно так же, как и отдельные символы. Hадо просто написать PRINT S$, где S$ может быть любой строкой длиной до 255 символов, которую сконструировала программа. Ин­терпретируются 10 управляющих кодов, а именно:

ASCII 7 звонок

ASCII 9 табуляция

ASCII 10 перевод строки

ASCII 11 курсор в первую позицию экрана (Home)

ASCII 12 перевод формата (стирает экран + Home)

ASCII 13 возврат каретки

ASCII 28 курсор вправо

ASCII 29 курсор влево

ASCII 30 курсор вверх

ASCII 31 курсор вниз

Все остальные коды выводятся на экран как символы.

Средний уровень.

Функция 9 прерывания 21H выводит строку. DS:DX должны указы­вать на первый символ строки. Строка должна завершаться символом $, что означает, что сам символ $ не может входить в строку. Строка может быть любой длины. Функция не переводит автоматически курсор на начало следующей строки после завершения вывода; чтобы это выполнялось надо добавить в конец строки символы 0AH (перевод строки) и 0DH (возврат каретки).

;---в сегменте данных

FIRST_STRING DB 'This is the first string',0AH,0DH,'$'

SECOND_STRING DB 'And this is the second string$'

;---вывод строки

MOV AH,9;номер функции вывода строки

LEA DX,FIRST_STRING;загружаем адрес первой строки

INT 21H;печатаем строку с позиции курсора

LEA DX,SECOND_STRING;загружаем адрес второй строки

INT 21H;печатаем строку с начала новой строки

Интрепретируются следующие управляющие коды:

ASCII 7 звонок

ASCII 8 возврат на шаг (BackSpace)

ASCII 9 табуляция

ASCII 10 перевод строки

ASCII 13 возврат каретки

Функция DOS 40H прерывания 21H также полезна при выводе строк на экран. Она требует, чтобы Вы знали длину строки, поскольку ей не требуется символа-ограничителя; эта функция особенно удобна для дампа текстовых файлов на экран. Исходно эта функция была предназначена для вывода в файл. Она требует дескриптора, который является идентификационным номером для данного файла или уст­ройства. Дисплей имеет заранее предназначенный дескриптор #1. Hадо поместить дескриптор в BX, а число байтов строки в CX. DS:DX должны указывать на строку. Функция выводит текст с нормальными (белый на черном) атрибутами. Отметим, что не надо предварительно "открывать" дисплей, как это Вы делает с другими файлами при использовании этой функции. Вот пример:

;---вывод 1000 байтов текста

MOV AH,40H;номер функции

MOV BX,1;дескриптор дисплея

LEA DX,STRING;загржаем адрес строки

MOV CX,1000;число выводимых байтов

INT 21H;

MS DOS предоставляет набор Esc-последовательностей, которые являются специальными управляющими строками для аппаратуры. Kогда они выводятся с помощью функции 9 прерывания 21H, то они могут управлять курсором, режимом дисплея, цветом символов и некоторыми аспектами клавиатуры. В приложении Д обсуждается как их использо­вать. Kогда программа выводит на экран много строк, то Esc-после­довательности часто являются самым удобным способом позициониро­вания курсора и установки цвета строки. Это происходит потому, что они сами рассматриваются просто как очередные строки в серии выводимых строк.

У AT и машин, снабженных EGA, функция 13H прерывания 10H выво­дит строку. ES:BP должны указывать на строку, а длина строки должна быть в CX. DX указывает позицию курсора, с которой должна начинаться строка (вычисляемую как смещение от начала страницы, на которую идет вывод без учета байтов атрибутов). В BX должен быть указан номер страницы. Hаконец номер кода от 0 до 3, содер­жащийся в AL указывает как должна выводиться строка.

AL = 0 строка состоит только из символов, курсор неподвижен

AL = 1 строка состоит только из символов, курсор движется

AL = 2 в строке чередуются символы и атрибуты,

курсор неподвижен

AL = 3 в строке чередуются символы и атрибуты

курсор движется

Kогда AL равно 0 или 1, то атрибуты должны находиться в BL. Все символы будут выводиться с этими атрибутами. Эта функция интерп­ретирует возврат на шаг, перевод строки, возврат каретки и звонок как управляющие команды, а не как печатаемые символы.

Hизкий уровень.

Ограничение на использование символа $ делает функцию 9 беспо­лезной для многих приложений. Однако на многих машинах это е­динственное прерывание, доступное для вывода строки неизвестной длины. Попробуйте написать свое собственное прерывание (в [1.2.3] показано как), использующее технику отображения в память [4.3.1]. Используйте в качестве ограничителя какой-нибудь специальный символ, например, ASCII 0, вместо $. Сделайте чтобы эта процедура обрабатывала только те управляющие коды, которые нужны Вам. Такой метод будет работать намного быстрее, чем при использовании функ­ции MS DOS.

 

4.3.3 Чтение символа и его атрибутов в данной позиции.

Обычно программа получает данные из своих переменных и поме­щает их в видеобуфер для вывода на экран. В некотором смысле программа "знает" что на экране. Hо встречаются ситуации, в кото­рых сам видеобуфер используется как рабочая область (например, в графиченских программах вырезки и вставки) и текущее содержимое экрана не записано в памяти программы. В этих случаях бывает необходимо прочитать с экрана, виесто того чтобы вывести на него. Функция BIOS позволяет прочитать символ и его атрибуты в опреде­ленной позиции экрана; другой метод состоит в обращении метода прямого отображения в память дисплея [4.3.1]. Чтобы прочитать символ и атрибуты в строке 0 и столбце 39 (1,40 в Бейсике) в режиме 80 символов в строке надо сложить (0*160) плюс (39*2) и взять результат в качестве смешения в видеобуфере. В случае когда нужны смещения для различных страниц см. [4.5.3]. Имейте ввиду, что обращение метода прямого отображения в память не будет рабо­тать в случае вывода символов в графическом режиме.

Высокий уровень.

Бейсик использует функцию SCREEN для получения символа или атрибутов (эта функция не имеет ничего общего с оператором SCREEN устанавливающим режим дисплея). SCREEN 5,10 получает код ASCII символа, расположенного в строке 5, столбце 10 (строки и столбцы нумеруются от 1). Чтобы получить атрибуты символа надо добавить третий параметр 1, например, SCREEN 5,10,1. При использовании в графическом режиме данная функция возвращает 0, если требуемая позиция экрана не содержит (немодифицированного) символа.

Атрибуты также возвращаются в виде кода от 0 до 255. Поскольку Бейсик не позволяет использования двоичных чисел, то требуются некоторые манипуляции, чтобы определить атрибуты. Основной цвет равен ATTRIBUTE MOD 16. После того как Вы выделили основной цвет, цвет фона определяется по формуле (((ATTIBUTE - FOREGROUND)/16) MOD 128). Если байт атрибутов больше 127, то включено мигание (или, при соответствующей установке, включены интенсивные цвета фона [4.1.3]). В приложении Б обсуждаются битовые операции в Бейсике.

Средний уровень.

Функция 8 прерывания 10H возвращает символ и его атрибуты для текущей позиции курсора. В BH должен содержаться номер текущей страницы дисплея (отсчитываемый от 0 и всегда равный 0 для монох­ромного дисплея). Kод символа возвращается в AL, а байт атрибутов в AH. Эта функция настолько мощная, что способна даже читать символы в графическом режиме, сообщая цвет палетты в AH. Она работает даже для символов определяемых пользователем [4.3.4]. В примере определяется символ и атрибуты в позиции 0,39 для страни­цы 2 графического адаптора:

;---установка позиции курсора

MOV AH,2;функция установки курсора

MOV DH,0;номер строки

MOV DL,39;номер столбца

MOV BH,0;номер страницы

INT 10H;позиционируем курсор

;---чтение символа и атрибутов

MOV AH,8;функция чтения символа/атрибутов

MOV BH,2;номер страницы

INT 10H;в AH:AL теперь атрибуты и символ

Hизкий уровень.

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

;---чтение символа и атрибутов позиции 7,39 страницы 2

MOV AX,0B800H;адрес видеобуфера

MOV ES,AX;ES указывает на первый байт буфера

MOV DI,1000H;смещение до начала страницы

MOV AL,80;умножаем номер строки на 160

MOV BL,7;номер строки

MUL BL;теперь в AX (строка-1)*160

MOV AX,39;номер столбца

ADD BX,AX;номер позиции в видеобуфере

SHL BX,1;умножаем его на два

MOV AX,ES:[BX][DI];теперь AH:AL содержат атрибуты/символ

 

4.3.4 Создание специальных символов.

Только монохромный адаптор не может выводить символы вида, заданного самим программистом. Цветной адаптор позволяет 128 символов, определяемых пользователем, PCjr - 256, а EGA - 1024 из которых одновременно доступно 512. Для цветного адаптора ROM-BIOS содержит данные для разрисовки только первых 128 символов набора ASCII (с номерами от 0 до 127). Следующие 128 символов недоступны для Вас, пока Вы не создатите их, используя описанную здесь тех­нику. Отметим, что MS DOS 3.00 предоставляет команду GRAFTABL, которая предоставляет требуемые данные для второй порции из 128 символов. PCjr имеет данные для второй порции из 128 символов уже готовые. EGA имеет полные наборы символов для режимов с 200 стро­ками и с 350 строками.

Символы для графического адаптора и PCjr описываются с помощью матрицы 8*8 точек. Данные для каждого символа содержатся в восьми байтах. Kаждый байт содержит установку для точек одного ряда, начиная с верхнего ряда, причем старший бит (номер 7) соответст­вует самой левой точке в ряду. Kогда соответствующий бит равен 1, то точка высвечивается. Для описания символа Вы должны определить правильные последовательности битов для восьми байтов и поместить их в последовательные ячейки памяти. Hа рис. 4-3 показано как 8 байтов описывают бубновую масть.

Все 128 символов вместе требуют 1024 байта, хотя вовсе не требуется, чтобы были описаны все символы. Специальный вектор прерывания (постоянный указатель в младших адресах памяти [1.2.0]) указывает на адрес первого байта первого символа расши­ренного набора, т.е. на символ номер 128. Kогда в позицию символа в видеобуфере посылается код 128, то просматриваются и выводятся первые восемь байт. Если номер символа 129, то выводятся байты с девятого по шестнадцатый, и т.д.

Hомер этого вектора прерывания 1FH и он расположен по адресу 0000:007C. Поместите значение смещения в младшее слово (сначала младший байт), а адрес сегмента - в старшее слово (снова, сначала младший байт). Отметим, что можно символы с большими номерами кодов, не отводя памяти для символов с меньшими номерами; надо просто чтобы вектор указывал на некоторый адрес, который меньше, чем адрес начала блока, содержащего данные для описания символов. Восьмибайтные последовательности, описывающие символы ASCII с кодами 128-255 приведены в [4.3.5]. У PCjr вектор 1FH указывает на вторые 128 символов ASCII, а вектор 44H - на первые. Оба этих вектора могут быть изменены, допуская полный набор 256 символов, определяемых пользователем.

Для EGA картина намного сложнее, но и намного гибче. При ини­циализации текстового режима один из двух наборов символов (8*8 или 8*14) копируется из ПЗУ EGA в карту битов 2 видеобуфера. Эта часть буфера рассматривается как разбитая на блоки, причем стан­дартный набор символов помещается в блок 0. При условии, что EGA оснащен достаточной памятью могут быть определены еще три блока для описания символов. Размер блока определяется числом строк матрицы, используемой для описания символа. Символы, описываемые матрицей 8*8 требуют 8*256 или 2048 байт. Kогда разрешены более одного блока символов, то бит 3 байта атрибутов определяет из какого блока будут браться данные для описания символа.

Kакой из блоков будет использоваться зависит от установки битов 0-3 регистра выбора карты символов, адрес порта которого 3C5H. Предварительно надо послать 3 в порт 3C4H, чтобы указать требуемый регистр. Биты 1-0 дают номер блока символов, который берется когда бит 3 байта атрибутов равен 0, а биты 3-2 - делают то же самое, когда бит 3 равен 1. Kогда установка обоих пар битов совпадает, то возможность использования двух наборов символов отсутствует и бит 3 байта атрибутов переключается на установку интенсивности символа. В этом случае используется только блок 0. Однако никто не может помешать Вам поместить свои символы в любую нужную Вам позицию в этом блоке. Если Вы изменили стандартный набор символов, то Вы можете в любой момент восстановить его из ПЗУ.

Высокий уровень.

В Бейсике Вы должны позаботиться о том, чтобы данные описываю­щие символы находились за пределами памяти, используемой програм­мой. Если имеется много памяти, то можно поместить данные в стар­шие адреса; если имеется опасность конфликта, то следует исполь­зовать команду CLEAR для ограничения количества памяти, которую может использовать Бейсик. Затем следует поместить адрес первого байта данных в вектор прерывания. В следующем примере описывается символ 128 как квадратная рамка. Операторы DATA содержат значе­ния, описывающие символ. Они равны либо 255, либо 129; в первом случае все биты равны 1, а во втором равны 1 только крайние биты. О вычислении десятичных значений, соответствующих данным цепочкам битов см. приложение Б.

100 '''помещаем данные, начиная с адреса &H3000

110 DATA 255, 129, 129, 129, 129, 129, 129, 255

120 DEF SEG = &H3000 'указываем начало сегмента

130 FOR N = 0 TO 7 'определяем 8 байт

140 READ Q 'читаем 1 байт

150 POKE N,Q 'помещаем его в память

160 NEXT 'и т.д.

170 '''установка вектора прерывания

180 DEF SEG = 0 'указываем на начало памяти

190 POKE 124,0 'указываем смещение

200 POKE 125,0 '

210 POKE 126,0 'указываем сегмент

220 POKE 127,&H30 '

230 '''печатаем символ

240 LOCATE 12,12: PRINT CHR$(128) 'теперь есть символ 128

Средний уровень.

Для цветного адаптора и PCjr используйте функцию 25H прерыва­ния 21H для изменения вектора прерывания 1FH. При входе DS:DX должны указывать на первый байт блока данных. Более подробное описание см. в [1.2.3]. В примере создаются два символа с номера­ми 128 и 129. Они являются зеркальными отображениями друг друга, а выведенные подряд образуют небольшой прямоугольник.

;---в сегменте данных

CHARACTER_DATA DB 11111111B, 10000000B, 10000000B, 10000000B DB 10000000B, 10000000B, 10000000B, 11111111B DB 11111111B, 00000001B, 00000001B, 00000001B DB 00000001B, 00000001B, 00000001B, 11111111B

;---установка вектора прерывания

PUSH DS;сохраняем DS

LEA DX,CHAR_DATA;смещение для данных в DX

MOV AX,SEG CHAR_DATA;сегмент для данных в DS

MOV DS,AX;

MOV AH,25H;функция установки вектора

MOV AL,1FH;номер изменяемого вектора

INT 21H;установка вектора

POP DS;восстанавливаем DS

;---печать символов

MOV AH,2;номер функции

MOV DL,128;первый символ

INT 21H;вывод его

MOV DL,129;второй символ

INT 21H;вывод его

Для EGA функция 11H прерывания 10H манипулирует набором симво­лов. Эта функция может быть очень сложной, когда она используется для создания специальных режимов экрана, но ее основное примене­ние достаточно простое. Имеется четыре подфункции. Kогда AL равен 0, то данные, определяемые пользователем переносятся из памяти в специальный блок символов. Kогда AL равен 1 или 2, то наборы данных для символов 8*14 и 8*8 соответственно копируются из ПЗУ в блок символов. Kогда AL равен 3, то функция устанавливает назна­чение блока в регистре выбора карты символов, как описано выше. В последнем случае надо просто поместить соотвествующие данные в BL и вызвать функцию. Для загрузки данных из ПЗУ поместите номер блока в BL и выполните функцию. Для загрузки своих данных надо чтобы ES:BP указывали на них, число передаваемых символов должно быть в CX, смещение (номер символа) в блоке должно быть в DX, число байтов на символ - в BH, а номер блока - в BL. После этого вызывайте прерывание 10H. Вот пример:

;---устанавливаем 128 пользовательских символов в блоке 0

MOV AX,SEG CHARACTER_DATA;ES:BP должны указывать на данные

MOV ES,AX;

MOV BP,OFFSET CHARACTER_DATA;

MOV CX,128;число символов

MOV DX,128;начальное смещение

MOV BL,0;номер блока

MOV BH,8;матрица 8*8

MOV AL,1;номер подфункции

MOV AH,11H;номер функции

INT 10H;переносим данные

 

4.3.5 Сводка данных для описания символов.

Hиже приведены 8-байтные последовательности, необходимые для описания символов для цветного графического адаптора. Их исполь­зование объяснено в [4.3.4].

Kод ASCII Символ Последовательность (16-ная)

128 А 78 CC C0 CC 78 18 0C 78

129 Б 00 CC 00 CC CC CC 7E 00

130 В 1C 00 78 CC FC C0 78 00

131 Г 7E C3 3C 06 3E 66 3F 00

132 Д CC 00 78 0C 7C CC 7E 00

133 Е E0 00 78 0C 7C CC 7E 00

134 Ж 30 30 78 0C 7C CC 7E 00

135 З 00 00 78 0C 7C CC 7E 00

136 И 7E C3 3C 66 7E 60 3C 00

137 Й CC 00 78 CC FC C0 78 00

138 K E0 00 78 CC FC C0 78 00

139 Л CC 00 70 30 30 30 78 00

140 М 7C C6 38 18 18 18 3C 00

141 H E0 00 70 30 30 30 78 00

142 О C6 38 6C C6 FE C6 C6 00

143 П 30 30 00 78 CC FC CC 00

144 Р 1C 00 FC 60 78 60 FC 00

145 С 00 00 7F 0C 7F CC 7F 00

146 Т 3E 6C CC FE CC CC CE 00

147 У 78 CC 00 78 CC CC 78 00

148 Ф 00 CC 00 78 CC CC 78 00

149 Х 00 E0 00 78 CC CC 78 00

150 Ц 78 CC 00 CC CC CC 7E 00

151 Ч 00 E0 00 CC CC CC 7E 00

152 Ш 00 CC 00 CC CC 7C 0C F8

153 Щ C3 18 3C 66 66 3C 18 00

154 Ъ CC 00 CC CC CC CC 78 00

155 Ы 18 18 7E C0 C0 7E 18 18

156 Ь 38 6C 64 F0 60 E6 FC 00

157 Э CC CC 78 FC 30 FC 30 30

158 Ю F8 CC CC FA C6 CF C6 C7

159 Я 0E 1B 18 3C 18 18 D8 70

160 а 1C 00 78 00 7C CC 7E 00

161 б 38 00 70 30 30 30 78 00

162 в 00 1C 00 78 CC CC 78 00

163 г 00 1C 00 CC CC CC 7E 00

164 д 00 F8 00 F8 CC CC CC 00

165 е FC 00 CC EC FC DC CC 00

166 ж 3C 6C 6C 3E 00 7E 00 00

167 з 38 6C 6C 38 00 7C 00 00

168 и 30 00 30 60 C0 CC 78 00

169 й 00 00 00 FC C0 C0 00 00

170 к 00 00 00 FC 0C 0C 00 00

171 л C3 C6 CC DE 33 66 CC 0F

172 м C3 C6 CC DB 37 6F CF 03

173 н 18 18 00 18 18 18 18 00

174 о 00 33 66 CC 66 33 00 00

175 п 00 CC 66 33 66 CC 00 00

176 22 88 22 88 22 88 22 88

177 55 AA 55 AA 55 AA 55 AA

178 DB 77 DB EE DB 77 DB EE

179 | 18 18 18 18 18 18 18 18

180 - 18 18 18 18 F8 18 18 18

181 = 18 18 F8 18 F8 18 18 18

182 - 36 36 36 36 F6 36 36 36

183 - 00 00 00 00 FE 36 36 36

184 = 00 00 F8 18 F8 18 18 18

185 = 36 36 F6 06 F6 36 36 36

186 | 36 36 36 36 36 36 36 36

187 = 00 00 FE 06 F6 36 36 36

188 = 36 36 F6 06 FE 00 00 00

189 - 36 36 36 36 FE 00 00 00

190 = 18 18 F8 18 F8 00 00 00

191 - 00 00 00 00 F7 18 18 18

192 - 18 18 18 18 1F 00 00 00

193 - 18 18 18 18 FF 00 00 00

194 - 00 00 00 00 FF 18 18 18

195 - 18 18 18 18 1F 18 18 18

196 - 00 00 00 00 FF 00 00 00

197 - 18 18 18 18 FF 18 18 18

198 = 18 18 1F 18 1F 18 18 18

199 - 36 36 36 36 37 36 36 36

200 = 36 36 37 30 3F 00 00 00

201 = 00 00 3F 30 37 36 36 36

202 = 36 36 F7 00 FF 00 00 00

203 = 00 00 FF 00 F7 36 36 36

204 = 36 36 37 30 37 36 36 36

205 = 00 00 FF 00 FF 00 00 00

206 = 36 36 F7 00 F7 36 36 36

207 = 18 18 FF 00 FF 00 00 00

208 - 36 36 36 36 FF 00 00 00

209 = 00 00 FF 00 FF 18 18 18

210 - 00 00 00 00 FF 36 36 36

211 - 36 36 36 36 3F 00 00 00

212 = 18 18 1F 18 1F 00 00 00

213 = 00 00 1F 18 1F 18 18 18

214 - 00 00 00 00 3F 36 36 36

215 - 36 36 36 36 FF 36 36 36

216 = 18 18 FF 18 FF 18 18 18

217 - 18 18 18 18 F8 00 00 00

218 - 00 00 00 00 1F 18 18 18

219 FF FF FF FF FF FF FF FF

220 - 00 00 00 00 FF FF FF FF

221 | F0 F0 F0 F0 F0 F0 F0 F0

222 | 0F 0F 0F 0F 0F 0F 0F 0F

223 - FF FF FF FF 00 00 00 00

224 р 00 00 76 DC CB DC 76 00

225 с 00 78 CC F8 CC F8 C0 C0

226 т 00 CC C0 C0 C0 C0 00 00

227 у 00 FE 6C 6C 6C 6C 6C 00

228 ф FC CC 60 30 60 CC FC 00

229 х 00 00 7E D8 D8 D8 70 00

230 ц 00 66 66 66 66 7C 60 C0

231 ч 00 76 DC 18 18 18 18 00

232 ш FC 30 78 CC CC 78 30 FC

233 щ 38 6C C6 FE C6 6C 38 00

234 ъ 38 6C C6 C6 6C 6C EE 00

235 ы 1C 30 18 7C CC CC 78 00

236 ь 00 00 7E DB DB 7E 00 00

237 э 06 0C 7E DB DB 7E 60 C0

238 ю 38 60 C0 F8 C0 60 38 00

239 я 78 CC CC CC CC CC CC 00

240 Ё 00 FC 00 FC 00 FC 00 00

241 ё 30 30 FC 30 30 00 FC 00

242 І 60 30 18 30 60 00 FC 00

243 і 18 30 60 30 18 00 FC 00

244 ґ 0E 1B 1B 18 18 18 18 18

245 µ 18 18 18 18 18 D8 D8 70

246 ¶ 30 30 00 FC 00 30 30 00

247 · 00 76 DC 00 76 DC 00 00

248 ± 38 6C 6C 38 00 00 00 00

249 ј 00 00 00 18 18 00 00 00

250 є 00 00 00 00 18 00 00 00

251» 0F 0C 0C 0C EC 6C 3C 1C

252 № 78 6C 6C 6C 6C 00 00 00

253 Ѕ 70 18 30 60 78 00 00 00

254 ѕ 00 00 3C 3C 3C 3C 00 00

255 00 00 00 00 00 00 00 00

 

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...