Глава 4. Вывод на терминал.

Раздел 2. Управление курсором.

4.2.1 Установка курсора в абсолютную позицию.

Для курсора могут быть установлены абсолютные координаты или координаты относительно его текущей позиции {4.2.2}. Абсолютные координаты могут меняться в пределах 25 строк и 80 (иногда 40) столбцов. Языки высокого уровня обычно отсчитывают координаты экрана, начиная с 1, и таким образом позиция левого верхнего угла 1,1. Язык ассемблера всегда начинает отсчет с нуля и позиция левого верхнего угла 0,0.

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

Операционная система предоставляет два способа позиционирования курсора в абсолютную позицию на экране. Функция 2 прерывания 10H устанавливает курсор, относящийся к указанной странице памяти. Страницы нумеруются начиная с нуля и для монохромного дисплея номер страницы (находящийся в BH) должен всегда быть равным 0. DH:DL содержат строку и столбец, которые тоже нумеруются с 0. Kурсор меняет свое положение на экране только если установка курсора относится к текущей активной странице.
;---установка курсора в строку 13, столбец 39
MOV AH,2 ;номер функции
MOV BH,0 ;номер страницы
MOV DH,13 ;строка
MOV DL,39 ;столбец
INT 10H ;позиционируем курсор

Второй метод позиционирования курсора состоит в использовании специального драйвера устройства ANSI.SYS, который должен быть загружен при старте системы. В приложении Д даны необходимые сведения. Для вывода строки, содержащей информацию о строке и столбце используется функция 9 прерывания 21H. Строка начинается с символа Esc (ASCII 27), а завершается символом ограничителем $. Формат строки Esc[строка,столбецH$, где строка и столбец нумеруются от нуля, а Esc обозначает код ASCII 27. Hапример, строка 27,'10;60H$' устанавливает курсор в строку 10, столбец 60.

Хотя такой метод кажется излишне сложным, но он оказывается очень удобным при выводе ряда строк на экран, так как Esc-последовательность обрабатывается как одна из строк набора. В данном примере три строки сообщения разбросаны по всему экрану.
;---в сегменте данных
POSITION_1 DB 27,'[10;30H$'
STRING_1 DB 'There are two options:$'
POSITION_2 DB 27,'[13;32H$'
STRING_2 DB '(1) Review part 1$'
POSITION_3 DB 27,'[15;32H$'
STRING_3 DB '(2) Move on to part 2$'
;---печать строк
MOV AH,9 ;номер функции вывода строки
LEA DX,POSITION_1 ;1-я строка позиционирования курсора
INT 21H ;позиционируем курсор
LEA DX,STRING_1 ;1-я текстовая строка
INT 21H ;вывод строки
LEA DX,POSITION_2 ;и т.д.
INT 21H ;
LEA DX,STRING_2 ;
INT 21H ;
LEA DX,POSITION_3 ;
INT 21H ;
LEA DX,STRING_3 ;
INT 21H ;

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

Регистры 14 и 15 микросхемы 6845 хранят положение курсора. Вы можете изменить их значение и курсор передвинется в соответствующую позицию экрана, но прерывания вывода на экран DOS и BIOS будут игнорировать Вашу установку и вернут курсор в старое положение. Это происходит потому, что каждый раз при вызове этих прерываний, они восстанавливают регистры курсора, используя 2-байтное значение, хранящееся в области данных BIOS. В этой области, начиная с адреса 0040:0050, могут находиться до восьми таких значений, давая текущее положение курсора для каждой из страниц дисплея. Процедура низкого уровня должна модифицировать и эти значения, чтобы изменить состояние курсора полностью.

Позиция курсора хранится в регистрах 14 и 15 как число от 0 до 1999, что соответствует 2000 (25*80) позициям экрана. Hе спутайте эту систему нумерации с позициями видеобуфера от 0 до 3999, где каждый символ сопровождается еще байтом атрибутов (для получения эквивалентного указателя на позицию курсора надо сдвинуть указатель видеобуфера на 1 бит вправо). Обращаем также Ваше внимание, на то, что не надо менять местами старший и младший байты: в регистре 14 - старший, а 15 - младший.
;---в программе
MOV BL,24 ;строка в BL (0-24)
MOV BH,79 ;столбец в BH (0-79)
CALL SET_CURSOR ;вызов процедуры
;---процедура установки курсора
SET_CURSOR PROC
;получаем доступ к регистру младшего байта
MOV DX,3B4H ;порт адресного регистра 6845
MOV AL,15 ;выбираем регистр 15
OUT DX,AL ;посылаем запрос
;вычисление позиции курсора
MOV AL,80 ;умножаем номер строки на 80
MUL BL ;в AX - номер строки, умноженный на 80
MOV BL,BH ;переносим номер столбца в BL
SUB BH,BH ;распространяем BL на BX
ADD AX,BX ;вычисляем позицию курсора
;посылаем младший байт результата
INC DX ;адресуем управляющий регистр
OUT DX,AL ;посылаем младший байт
;получаем доступ к регистру старшего байта
MOV AL,14 ;номер требуемого регистра
DEC DX ;восстанавливаем порт адресного регистра
OUT DX,AL ;посылаем запрос
;посылаем старший байт результата
INC DX ;адресуем управляющий регистр
MOV AL,AH ;помещаем старший байт в AL
OUT DX,AL ;посылаем старший байт
RET
SET_CURSOR ENDP


<~-Раздел 2. Управление курсором.
Содержание
4.2.2 Относительное позиционирование курсора-~>

Сайт управляется системой uCoz