Вычисление выражения по формуле с ветвлением - Assembler (223291)
Формулировка задачи:
Вычислить заданные условные выражения,исходные данные должны вводится с клавиатуры с проверкой на область допустимые значений. 1ый курс ассемблера, ничего в нем не понимаю, Самостоятельные попытки разобраться привели к полному краху
Решение задачи: «Вычисление выражения по формуле с ветвлением»
textual
Листинг программы
LOCALS .model small .stack 100h .data PromptA db 'Введите число (-32768..+32767): A = ', '$' PromptB db 'Введите число (-32768..+32767): B = ', '$' msgErr db 'Divide by zero', 0Dh, 0Ah, '$' msgFmt db 'Format error', 0Dh, 0Ah, '$' msgShowX db 'X = ', '$' A dw ? B dw ? X dw ? KeyBuf db 7, 0, 7 dup(0) ;max,len,string,CR(0dh) CR_LF db 0Dh, 0Ah, '$' .code main proc mov ax, @data mov ds, ax ;----------------------------- ;ввод A ;----------------------------- @@InputA: ;вывод приглашения и ввод строки mov ah, 09h lea dx, PromptA int 21h mov ah, 0Ah mov dx, offset KeyBuf int 21h ;перевод строки (на новую строку) lea dx, CR_LF mov ah,09h int 21h ; преобразование строки в число lea si, KeyBuf+1 lea di, A call Str2Num ; проверка на ошибку jnc @@InputB ; если есть ошибка ввода - напечатать сообщение об ошибке lea dx, msgFmt mov ah,09h int 21h jmp @@InputA ;----------------------------- ;ввод B ;----------------------------- @@InputB: ;вывод приглашения и ввод строки mov ah, 09h lea dx, PromptB int 21h mov ah, 0Ah mov dx, offset KeyBuf int 21h ;перевод строки (на новую строку) lea dx, CR_LF mov ah,09h int 21h ; преобразование строки в число lea si, KeyBuf+1 lea di, B call Str2Num ; проверка на ошибку jnc @@CalcX ; если есть ошибка ввода - напечатать сообщение об ошибке lea dx, msgFmt mov ah,09h int 21h jmp @@InputB ;----------------------------- ;вычисление X по формуле ;----------------------------- @@CalcX: mov ax, A cmp ax, B je @@Equal jg @@Greater ;вычисления при a<b @@Lesser: ;проверка ОДЗ cmp B, 0 jnz @@Lesser2 mov ah, 09h ;вывод сообщения об ошибке lea dx, msgErr ; параметры не в ОДЗ int 21h jmp @@InputA ;повторный ввод параметров @@Lesser2: mov ax, A ;(dx:ax):=A cwd idiv B ;ax:=A/B add ax, 10 ;ax:=(A/B)+10 mov X, ax ;сохранить результат в X jmp @@Exit ;вычисления при a=b @@Equal: mov ax, -51 mov X, ax ;X:=-51 jmp @@Exit ;вычисления при a>b @@Greater: ;проверка ОДЗ cmp A, 0 jnz @@Greater2 mov ah, 09h ;вывод сообщения об ошибке lea dx, msgErr ; параметры не в ОДЗ int 21h jmp @@InputA ;повторный ввод параметров @@Greater2: mov ax, A ;(dx:ax):=A*B imul B sub ax, 4 ;(dx:ax):=A*B-4 sbb dx, 0 idiv A ;ax:=(A*B-4)/A mov X, ax @@Exit: ;вывод результата mov ah, 09h lea dx, msgShowX int 21h mov ax, X call Show_AX ;завершение программы mov ax, 4C00h int 21h main endp ; преобразования строки в число ; на входе: ; ds:[si] - строка с числом ; ds:[di] - адрес числа ; на выходе ; ds:[di] - число ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен) Str2Num proc push ax push bx push cx push dx push ds push es push si push ds pop es mov cl, ds:[si] xor ch, ch inc si mov bx, 10 xor ax, ax ;если в строке первый символ '-' ; - перейти к следующему ; - уменьшить количество рассматриваемых символов cmp byte ptr [si], '-' jne @@Loop inc si dec cx @@Loop: mul bx ; умножаем ax на 10 ( dx:ax=ax*bx ) mov [di], ax ; игнорируем старшее слово cmp dx, 0 ; проверяем, результат на переполнение jnz @@Error mov al, [si] ; Преобразуем следующий символ в число cmp al, '0' jb @@Error cmp al, '9' ja @@Error sub al, '0' xor ah, ah add ax, [di] jc @@Error ; Если сумма больше 65535 cmp ax, 8000h ja @@Error inc si loop @@Loop pop si ;проверка на знак push si inc si cmp byte ptr [si], '-' jne @@Check ;если должно быть положительным neg ax ;если должно быть отрицательным jmp @@StoreRes @@Check: ;дополнительная проверка, когда при вводе положительного числа получили отрицательное or ax, ax ; js @@Error @@StoreRes: ;сохранить результат mov [di], ax clc pop si pop es pop ds pop dx pop cx pop bx pop ax ret @@Error: xor ax, ax mov [di], ax stc pop si pop es pop ds pop dx pop cx pop bx pop ax ret Str2Num endp ; выводит число из регистра AX на экран ; входные данные: ; ax - число для отображения Show_AX proc push ax push bx push cx push dx push di mov cx, 10 ; cx - основание системы счисления xor di, di ; di - кол. цифр в числе ; если число в ax отрицательное, то ;1) напечатать '-' ;2) сделать ax положительным or ax, ax jns @@Conv push ax mov dx, '-' mov ah, 2 ; ah - функция вывода символа на экран int 21h pop ax neg ax @@Conv: xor dx, dx div cx ; dl = num mod 10 add dl, '0' ; перевод в символьный формат inc di push dx ; складываем в стэк or ax, ax jnz @@Conv ; выводим из стэка на экран @@Show: pop dx ; dl = очередной символ mov ah, 2 ; ah - функция вывода символа на экран int 21h dec di ; повторяем пока di<>0 jnz @@Show pop di pop dx pop cx pop bx pop ax ret Show_AX endp end main
Объяснение кода листинга программы
Этот код на ассемблере вычисляет выражение, введенное пользователем, и выводит результат на экран. Ввод осуществляется с помощью функции Str2Num
, которая преобразует строку в число. Код проверяет ошибки ввода, такие как ввод отрицательного числа, и выводит соответствующее сообщение об ошибке. После ввода обоих параметров и их преобразования в числа, код проверяет, является ли A меньше B, и выводит соответствующее сообщение. Если A равно B, выводится сообщение об ошибке. Если A больше B, результат вычисления A*B-4 делится на A и сохраняется в X. Затем выводится сообщение с результатом.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д