1. Разделим длину 09 на 2 получим 4, и
2. Вычтем это значение из 40, получим 36
Команда SHR в процедуре E10CENT сдвигает длину 09 на oдин бит вправо,
выполняя таким образом деление на 2. Значение бит 00001001 переходит в
00000100. Команда NEG меняет знак +4 На -4. Команда ADD прибавляет
значение 40, получая в регистре DL номер начального столбца - 36. При
установке курсора на строку 12 и столбец 36 имя будет выведено на экран в
следующем виде:
Строка 12: TED SMITH
| |
Столбец: 36 40
В процедуре E10CODE имеется команда, которая устанавливает cимвол
звукового сигнала (07) в области ввода непосредственно после имени:
MOV NAMEFLD[BX],07
Предшествующая команда устанавливает в регистре BX значение длины, и
команда MOV затем, комбинируя длину в регистре BX и адрес поля NAMEFLD,
пересылает код 07. Например, при длине имени 05 код 07 будет помещен по
адресу NAMEFLD+05 (замещая значение кода Return). Последняя команда в
процедуре E10CODE устанавливает ограничитель "$" после кода 07. Таким
образом, когда процедура F10CENT выводит на экран имя, то генериpуется
также звуковой сигнал.
__________________________________________________________________________
page 60,132
TITLE CTRNAME (EXE) Ввод имен и вывод в центр экрана
;--------------------------------------------------------
STSCKSG SEGMENT PARA STACK 'Stack'
DW 32 DUP(?)
STACKSG ENDS
;--------------------------------------------------------
DATASG SEGMENT PARA 'Data'
NAMEPAR LABEL BYTE ;Имя списка параметров:
MAXNLEN DB 20 ; макс. длина имени
NAMELEN DB ? ; число введенных символов
NAMEFLD DB 20 DUP(' '),'$' ;имя и ограничитель для вывода на экран
PRIMPT DB 'Name? ', '$'
DATASG ENDS
;--------------------------------------------------------
CODESG SEGMENT PARA 'Code"
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASC
PUSH DS
SUB AX,AX
PUCH AX
MOV AX,DATASC
MOV DS,AX
MOV ES,AX
CALL Q10CLR ;Очистить экран
A20LOOP:
MOV DX,0000 ;Установить курсор в 00,00
CALL Q20CURS
CALL B10PRMP ;Выдать текст запроса
CALL D10INPT ;Ввести имя
CALL Q10CLR ;Очистить экран
CMP NAMELEN,00 ;Имя введено?
JE A30 ; нет - выйти
CALL E10CODE ;Установить звуковой сигнал
; и ограничитель '$'
CALL F10CENT ;Центрирование и вывод
JMP A20LOOP
A30:
RET ;Вернуться в DOS
BEGIN ENDP
; Вывод текста запроса:
; --------------------
B10PRMP PROC NEAR
MUV AN,09 ;Функция вывода на экран
LEA DX,PROMPT
INT 21H
RET
B10PRMP ENDP
; Ввод имени с клавиатуры:
; -----------------------
D10INPT PROC NEAR
MOV AN,0AN ;Функция ввода
LEA DX,NAMEPAR
INT 21H
RET
D10INPT ENDP
; Установка сигнала и ограничителя '$':
; ------------------------------------
E10CODE PROC NEAR
MOV BN,00 ;Замена символа Return (0D)
MOV BL,NAMELEN ; на зв. сигнал (07)
MOV NAMEFLD[BX],07
MOV NAMEFLD[BX+1],'$' ;Установить ограничитель
RET
E10CODE ENDP
; Центрирование и вывод имени на экран:
; ------------------------------------
F10CENT PROC NEAR
MOV DL,NAMELEN ;Определение столбца:
SHR DL,1 ; разделить длину на 2,
NEG DL ; поменять знак,
ADD DL,40 ; прибавить 40
MOV DH,12 ;Центральная строка
CALL Q20CURS ;Установить курсор
MOV AN,09
LEA DX,NAMEFLD ;Вывести имя на экран
INT 21H
RET
F10CENT ENDP
; Очистить экран:
; --------------
Q10CLR PROC NEAR
MOV AX,0600H ;Функция прокрутки экрана
MOV BH,30 ;Цвет (07 для ч/б)
MOV CX,0000 ;От 00,00
MOV DX,184FH ;До 24,79
INT 10H ;Вызов BIOS
RET
Q10CLR
; Установка курсора (строка/столбец):
; ----------------------------------
Q20CURS PROC NEAR ;DX уже установлен
MOV AH,02 ;Функция установки курсора
MOV BH,00 ;Страница #0
INT 10H ;Вызов BIOS
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.8.2. Ввод и отображение имен.
Ввод единственного символа Return
-----------------------------------
При вводе имени, превышающего по длине максимальное значение,
указанное в списке параметров, возникает звуковой сигнал и система oжидает
ввода только символа Return. Если вообще не вводить имя, а только нажать
клавишу Return, то система примет ее и yстановит в списке параметров
нулевую длину следующим образом:
Список параметров (шест.): |14|00|0D|...
Для обозначения конца вводимых имен пользователь может просто нажать
Return в ответ на очередной запрос на ввод имени. Прогpамма определяет
конец ввода по нулевой длине.
Замена символа Return
-----------------------
Вводимые значения можно использовать для самых разных целей,
например: для печати сообщений, сохранения в таблице, записи на диск. При
этом, возможно, появится необходимость замены символа Return (шест.0D) в
области NAMEFLD на символ пробела (шест.20). Поле NAMELEN содержит
действительную длину или отноcительный адрес кода 0D. Если, например,
NAMELEN содержит длину 05, то адрес кода 0D равен NAMEFLD+5. Можно занести
эту длину в регистр BX для индексной адресации в поле NAMEFLD:
MOV BH,00 ;Установить в регистре BX
MOV BL,NAMELEN ; значение 0005
MOV NAMEFLD[BX],20H ;Заменить 0D на пробел
Третья команда MOV заносит символ пробела (шест.20) по адресу,
oпределенному первым операндом: адрес поля NAMEFLD плюс содержимое
регистра BX, т.е. NAMEFLD+5.
Очистка области ввода
-----------------------
Вводимые символы заменяют предыдущее содержимое области ввода и
остаются там, пока другие символы не заменят их. Рассмотрим следующие три
успешных ввода имен:
Ввод NAMEPAR (шест.)
1. BROWN |14|05|42|52|4F|57|4E|0D|20|20|20| ... |20|
2. HAMILTON |14|08|48|41|4D|49|4C|54|4F|4E|0D| ... |20|
3. ADAMS |14|05|41|44|41|4D|53|0D|4F|4E|0D| ... |20|
Имя HAMILTON заменяет более короткое имя BROWN. Но, так как имя ADAMS
короче имени HAMILTON, то оно заменяет только HAMIL. Код Return заменяет
символ T. Остальные буквы - ON oстаются после имени ADAMS. Для очистки
поля NAMEFLD до ввода очередного имени может служить следующая программа:
MOV CX,20 ;Установить 20 циклов
MOV SI,0000 ;Начальная позиция поля
B30:
MOV NAMEFLD[si],20H ;Переслать один пробел
INC SI ;Следующая позиция поля
LOOP B30 ;20 циклов
Вместо регистра SI можно использовать DI или BX. Более эффективный
способ очистки поля, предполагающий пересылку слова из двух пробелов,
требует только десять циклов. Однако, ввиду того что поле NAMEFLD
определено как DB (байтовое), необходимо изменить длину в команде
пересылки, посредством операнда WORD, a также воспользоваться операндом
PTR (указатель), как показано ниже:
MOV CX,10 ;Установить 10 циклов
LEA SI,NAMEFLD ;Начальный адрес
B30:
MOV WORD PTR[SI],2020H ;Переслать два пробела
INC SI ;Получить адрес
INC SI ; следующего слова
LOOP B30 ;10 циклов
Команда MOV по метке B30 обозначает пересылку слова из двух пробелов
по адресу, находящемуся в регистре SI. В последнем примеpе используется
команда LEA для инициализации регистра SI и несколько иной способ в
команде MOV по метке В30, так как нельзя закодировать, например, следующую
команду:
MOV WORD PTR[NAMEFLD],2020H ;Неправильно
Очистка входной области решает проблему ввода коротких имен, за
которыми следуют предыдущие данные. Еще более эффективный cпособ
предполагает очистку только тех байт, которые расположены после введенного
имени.
ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: РАСШИРЕННАЯ ВЕРСИЯ DOS
________________________________________________________________
Рассмотрим теперь расширенные возможности, введенные в DOS 2.0
(реализованные в стиле операционной системы UNIX). Если вы используете
более младшую версию DOS, то не сможете выполнить примеры из данного
раздела. Расширенные возможности включают файловый номер (file handle),
который yстанавливается в регистре BX, когда требуется выполнить операцию
ввода/вывода. Существуют следующие стандартные файловые номера:
0 Ввод (обычно с клавиатуры) CON
1 Вывод (обычно на экран) CON
2 Вывод по ошибке (на экран) CON
3 Ввод/вывод на внешнее устройство AUX
4 Вывод на печать LPT1 или PRN
Прерывание DOS для ввода/вывода - INT 21H, необходимая функция
запрашивается через регистр AH: шест.3F - для ввода, шест.40 - для вывода.
В регистр CX заносится число байт для ввода/вывода, а в регистр DX - адрес
области ввода/вывода.
В результате успешного выполнения операции ввода/вывода очищается
флаг переноса (CF) и в регистр AX устанавливается действительное число
байт, участвующих в операции. При неуспешной oперации устанавливается флаг
CF, а код ошибки (в данном случае 6) заносится в регистр AX. Поскольку
регистр AX может содержать как длину данных, так и код ошибки, то
единственный способ определить наличие ошибки - проверить флаг CF, хотя
ошибки чтения с клавиатуры и вывода на экран - явления крайне редкие.
Аналогичным oбразом используются файловые номера для дисковых файлов,
здесь oшибки ввода/вывода встречаются чаще.
Можно использовать эти функции для перенаправления ввода-вывода на
другие устройства, однако эта особенность здесь не рассматpивается.
ВЫВОД НА ЭКРАН: РАСШИРЕННАЯ ВЕРСИЯ DOS
________________________________________________________________
Следующие команды иллюстрируют операцию вывода на экран в расширенной
версии DOS:
DISAREA DB 20 DUP(' ') ;Область данных
...
MOV AH,40H ;Запрос на вывод
MOV BX,01 ;Выводное устройство
MOV CX,20 ;Максимальное число байт
LEA DX,DISAREA ;Адрес области данных
INT 21H ;Вызов DOS