ВЫВОД НА ЭКРАН СРЕДСТВАМИ DOS.
Вывод на экран средствами DOS осуществляет 09 функция
INT 21H DOS
. Номер функции указывается в регистре AH.
Адрес выводимой строки в DS:DX. В процессе выполнения операции
конец сообщения определяется по oграничителю ($).
PRMP DB ‘Строка','$' |
|
. |
|
. |
|
MOV AH,09 |
; Запрос вывода на экран |
LEA DX,PRMP |
; Загрузка адреса сообщ. |
INT 21H |
; Вызов DOS |
Знак ограничителя '$' можно кодировать непосредственно после cимвольной
строки (как показано в примере), внутри строки: 'Имя покупателя?$', или
в следующем операторе DB '$'. Используя данную операцию, нельзя вывести
на экран символ доллара "$". Кроме того, если знак доллара
будет отсутствовать в конце строки, то на экран будут выводиться все последующие
символы, пока знак "$" не встретиться в памяти.
Команда LEA загружает адрес области PRMP в регистр DX для передачи
в DOS адреса выводимой информации. Адрес поля PRMP, загружаемый в
DX по команде LEA, является oтносительным, поэтому для вычисления
абсолютного адреса данных DOS складывает значения регистров DS и DX (DS:DX).
ВВОД ДАННЫХ С КЛАВИАТУРЫ.
Для ввода с клавиатуры используется функция 0AH INT 21H
. Она требует наличия
cписка параметров, содержащего поля, которые необходимы при выполнении команды INT.
- должна быть определена максимальная длина вводимого текста;
-
должно быть определенное поле, куда команда возвращает действительную длину
введенного текста в байтах.
-
должно быть зарезервировано в памяти место для вводимой строки
Ниже приведен пример, в котором определен список параметров для области ввода.
LABEL представляет собой директиву с атрибутом BYTE. Первый байт содержит
максимальную длину вводимых данных. Второй байт необходим DOS для занесения
в него действительного числа введенных символов. Третьим байтом начинается поле,
которое будет содержать введенные символы.
NAMEPAR LABEL BYTE |
; Список параметров: |
MAXLEN DB 20 |
; Максимальная длина |
ACTLEN DB ? |
; Реальная длина |
NAMEFLD DB 20 DUP (' ') |
; Введенные символы |
Так как в списке параметров директива LABEL не занимает места, то
NAMEPAR и MAXLEN указывают на один и тот же aдрес памяти. Для
запроса на ввод необходимо поместить в регистр AH номер функции -10
(шест. 0AH), загрузить адрес списка параметров (NAMEPAR в
нашем примере) в регистр DX и выполнить INT 21H
:
MOV AH,0AH |
; Запрос функции ввода |
LEA DX,NAMEPAR |
; Aдреса списка параметров |
INT 21H |
; Вызвать DOS |
Команда INT ожидает пока пользователь не введет с клавиатуры текст,
проверяя при этом, чтобы число введенных cимволов не превышало
максимального значения, указанного в списке параметров (20 в нашем
случае). Для указания конца ввода пользователь нажимает клавишу Return.
Код этой клавиши (шест. 0D) также заносится в поле ввода (NAMEFLD
в нашем примере). Если, например, пользователь ввел имя BROWN (Return), то cписок
параметров будет содержать информацию:
дес. : |
20 |
5 |
B |
R |
O |
W |
N |
# |
|
|
|
|
... |
шест. : |
14 |
05 |
42 |
52 |
4F |
57 |
4E |
0D |
20 |
20 |
20 |
20 |
... |
Во второй байт списка параметров (ACTLEN в нашем примере) команда
заносит длину введенного имени - 05. Код Return находится по адресу
NAMEFLD +5. Символ # использован здесь для индикации конца данных, так как
шест. 0D не имеет отображаемого символа. Поскольку максимальная длина в 20
символов включает шест.0D, то действительная длина вводимого текста может
быть только 19 символов.
ПРИМЕР: ВВОД И ВЫВОД ИМЕН (СТРОК).
EXE-программа запрашивает ввод имени (строки), затем отображает
в середине экрана введенное имя (строку) и включает звуковой сигнал.
Программа продолжает запрашивать и отображать имена, пока пользователь не
нажмет Return в ответ на очередной запрос.
Рассмотрим ситуацию, когда пользователь ввел имя (строку) TED SMITH:
      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уется также звуковой сигнал.
; --------------------------------------------------------
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(' '),'$' |
; имя и ограничитель для вывода на экран |
PROMPT 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
PASH 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 |
|
MOV AH,09 |
; Функция вывода на экран |
LEA DX,PROMPT
INT 21H
RET
B10PRMP ENDP |
|
Ввод имени с клавиатуры:
D10INPT PROC NEAR |
|
MOV AH,0AH |
; Функция ввода |
LEA DX,NAMEPAR
INT 21H
RET
D10INPT ENDP |
|
Установка звукового сигнала и ограничителя '$':
E10CODE PROC NEAR |
|
MOV BH,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 AH,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 |
|
Преобразование строки в число и числа в строку.
Данные, вводимые с клавиатуры, имеют ASCII-формат, например,
буквы SAM имеют в памяти шестнадцатеричное представление 53414D,
цифры 1234 - шест.31323334. Во многих случаях формат алфавитных данных,
например, имя человека или описание статьи, не меняется в программе. Но для
выполнения арифметических операций над числовыми значениями, такими
как шест.31323334, требуется специальная обработка.
ПРЕОБРАЗОВАНИЕ ASCII-ФОРМАТА (строки) В ДВОИЧНЫЙ ФОРМАТ (число).
Для выполнения арифметических операций часто требуется преобразование
их в двоичный формат.
Процедура преобразования заключается в следующем:
-
Начинают с самого правого байта числа в ASCII-формате
и обрабатывают справа налево.
-
Удаляют тройки из левых шестнадцатеричных цифр каждого ASCII-байта.
-
Умножают ASCII-цифры на 1, 10, 100 (шест.1, A, 64) и
т.д.
-
Cкладывают результаты
Для примера рассмотрим преобразование числа 1234 из
ASCII-формата в двоичный формат:
|
Десятичное |
Шестнадцатиричное |
4 х 1 = |
4 |
4 |
3 х 10 = |
30 |
1Е |
2 х 100 = |
200 |
С8 |
1 х 1000 |
1000 |
04D2 |
Результат: |
|
04D2 |
Действительно шест.04D2 соответствует десятичному 1234.
Пример преобразования:
CODESG SEGMENT
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN |
|
; --------------------------------------------------------------------- |
|
ASCVAL DB '1234' |
; Элементы данных |
BINVAL DB 0
ASCLEN DB 4
MULT10 DB 1 |
|
; --------------------------------------------------------------------- |
|
MAIN PROC NEAR |
; Основная процедура: |
CALL B10ASBI |
; Вызвать преобразование ASCII |
CALL C10BIAS |
; Вызвать преобразование двоичное |
RET MAIN ENDP |
|
; ---------------------------------------------------------------------
; Преобразование ASCII в двоичное:
; --------------------------------------------------------------------- |
|
B10ASBI PROC
MOV CX,10 |
; Фактор умножения |
LEA SI,ASCVAL-1 |
; Адрес ASCVAL |
MOV BX,ASCLEN |
; Длина ASCVAL |
В20:
MOV AL,[SI+BX] |
; Выбрать ASCII-символ |
AND AX,000FH |
; Очистить зону тройки |
MUL MULT10 |
; Умножить на фактор 10 |
ADD BINVAL,AX |
; Прибавить к двоичному |
MOV AX,MULT10 |
; Вычислить следующий |
MUL CX |
; Фактор умножения |
MOV MULT10,AX
DEC BX |
; Поспедн. ASCII-симвоп? |
JNZ B20 |
; Нет - продолжить |
RET
B10ASBI ENDP |
|
В процедуре B10ASBI выполняется преобразование ASCII-числа
1234 в двоичный формат. В примере предполагается, что длина
ASCII-числа равна 4 и она записана в поле ASCLEN.
Для инициализации адрес ASCII-поля ASCVAL-1 заносится в регистр
SI, а длина - в регистр BX.
Команда по метке B20 пересылает ASCII-байт в регистр AL:
MOV AL,[SI+BX]
Здесь используется адрес ASCVAL-1 плюс содержимое регистра BX (4),
т.е. получается адрес ASCVAL+3 (самый правый байт поля ASCVAL). В каждом
цикле содержимое регистра BX уменьшается на 1, что приводит к обращению к
следующему слева байту. Для данной адресации можно использовать регистр
BX, но не CX, и, следовательно, нельзя применять команду LOOP. В каждом
цикле происходит также умножение поля MULT10 на 10, что дает в результате
множители 1,10,100 и т.д. Такой прием применен для большей ясности,
однако, для большей производительности множитель можно хранить в регистре
SI или DI.
ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО ФОРМАТА В ASCII-ФОРМАТ.
Для того, чтобы напечатать или отобразить на экране pезультат выполнения арифметических
операций, необходимо преобразовать его в ASCII-формат. Данная операция включает
в себя процесс обратный предыдущему. Вместо умножения используется деление
двоичного числа на 10 (шест.0A) пока результат не будет меньше 10.
Остатки, которые лежат в границах от 0 до 9, образуют число в ASCII формате.
В качестве примера рассмотрим преобразование шест.4D2 обратно в десятичный формат:
|
Частное |
Остаток |
4D2 : A = |
7B |
4 |
7B : A = |
C |
3 |
C : A = |
1 |
2 |
Так как последнее частное 1 меньше, чем шест.A, то операция
завершена. Остатки вместе с последним частным образуют результат в
ASCII-формате, записываемый справа налево 1234. Все остатки и
последнее частное должны записываться в память с тройками, т.е. 31323334.
Пример преобразования:
C10BIAS PROC
MOV CX,0010 |
; Фактор деления |
LEA SI,ASCVAL+3 |
; Адрес ASCVAL |
MOV AX,BINVAL |
; Загрузить дв. число |
С20:
CMP AХ,0010 |
; Значение меньше 10? |
JB С30 |
; Да - выйти |
XOR DX,DX |
; Очистить часть частного |
DIV CX |
; Разделить на 10 |
OR DL,30H
MOV [SI],DL |
; Записать ASCII-символ |
DEC SI
JMP С20
C30:
OR AL,30H |
; 3аписать поcл. частное |
MOV [SI],AL |
; как ASCII-символ |
RET
C10BIAS ENDP
CODESG ENDS
END BEGIN |
|
Процедура C10BIAS преобразует шест.4D2 (результат вычисления
в процедуре B10ASBI) в ASCII-число 1234.
Лабораторная работа №3