Глава 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 Относительное позиционирование курсора-~>