data segment ; сегмент данных
buffer db 8, 7 dup (0) ; буфер для строки при вводе-выводе числа
arr1 dw 5 dup (0) ; первый массив
arr2 dw 5 dup (0) ; второй массив
arrS dw 5 dup (0) ; массив сумм
arrD dw 5 dup (0) ; массив пвзностей
arrP dw 5 dup (0) ; массив произведений
arrQ dw 5 dup (0) ; массив частных
count db 5 ; длина массивов
msg_prompt db 'Enter two integer [5] arrays (delimited by new-lines):', 0dh, 0ah, '$'
msg_input_err db 0dh, 0ah, 'Number is incorrect or too large. Please enter again.', 0dh, 0ah, '$'
msg_info db 0dh, 0ah, 'Here is sums, differences, products and quotients:', 0dh, 0ah, '$'
msg_zero_div db 0dh, 0ah, 'One of the entered numbers to divide is 0. Exitting.', 0dh, 0ah, '$'
crlf db 0dh, 0ah, '$'
data ends
code segment ; сегмент кода
assume CS: code, DS: data
; Ввести число с клавиатуры. Результат в ax (-1, если не удалось ввести число)
enter_number proc
; сохраним значения используемых далее регистров
push cx
push dx
push si
; получаем строку из ввода
mov ah, 0ah ; функция DOS ah ввода с клавиатуры
lea dx, buffer ; загрузим адрес буфера в dx
int 21h ; вызов DOS
; первый байт буфера показывает его длину; он заполнен ещё при инициализации памяти там наверху
; второй символ буфера показывает кол-во введённых символов
lea si, buffer ; загрузим адрес буфера в si для работы со строкой
cld ; обнулим флаг направления, т. е. идём слева направо, увеличивая адрес
inc si ; пропустим первый байт (см. выше)
lodsb ; в al теперь длина строки, si указывает на первый символ введённой строки
xor dx, dx ; обнулим dx, здесь будет лежать результат
xor ch, ch ; обнулим ch, чтобы cx == cl
mov cl, al ; поместим длину строки в cl
; проверяем на пустую строку
test cl, cl ; проверим cl на ненулевость
jz fail ; если 0, строка пустая. Число ввести не удалось
char:
lodsb ; получаем следующий символ в al
cmp al, '0' ; сравним с '0'
jb fail ; al < '0' - нечисловой символ, неудача при вводе
cmp al, '9' ; сравним с '9'
ja fail ; al > '9' - нечисловой символ, неудача при вводе
sub al, '0' ; получим из символа цифру
; обновляем результат
; умножаем его на 10
mov bx, dx
shl dx, 2 ; dx' == 4 dx
add dx, bx ; dx' == 5 dx
shl dx, 1 ; dx' == 10 dx
xor ah, ah ; обнулим ah, чтобы ax == al
add dx, ax ; прибавим к dx результату цифру;
; теперь результат содержит число на одну цифру больше
loop char ; повторим для следующего символа (cx уменьшился на 1)
; здесь cx == 0, вся строка получена и число готово
call newline
mov ax, dx ; результат помещаем в ax
jmp return
; в случае ошибки
fail:
mov ax, -1 ; ошибка, не удалось ввести число
return:
; восстановим значения регистров
pop si
pop dx
pop cx
ret
enter_number endp
; Ввести массив с клавиатуры. Параметры: адрес начала массива в ax
enter_array proc
; сохраним значения из используемых регистров
push bx
push cx
push di
mov bx, ax ; загрузим адрес массива из ax в bx
xor ch, ch
mov cl, count ; будем повторять цикл count раз
xor di, di ; получем индекс первого элемента 0
elem:
jmp input_try
reinput:
mov ax, offset msg_input_err
call print_str ; выведем сообщение об ошибке ввода
jmp input_try ; повторим ввод
input_try:
call enter_number ; введём число
cmp ax, -1 ; сравним результат с -1
je reinput ; если ax == -1, была ошибка при вводе числа. Повторим его
; число введено
mov [bx]+di, ax ; поместим число в элемент массива с индексом di
add di, 2
loop elem ; если cx == 0, то также di == -1, все элементы массива введены
; иначе, обработаем следующий элемент
; восстановим значения в регистрах
pop di
pop cx
pop bx
ret
enter_array endp
; Вывести строку по адресу из ax
print_str proc
push dx ; сохраним то, что было в dx, т. к. он здесь используются
mov dx, ax ; загрузим адрес строки из ax
mov ah, 09h ; функция DOS 9h вывода на экран
int 21h ; вызов DOS
pop dx ; восстановим значение в dx
ret
print_str endp
; Вычислить суммы, разности и остальные чисел массивов
calculate proc
; Сохраним значения из регистров
push ax
push bx
push cx
push dx
push di
; Собственно, цикл с расчётами
xor ch, ch
mov cl, count ; будем повторять цикл count раз
xor di, di ; получем индекс первого элемента 0
elem_c:
mov ax, arr1+[di] ; из первого массива число в ax
mov dx, arr2+[di] ; из второго массива число в dx
; сразу проверим второе число на ноль, чтобы зря не +-*, если нельзя делить
test dx, dx ; проверим на ноль
jz fail_c ; 0 - ошибка
; можно спокойно считать
mov bx, ax ; чтобы не затереть ax: число нужно и для других операций
add bx, dx ; складываем
mov arrS+[di], bx ; сумму в массив сумм
mov bx, ax
sub bx, dx ; вычитаем
mov arrD+[di], bx ; разность в свой массив
mov bx, ax
mul dl ; умножаем
mov arrP+[di], ax ; произведение в свой массив
mov ax, bx ; возвращаем обратно изменённый умножением результат
div dl ; делим; остаток в ah
xor ah, ah ; обнулим остаток, чтобы ax == al
mov arrQ+[di], ax ; частное в массив частных
add di, 2
loop elem_C ; если cx == 0, то также di == -1, все элементы перебраны
; иначе, обработаем следующий элемент
jmp return_c
; ошибка
fail_c:
mov ax, offset msg_zero_div
call print_str ; выведем сообщение об ошибке
return_c:
; Восстановим регистры
pop di
pop dx
pop cx
pop bx
pop ax
ret
calculate endp
; Перевести строку
newline proc
push ax
mov ax, offset crlf
call print_str
pop ax
ret
newline endp
; Вывести число из ax на экран
print_number proc
; Сохраним ...
push ax
push bx
push cx
push dx
; Выведем число
test ax, ax ; проверим, не ноль ли число
jz it_is_0 ; выведем тогда '0'
mov cx, 10
digit:
xor dx, dx ; при обнулении dx dx:ax == ax
idiv cx ; найдём очередную цифру в dx и остаток числа в ax
mov bx, ax
mov ah, 06h ; функция DOS 6h вывода символа
xor dh, dh ; чтобы dx == dl
add dl, '0' ; получаем из цифры символ для вывода
int 21h ; вызов DOS
mov ax, bx
test ax, ax ; не ноль ли число
jnz digit ; не ноль: надо печатать остальные цифры
; больше нечего выводить
jmp return_p
it_is_0:
mov ah, 06h ; функция DOS 6h вывода символа
mov dl, '0' ; символ для вывода
int 21h ; вызов DOS
return_p:
; Восстановим ...
pop dx
pop cx
pop bx
pop ax
ret
print_number endp
; Вывести массив на экран. Адрес массива берётся из ax
print_array proc
; Сохраним ...
push ax
push bx
push cx
push dx
push di
; Вывод элементов массивов
mov bx, ax
xor ch, ch
mov cl, count ; будем повторять цикл count раз
xor di, di ; получем индекс первого элемента 0
elem_p:
mov ax, [bx]+di ; текущий элемент в ax
call print_number ; и напечатаем это число
mov ah, 06h ; функция DOS 6h вывода символа
mov dl, ' ' ; пробел между элементами
int 21h ; вызов DOS
add di, 2
loop elem_p ; если cx == 0, то также di == -1, все элементы перебраны
call newline ; перейдём на новую строку
; Восстановим ...
pop di
pop dx
pop cx
pop bx
pop ax
ret
print_array endp
program:
mov ax, data ; адрес сегмента данных сначала загрузим в ax,
mov ds, ax ; а затем перенесем из ax в ds
; напишем приглашение ввода, введём массивы
mov ax, offset msg_prompt ; поместим адрес строки-подсказки для вывода в ax
call print_str ; выведем эту строку на экран
mov ax, offset arr1 ; поместим в ax адрес начала 1-го массива
call enter_array ; введём 1-й массив
mov ax, offset arr2 ; поместим в ax адрес начала 2-го массива
call enter_array ; введём 2-й массив
; посчитаем
call calculate
; выведем массивы
mov ax, offset msg_info ; поместим адрес строки-описания для вывода в ax
call print_str ; выведем эту строку на экран
mov ax, offset arrS ; в ax адрес массива сумм
call print_array ; напечатаем его
mov ax, offset arrD ; в ax адрес массива разностей
call print_array ; напечатаем его
mov ax, offset arrP ; в ax адрес массива произведений
call print_array ; напечатаем его
mov ax, offset arrQ ; в ax адрес массива частных
call print_array ; напечатаем его
; завершим программу
mov ah, 4ch ; функция 4ch завершения программы
mov al, 0 ; код 0 успешного завершения
int 21h ; вызов DOS
code ends
s segment stack ; сегмент стека
db 256 dup (0) ; резервируем под него 256 байт
s ends
end program