Преобразования ввода-вывода

При программировании операций ввода-вывода на ассемблере приходится вручную осуществлять преобразования чисел из символьного представления во внутренний формат (двоичный с фиксированной точкой, отрицательные числа записаны в дополнительном коде) и обратно.

Для облегчения преобразования во внутренний формат целесообразно оговорить возможные варианты ввода чисел в символьном виде. При этом также используется то, что при добавлении цифры к числу справа число меняется следующим образом: <число>:=<число>*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