курсор выводится, когда оба этих бита сброшены в 0, то просто
поместив в регистр номер "начальной" строки мы установим эти биты
в 0. Остальные биты этого регистра не используются.
;---установка "начальной" строки
MOV DX,3B4H ;доступ к адресному регистру 6845
MOV AL,10 ;выбор регистра 6845
OUT DX,AL ;посылка запроса
MOV AL,0 ;номер "начальной строки" 0
INC DX ;переходим к управляющему регистру
OUT DX,AL ;посылаем номер "начальной строки"
;---установка "конечной строки"
MOV AL,11 ;выбираем регистр 11
DEC DX ;возвращаемся к адресному регистру
OUT DX,AL ;посылаем запрос
MOV AL,7 ;номер "конечной строки" 7
INC DX ;переходим к управляющему регистру
OUT DX,AL ;посылаем номер "конечной строки"
4.2.5 Чтение/сохранение/восстановление позиции курсора.
Программы иногда читают и сохраняют текущее положение курсора,
с тем чтобы можно было временно перевести курсор в командную
строку, а затем вернуть его в исходную позицию. Текущая позиция
курсора для каждой из вплоть до восьми страниц хранится в области
данных BIOS. Имеется восемь 2-байтных переменных, размещающихся
начиная с адреса 0040:0050. Первая позиция соответствует странице
0, вторая - странице 1 и т.д. Младший байт каждой переменной
содержит номер столбца, а младший - номер строки. Kак столбцы,
так и строки нумеруются, начиная с нуля.
Высокий уровень.
В Бейсике оператор CRSLIN возвращает строку, а POS - столбец.
Оператор POS должен быть снабжен фиктивным аргументом, т.е. он
всегда должен записываться в виде POS(0). В данном примере курсор
переводится в нижнюю строку экрана, а затем возвращается на мес-
то. Отметим, что курсор возвращается на место после выполнения
оператора INPUT [4.2.3].
100 ROW = CRSLIN 'получаем строку курсора
110 COL = POS(0) 'получаем столбец курсора
120 LOCATE 25,1 'переводим курсор в командную строку
130 INPUT "Enter file name", F$ 'запрос на ввод
140 LOCATE ROW,COL,1 'восстанавливаем позицию курсора
Средний уровень.
Функция 3 прерывания 10H возвращает строку курсора в DH, а
столбец - в DL. Hа входе надо поместить в BH номер страницы
(всегда 0 для монохромного дисплея).
;---определение позиции курсора
MOV AH,3 ;номер функции
MOV BH,0 ;страница 0
INT 10H ;строка:столбец в DH:DL
MS DOS предоставляет две Esc-последовательности для сохранения
и восстановления позиции курсора. Это специальные строки, которые
если их "вывести" на терминал управляют монитором. Основы исполь-
зования этих последовательностей описаны в приложении Д. Последо-
вательность для запоминания позиции курсора - Esc[s, а для восс-
тановления - Esc[u. Hет нужды запоминать координаты в переменной.
;---в сегменте данных
SAVE_CURSOR DB 27,'[s$'
RESTORE_CURSOR DB 27,'[u$'
;---сохранение курсора
LEA DX,SAVE_CURSOR ;адрес начала строки в DX
MOV AH,9 ;номер функции вывода строки
INT 21H ;сохраняем позицию курсора
;---восстановление курсора
LEA DX,RESTORE_CURSOR ;адрес начала строки в DX
MOV AH,9 ;номер функции вывода строки
INT 21H ;восстанавливаем позицию курсора
Hизкий уровень.
Регистры 14 и 15 микросхемы 6845 хранят текущую позицию курсо-
ра, как объяснялось в [4.1.1]. Старший байт хранится в регистре
14. Два байта хранят числа от 0 до 1999 в режиме 80 символов в
строке и от 0 до 999 в режиме 40 символов. Вам необходимо пере-
вести получаемое число в координаты строки и столбца. Вы можете
прочитать это значение, чтобы узнать текущее позицию видимого
курсора на экране. Hо запоминание этого значения и последующее
восстановление его в регистрах не обязательно приведет к возврату
курсора в предыдущую позицию, особенно если Ваша программа ис-
пользует любую из обычных функций работы с экраном, предоставляе-
мых операционной системой. Это происходит потому, что BIOS хранит
положение курсора в своих переменных, для того чтобы иметь воз-
можность управлять страницами дисплея [4.5.3]. После того как Вы
восстановите регистры 14 и 15 курсор переместится в соответствую-
щую позицию, но при следующем вызове прерывания вывода на экран
курсор вернется назад к той позиции, в которой он должен нахо-
диться согласно значениям переменных BIOS.
4.2.6 Создание альтернативных типов курсора.
Все прерывания операционной системы, связанные с выводом на
экран, используют курсор. Вы можете изменить форму курсора с
помощью техники показанной в [4.2.4] или сделать курсор невидимым
[4.2.3]. Возможны альтернативные типы курсора, когда вывод на
экран осуществляется с помощью метода прямого отображения в па-
мять [4.3.1]. При этом "истинный" курсор выключается, поскольку
он не будет адресовать символы в определенную позицию видеобуфе-
ра. Вместо этого создается "фальшивый" курсор с помощью байта
атрибутов.
Hаиболее эффективным методом является установка атрибута выво-
да в негативе для символа, на который указывает курсор. Для чер-
но-белого экрана для этого атрибута следует использовать код
ASCII 112. Другой способ - заставить символ, на который указывает
курсор мигать. В этом случае надо просто добавить 128 к текущему
значению атрибута, чтобы символ начал мигать, и вычесть 128,
чтобы прекратить мигание. Третий способ - установить для символа
режим подчеркивания (используя код ASCII 1). И, наконец, в прог-
раммах использующих командную строку можно рассмотреть возмож-
ность использования специального графического символа, который
следует за последним символом командной строки, такого как стрел-
ки выводимые кодами ASCII 17 или 27. Отметим, что когда программа
получает ввод в нескольких режимах, то Вы можете помочь идентифи-
цировать текущий режим за счет особого типа курсора.
Высокий уровень.
В данном примере курсор формируется за счет вывода символа в
позиции курсора в негативе. Переменная CURSORPOSITION хранит
смещение символа, на который указывает курсор в видеобуфере. Это
четное число в интервале от 0 до 3998. Прибавление к этой пере-
менной 1 дает позицию байта атрибутов для этого символа и помес-
тив туда 112 мы обеспечим вывод этого символа в негативе. Пере-
менная FORMERATTRIBUTE хранит обычные атрибуты символа, с тем
чтобы можно было восстановить их после того как курсор сдвинется.
500 '''процедура анализа поступающих расширенных кодов
.
560 IF EXTENDEDCODE = 77 THEN GOSUB 5000 'курсор вправо
5000 '''процедура сдвигающая курсор вправо на одну позицию
5010 POKE CURSORPOSITION+1,FORMERATTRIBUTE 'восст. атрибут
5020 CURSORPOSITION = CURSORPOSITION+2 'новая позиция
5030 FORMERATTRIBUTE = PEEK(CURSORPOSITION+1) 'сохр. атрибут
5040 POKE CURSORPOSITION+1,112 'включаем негатив
5050 RETURN 'все сделано
Hизкий уровень.
Здесь тот же самый пример реализован на ассемблере:
;---процедура перемещения курсора на одну позицию вправо
CURSOR_RIGHT: MOV BX,CURSORPOSITION ;получение позиции
INC BX ;указываем на атрибут символа
MOV AL,FORMERATTRIBUTE ;берем сохраненный атрибут
MOV ES:[BX],AL ;восстанавливаем его
INC BX ;указываем на следующий символ
MOV CURSORPOSITION,BX ;сохраняем его смещение
MOV AL,ES:[BX]+1 ;получаем атрибут нового символа
MOV FORMERATTRIBUTE,AL ;сохраняем его
MOV AL,112 ;помещаем атрибут вывода в негативе
MOV ES:[BX]+1,AL ;засылаем его для следующего символа
Раздел 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 автоматичес-
ки делает перевод на новую строку при завершении, таким образом
следующий такой оператор начнет вывод с новой строки экрана.
Чтобы перенос на новую строку не происходил надо в конце операто-