Сист. прогр. Ч1 (1085770), страница 12
Текст из файла (страница 12)
INT 10Н
RET
C10SET ENDP
Вывод на экран ASCII символов:
D10DISP PROC
MOV CХ , 256 ;256 итераций
D20: LEA DX, CTR ; Адрес счетчика D20
MOV АН., 09 ; опция вывода символа
INT 21Н.
INC CTR ;Уввличить ечетчик
LOOP D20 ;Уменьшить CХ, если не ноль - цикл
RET ; Вернуться
D10DISP ENDP
CODESG ENDS
END BEGIN
Рис.8.1. Вывод на экран набора символов ASCII-кода
Так как символ доллара не выводится на экран и, кроме того, коды от 08Н до 0DН являются специальными управляющими символами, то это приводит к перемещению курсора и другим управляющим воздействиям. Первая выведенная строка начинается с пробельного символа (00Н), двух "радостных физиономий" (01Н и 02Н) и трех карточных символов (0ЗН, 04Н и 05Н). Код 07Н выдает звуковой сигнал. Код 06Н должен отобразиться карточным символом "пики", но управляющие символы от 08Н до 00Н сотрут его. Код 00Н является "возвратом каретки" и приводит к переходу на новую (следующую) строку. Код 0ЕН представляется в виде музыкальной ноты. Символы после 7FH являются графическими.
Можно изменить программу для обхода управляющих символов. Ниже приведен пример фрагмента программы, позволяющий обойти все символы между 08Н и 0DН. Вы можете поэкспериментировать, обходя только, скажем, 08Н "возврат на символ" и 0DН "возврат каретки":
СMР CTR, 08H ;Меныие чем 08?
JB D30 ; Да - принять
СМР CTR,0DH ;Меньше/равно 0D?
JBЕ D40 ; Да - обойти
D30:
MOV AH, 40H ;Вывод символов < 08
……………..
INT 21H
D40:
INC CTR
ВВОД ДАННЫХ С КЛАВИАТУРЫ: БАЗОВАЯ ВЕРСИЯ DOS
Процедура ввода данных с клавиатуры проще, чем вывод на экран. Для ввода, использующего базовую DOS, область ввода требует наличия списка параметров, содержащего спецификацию полей, которые необходимы при выполнении команды INT. Во-первых, должна быть определена максимальная длина вводимого текста. Это необходимо для предупреждения пользователя звуковым сигналом, если набран слишком длинный текст; символы, превышающие максимальную длину, не принимаются. Во-вторых, в списке параметров должно быть определенное поле, куда команда возвращает действительную длину введенного текста в байтах.
Ниже приведен пример, в котором определен список, параметров для области ввода. Здесь LABEL представляет собой директиву с атрибутом BYTE. Первый байт содержит максимальную длину вводимых данных. Так как это однобайтовое поле, то возможное максимальное значение его - шестнадцатеричное FF или 255. Второй байт необходим DOS для занесения в него действительного числа введенных символов. Третьим байтом начинается поле, которое будет содержать введенные символы.
NAMEPAR LABEL BYTE ;Список параметров:
MAXLEN DB 20 ; Максимальная длина
ACTLEM DB ? ; Реальная длина
NAMEFLD DB 20 DUP (‘ ‘) ; Введенные символы
Так как в списке параметров директива LABEL не занимает места, то NAMEPAR и MAXLEN указывают на один и тот же адрес памяти. B трансляторе MASM для определения списка параметров в виде структуры может использоваться также директива STRUC.
Для запроса на ввод необходимо поместить в регистр АН номер функции - 10 (0AH), загрузить адрес списка параметров (NAMEPAR в нашем примере) в регистр DХ и выполнить INT 21Н:
MOV АН,0AH ;3апрос функции ввода
LEA DX,NAMEPAR ;3агрузить адреса списка параметров
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бласть данных