О п е р а ц и и

в в о д а

/

в ы в о д а

ВЫВОД НА ЭКРАН СРЕДСТВАМИ 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
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

Программирование на Машинно-Ориентированных Языках.
Преподаватель: Коробов С.А.