Преобразования ввода-вывода
При программировании операций ввода-вывода на ассемблере приходится вручную осуществлять преобразования чисел из символьного представления во внутренний формат (двоичный с фиксированной точкой, отрицательные числа записаны в дополнительном коде) и обратно.
Для облегчения преобразования во внутренний формат целесообразно оговорить возможные варианты ввода чисел в символьном виде. При этом также используется то, что при добавлении цифры к числу справа число меняется следующим образом: <число>:=<число>*10+<цифра>.
Обратное преобразование из внутреннего формата в символьный для вывода результатов обычно использует стандартное правило перевода числа из двоичной системы счисления в десятичную: деление на 10 с выделением остатков. В этом случае десятичные цифры получаются в обратном порядке.
Если среди вводимых или выводимых чисел могут быть отрицательные, то необходимо предусмотреть специальную проверку и преобразовывать отрицательные числа в дополнительный код при вводе и в прямой при выводе.
Пример.
Написать процедуры ввода массива из n чисел размером слово и вывода того же массива. Числа должны вводиться каждое со своей строки, положительные числа должны вводиться без знака c первой позиции, отрицательные - со знаком в первой позиции. Вывод всех чисел должен осуществляться в одну строку через пробелы. Перед отрицательными числами необходимо выводить знак "-".
Составить тестирующую программу.
Title inout
Code segment
assume cs:code, ds:code
N equ 5; определяем константу для транслятора
A dw N dup (?); резервируем место под массив
main proc far; основная процедура
push ds; обеспечиваем возврат управления в MS DOS
Mov ax, 0
Push ax
mov ax, code; загружаем сегментный адрес
mov ds, ax; сегмента данных в DS
call input ; вызываем процедуру ввода
call output ; вызываем процедуру вывода
ret; возврат управления DOS
main endp ; конец основной процедуры
input proc near; процедура ввода
mov cx, N ;загругка размерности массива
mov di, 0 ; загрузка смещения массива
cycl1_in: push cx; сохраняем счетчик внешнего цикла
lea dx, mes_in ; загружаем адрес запроса на ввод
mov ah, 9 ; загружаем номер функции DOS
int 21h; вызываем функцию вывода строки
lea dx, BUf_in; загружаем адрес строки ввода
mov ah, 0ah ; загружаем номер функции DOS
int 21h; вызываем функцию ввода строки
mov byte ptr NEG_IN, 0; признак - "число положительно"
cld; флаг направления - "возрастание адресов"
mov cl, BUF_IN+1; загружаем длину введенной строки
mov ch, 0; счетчик - в CX
lea si, BUF_IN+2 ; загружаем адрес введенной строки
cmp byte ptr [si], '-' ; число отрицательно ?
jne short unsigned ; если нет, то переход
mov byte ptr NEG_IN, 1; признак - "число отрицательно"
inc si; пропускаем знак
dec cx; уменьшаем счетчик
unsigned: mov bx, 0; исходное значение числа
cycl2_in: mov ax, 10; заносим константу 10
mul bx; умношаем текущее значение числа на 10
mov bx, ax; текущее значение числа в BX
lodsb ; загрузили очередную цифру
sub al, 30h; преобразовали из символа в двоичное число
cbw; преобразовали в слово
add bx, ax; добавили к текущему значению числа
loop cycl2_in; выполняем для всех введенных цифр
cmp NEG_IN, 0; число положительно ?
je short done; если да, то переход
neg bx ; преобразуем в отричательное число
done: mov A[di], bx; записываем результат в массив
add di, 2 ; корректируем смещение
pop cx ;восстанавливаем счетчик внешнего цикла
loop cycl1_in ;выполняем для всех чисел
ret; возвращаем управление основной процедуре
BUF_IN db 10,10 dup (0) ; буфер ввода (до 10 символов)
NEG_IN db 0; признак "положительно/отрицательно"
mes_in db 13,10,'Введите число: $'; запрос на ввод
Input endp
output proc near; процедура вывода
lea dx, mes_out ; загружаем адрес заголовка вывода
mov ah, 9 ; загружаем номер функции DOS
int 21h ;вызываем функцию вывода строки
mov cx, N; загружаем количество чисел
mov si, 0 ; устанавливаем смещение в массиве
mov di, 7 ; устанавливаем смещение для строки вывода
cycl1_out: mov byte ptr NEGOUT, 0; признак - "число положительно"
mov bx, 10 ; загрузили константу 10
mov ax, A[si]; взяли очередное число из массива
cmp ax, 0 ; сравнили с нулем
jge short again; если положительно, то переход
mov byte ptr NEG_OUT, 1 ; признак "число отрицательно"
neg ax; преобразовали в положительное
again: cwd; преобразовали в двойное слово
div bx ; разделили на 10
add dl, 30h ; преобразовали остаток в символ
mov BUF_OUT[di], dl ; записали в поле вывода
dec di ; уменьшили смещение в поле вывода на 1
cmp ax, 0 ; сравнили результат деления с нулем
jne again ;если не равно, то получаем следующую цифру
cmp byte ptr NEG_OUT, 1 ;число отрицательно
jne short positive ; если нет, то переход
mov BUF_OUT[di], '-'; если да, то вставили знак "-"
positive: mov ax, N+2; считаем смещение следующего числа
sub ax, cx ; в поле вывода
mov bx, 7 ;
mul bx;
mov di, ax ;записали смещение в DI
add si, 2 ; перешли к следующему числу массива
loop cycl1_out; выполняем для всех чисел массива
lea dx, BUF_OUT ; загружаем адрес строки вывода
mov ah, 9; загружаем номер функции DOS
int 21h ; вызываем функцию вывода строки
ret; возврат в основную процедуру
NEG_OUT db 0; признак "положительно/отрицательно"
BUF_OUT db 13,10, N*7 dup (' '),'$'; поле вывода
mes_out db 13,10,'Результат: $' ; заголовок вывода
Output endp
Code ends
End main