Сист. прогр. Ч1 (1085725), страница 12
Текст из файла (страница 12)
INT 21Н ;Вызвать DOS
Команда INT ожидает, пока пользователь не введет с клавиатуры текст, проверяя при этом, чтобы число введенных символов не превышало максимального значения, указанного в списке параметров (20 в нашем примере). Для указания конца ввода пользователь нажимает клавишу Return. Код этой клавиши (0D) также заносится в поле ввода (NAMEFLD в нашем примере). Если, например, пользователь ввел имя BRQWN(Return), то список параметров будет содержать информацию:
Десятичные и cимвольные: 20 5 B R O W N #
Шестнадцатеричные: 14 05 42 52 4F 57 4E 0D 20 20 …………
Во второй байт списка параметров (ACTLEN в нашем примере) команда заносит длину введенного имени - 05. Код Return находится по адресу NAMEFLD+ 5. Символ # использован здесь для индикации конца данных, так как 0DН не имеет отображаемого символа. Поскольку максимальная длина в 20 символов включает 0DН, то действительная длина вводимого текста может быть только 19 символов.
ПРОГРАММА: ВВОД И ВЫВОД ИМЕН.
ЕХЕ-программа, приведенная на рис.8.2, запрашивает ввод имени, затем отображает в середине экрана введенное имя и включает звуковой сигнал. Программа продолжает запрашивать и отображать имена, пока пользователь не нажмет Return в ответ на очередной запрос. Рассмотрим ситуацию, когда пользователь ввел имя TED SMITH:
1. Разделим длину 09 на 2 и получим 4
2. Вычтем это значение из 40, получим 36
page 60,132
TITLE CTRNAME (EXE) ;Ввод имен и вывод в центр
STACKSG SEGMENT PARA STACK 'Stack'
DW 32 DUP(?)
STACKSG ENDS
DATASG SEGMENT PARA ‘Data’
NAMEPAR LABEL BYTE
MAXNLEN DB 20
NAMELEN DB ?
NAMEFL DB 20 DUP (‘ ‘),’$’
PRIMPT DB ‘Name? ‘,’$’
DATASG ENDS
CODESG SEGMENT PARA ‘Code’
BEGIN PROC FAR
ASSUME CS: CODESG, DS:DATASG , SS:STACKSG, ES:DATASG
PUSH DS
SUB AX, AX
PUCH AX
MOV AX, DATASG
MOV DS, AX
MOV ES, AX
А20LOOP: CALL Q10CLR ;0чистить
MOV DX ,0000
CALL Q20CURS
CALL B10PRMP
CALL D10INPT
CALL Q10CLR
CMP NAMELEN, 00
JE A30
CALL E10CODE
CALL F10CENT
JMP A20LOOP
АЗ0:
RET ; Вывод текста запроса:
B10PRMP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX, PROMPT
INT 21H
RET
B10PRMP ENDP
BEGIN ENDP
D10INPT PROC NEAR
MOV АН, ОАН ;Функция ввода
LEA DX, NAMEPAR
INT 21H
RET
D10INPT ENDP
………….
E10CODE PROC NEAR
MOV BH., 00
MOV SL, .NAMELEN
MOV NAMEFLD[BX],07
MOV NAMEFLD[BX+1], ‘$’
RET
E10CODE ENDP
………………….
F10CENT PROC NEAR
MOV DL, NAMELEN
SHR DL, l ; разделить на 2,
NEG DL ; поменять знак.
ADD DL, 40 ; прибавить 40
MOV DH, 12 ;Центральная строка
CALL Q20CURS ;Установить курсор
MOV AH, 09
LEA DX, NAMEFLD ; Вывести имя на экран
INT 21H
RET
FlOCENT ENDP
;
Очистить экран:
Q10CLR PROC NEAR
MOV AX , 0600H ; Функция прокрутки
MOV BH, 30 ;Цвет (07 для ч/б)
MOV CX. , 0000 ;0т 00,00
MOV DX, 184FH ;До 24,79
INT 10H ; Вызов BIOS
RET
Q10CLR ENDP
; Установка курсора:
Q20CURS PROC NEAR ;DX уже установлен
MOV AH, 02 ; Ф-ция установки
MOV BH, 00 ;Страница # 0 '''
INT 10H ; Вызов BIOS ""-
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
Рис.8.2. Ввод и отображение имен.
Команда SHR в процедуре F10CENT сдвигает длину 09 на один бит вправо, выполняя таким образом деление на 2. Значение бит 00001001 переходит в 00000100. Команда NEG меняет знак + 4 на -4. Команда ADD прибавляет значение 40, получая в регистре DL номер начального столбца - 36. При установке курсора на строку 12 и столбец 36 имя будет выведено на экран в следующем виде:
Строка 12: TED SMITH
I I
Столбец: 36 40
В процедуре E10CODE имеется команда, которая
устанавливает символ звукового сигнала (07) в области ввода
непосредственно после имени:
MOV NAMEFLD[BX],07
Предшествующая команда устанавливает в регистре ВХ значение длины, и команда MQV, комбинируя длину в регистре ВХ и адрес поля NAMEFLD, пересылает код 07. Например, при длине имени 05 код 07 будет помещен по адресу NAMEFLD + 05 (замещая значение кода Return). Последняя команда в процедуре E10CODE устанавливает ограничитель "$" после кода 07. Таким образом, когда процедура F10CENT выводит на экран имя, то генерируется также звуковой сигнал.
Ввод единственного символа Return
При вводе имени, - превышающего по длине максимальное значение, указанное в списке параметров, возникает звуковой сигнал и система ожидает ввода только символа Return. Если вообще не вводить имя, а только нажать клавишу Return, то система примет ее и установит в списке параметров нулевую длину следующим образом:
Список параметров (шестнадцатиричные): 14 00 0D
Для обозначения конца вводимых имен пользователь может просто нажать Return в ответ на очередной запрос на ввод имени. Программа определяет конец ввода по нулевой длине.
Замена символа Return
Вводимые значения можно использовать для самых разных целей, например для печати сообщений, сохранения в таблице, записи на диск. При этом, возможно, появится необходимость замены символа Return (0DH) в области NAMEFLD на символ пробела (20Н). Поле NAMELN содержит действительную длину или относительный адрес кода 0D. Если, например, NAMELEN содержит длину 05, tо адрес кoда 0D равен NAMEFLD + 5. Можно занести эту длину в регистр ВХ для индексной адресации в поле NAMEFLD:
MOV ВН, 00 ; Установить в регистре ВХ
MOV BL,NAMELEN ; значение 0005
MOV NAMEFLD[BX],20H ;3аменить 0D на пробел
Третья команда MOV заносит символ пробела (20Н) по адресу, определенному первым операндом: адрес поля NAMEFLD плюс содержимое регистра ВХ, т.е. NAMEFLD+ 5.
Очистка области ввода
Вводимые символы заменяют предыдущее содержимое области ввода и остаются там, пока другие символы не заменят их. Рассмотрим следующие три успешных ввода имен:
Ввод NAMEPAR ( шестнадцатиричное)
1. BROWN 14 ! 05 ! 42 ! 52 ! 4F ! 57 ! 4E ! 0D ! 20 ! 20 ! 20 !
2. HAMILTON 14 ! 08 ! 48 ! 41 ! 4D ! 49 !4C ! 54 ! 4F ! 4E ! 20 !
3. ADAMS 14 ! 05 ! 41 ! 44 ! 41 ! 4D ! 53 ! 0D ! 4F ! 4E! 20 !
Имя HAMILTON заменяет более короткое имя BROWN. Но, так как имя ADAMS короче имени HAMILTON, то оно заменяет только HAMIL. Код Return заменяет символ Т. Остальные буквы ON остаются после имени ADAMS. Для очистки поля NAMEFLD до ввода очередного имени может служить следующая программа:
MOV СХ,20 ;Установить 20 циклов
MOV SI, 0000 ;Начальная позиция
B30:
MOV NAMEFLD[SI],20H ;Переслать пробел
INC SI ; Следующая позиция поля
LOOP ВЗ0 ;20 циклов
Вместо регистра SI можно использовать DI или ВХ. Более эффективный способ очистки поля, предполагающий пересылку
слова из двух пробелов, требует только десяти циклов. Однако,
ввиду того, что поле NAMEFLD определено как DB (байтовое),
необходимо изменить длину в команде пересылки посредством
операнда WORD, а также воспользоваться операндом PTR
(указатель), как показано ниже:
MOV СХ,10 ;Установить 10 циклов
LEA SI,NAMEFLD ;Начальный адрес
B30:
MOV WORD PTR[SI],2020H ;2 пробела
INC SI ;Получить адрес
INC SI ; следующего слова
LOOP B30 ;10 циклов
Команда MOV по метке ВЗ0 обозначает пересылку слова из двух
пробелов по адресу, находящемуся в регистре SI. В последнем
примере используется команда LEA для инициализации регистра SI
и иная команда MOV по метке ВЗО, тaк как нельзя закодировать,
например, следующую команду:
MOV WORD PTR[NAMEFLD],2020H ; Неправильно
Очистка входной области решает проблему ввода коротких имен, за которыми следуют предыдущие данные. Еще более эффективный способ предполагает очистку только тех байтов, которые расположены после введенного имени.
ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: РАСШИРЕННАЯ ВЕРСИЯ DOS
Рассмотрим теперь расширенные возможности, введенные в DOS 2.0 и реализованные в стиле операционной системы UNIX. Если вы используете раннюю версию DOS, то не сможете выполнить примеры из данного раздела. Расширенные возможности включают файловый номер (file handle), который устанавливается в регистре ВХ, когда требуется выполнить операцию ввода-вывода. Существуют следующие стандартные файловые номера:
0 Ввод, обычно с клавиатуры (CON)
1 Вывод, обычно на экран (CON)
2 Вывод по ошибке, обычно на экран (CON)
3 Ввод-вывод на внешнее устройство (AUX)
4 Вывод на печать (LPT1 или PRN)
Для ввода-вывода используется прерывание DOS INT 21Н, необходимая функция запрашивается через регистр АН: 3FH - для ввода, 40Н - для вывода. В регистр СХ заносится число байтов для ввода-вывода, а в регистр DX - адрес области ввода-вывода.
В результате успешного выполнения операции ввода-вывода очищается флаг переноса (CF) и в регистр АХ устанавливается действительное число байтов, участвующих в операции. При неуспешной операции устанавливается флаг CF, а код ошибки (в данном случае 6) заносится в регистр АХ. Поскольку регистр АХ может содержать как длину данных, так и код ошибки, то единственный способ определить наличие ошибки - проверить флаг CF, хотя ошибки чтения с клавиатуры и вывода на экран - явления крайне редкие. Аналогичным образом используются файловые номера для дисковых файлов, здесь ошибки ввода-вывода встречаются чаще.
Можно использовать эти функции для перенаправления ввода- вывода на другие устройства, однако эта особенность здесь не рассматривается.
ВЫВОД НА ЭКРАН В РАСШИРЕННОЙ ВЕРСИИ DOS
Следующие команды иллюстрируют операцию вывода на экран в расширенной версии DOS:
DISAREA DB 20DUP(‘ ‘) ;0бласть данных
…………
MOV AH, 40H ;3апрос на вывод
MOV ВХ ,01 ;Выводное устройство
MOV CX,20 ; Макс, число байтов
LEA DX,DISAREA ;Адрес области данных
INT 21H ; Вызов DOS
Команда LEA загружает в регистр DX адрес DISAREA для возможности DOS локализовать информацию, предназначенную для вывода. В результате успешной операции флаг переноса очищается (это можно проверить), а в регистре АХ устанавливается число выведенных символов. Ошибка в данной операции может произойти, если установлен неправильный файловый номер. В этом случае будет установлен флаг CF и код ошибки (в данном случае 6) в регистре АХ. Поскольку регистр АХ может содержать или длину, или код ошибки, то единственный способ определить состояние ошибки - проверить флаг CF. ,
Упражнение: Вывод на экран
Воспользуемся отладчиком DEBUG для проверки внутренних эффектов прерывания. Загрузите DEBUG и после вывода на экран приглашения введите
А 100 для ввода ассемблерных команд (не машинных команд) по адресу 100. Не забудьте, что DEBUG предполагает, что все числа вводятся в шестнадцатиричном формате:
100 MOV AH,40
102 MOV BX,01
105 MOV CX,xx (введите длину вашего имени)
108 MOV DX,10E
10B INT 21
10D RET
10E DB ‘Ваше имя’
Программа устанавливает в регистре АН запрос на вывод и устанавливает значение 10Е в регистре DX - адрес DB, содержащий ваше имя в конце программы.
Когда вы наберете все команды, нажмите еще раз клавишу Return. С помощью команды U (U 100,10D) дисассемблируйте программу для проверки. Затем используйте команды R и Т для трассировки выполнения. При выполнении команды INT 21Н отладчик перейдет в BIOS, поэтому при достижении адреса 10В введите команду GO (G 10D) для перехода к команде RET. Ваше имя будет выведено на экран. С помощью команды Q вернитесь в DOS.
ВВОД С КЛАВИАТУРЫ В РАСШИРЕННОЙ ВЕРСИИ DOS
Ниже приведены команды, иллюстрирующие использование
функции ввода с клавиатуры в расширенной версии DOS:
INAREA DB 20 DUP (‘ ‘) ;0бласть ввода
MOV AH,3H ;3апрос на ввод
MOV BX, 00 ;Номер для клавиатуры
MOV CX,20 ;Макс. байт для ввода
LEA DX,INAREA ;Адрес области ввода
INT 21H ;Вызов DOS
Команда LEA загружает относительный адрес INAREA в регистр DX. Команда INT ожидает, пока пользователь не введет символы с клавиатуры, но не проверяет, превышает ли число введенных символов максимальное значение в регистре СХ (20 в приведенном примере). Нажатие клавиши Return (код 0D) указывает на завершение ввода. Например, после ввода текста "PC Users Group" INAREA будет содержать:
PC Users Group, 0DН, 0АН
После введенного текста непосредственно следует символ возврата каретки (0D), который был введен, и символ конца строки (0А), который не был введен. Вследствие данной особенности максимальное число символов и размер области ввода должны предусматривать место для двух дополнительных символов. Если будет введено символов меньше максимального значения, то область памяти за введенными символами сохранит прежнее значение.
В результате успешной операции очищается флаг CF (что можно проверить) и в регистре АХ устанавливается число байтов, введенных с клавиатуры. В предыдущем примере это число будет равно 14 плюс 2 для символов возврата каретки и перевода строки, т.е. 16. Соответствующим образом программа может определить действительное число введенных символов. Хотя данное свойство весьма тривиально для ответов типа YES или NO, оно может быть полезно для ввода строк с переменной длиной, таких, например, как имена.
Ошибка ввода может возникнуть, если определен неправильный номер файла. В этом случае устанавливается флаг CF и в регистр АХ помещается код ошибки (6 в данном случае). Так как регистр АХ .может содержать или длину введенных данных, или код ошибки, то единственный способ определения наличия ошибки - проверка флага CF.
Если вводить текст, который превышает максимальную длину, установленную в регистре СХ, то будут приниматься все символы. Рассмотрим ситуацию, когда регистр СХ содержит значение 08, а пользователь введет символы "PC Exchange". В результате первые восемь символов "PC Excha" попадут в область ввода без кодов возврата каретки и перевода строки, В регистре АХ будет установлена длина 08. Следующая команда INT будет принимать данные не с клавиатуры, а из собственного внутреннего буфера, поскольку там еще остались предыдущие данные. Таким образом, в область ввода будут приняты символы "nge", символ возврата каретки и символ перевода строки, в регистре АХ будет установлено значение 05. Обе операции ввода являются вполне нормальными и флаг CF будет очищен: