Найти значение выражения. Не получается вывести результат на экран - Assembler

Узнай цену своей работы

Формулировка задачи:

Добрый вечер! Помогите найти ошибку. Ассемблер изучаю всего несколько дней. Необходимо вычислить значение выражения (A*X+B)div(C*X*X+D*X+E). Ввод данных получилось сделать по образцу при помощи процедур ASCII, а как делать вывод на экран пока не понимаю, возможно ошибка где-то в вычислениях. Компилятор TASM 4.1 через DOSBox 0.74. Заранее спасибо!
.model tiny     ; модель (64 Кб) памяти, используемая для СОМ
.code       ; начало сегмента кода
org 100h        ; начальное значение счетчика инструкций (IP) - 100h
    start:  ; метка начала программы, расположена по адресу 100h

mov a,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message1 ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah       ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov a,ax        ; сохранение результата
 
mov b,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message2 ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah       ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov b,ax        ; сохранение результата
 
mov c,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message3 ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah       ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov c,ax        ; сохранение результата
 
mov d,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message4 ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah       ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov d,ax        ; сохранение результата
 
mov e,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message5 ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah       ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov e,ax        ; сохранение результата
 
mov x,ax        ; сохранение результата
mov ah,9        ; номер функции вывода на экран - в АН
mov dx,offset message6  ; адрес начала строки - в DX
int 21h     ; вызов системной функции DOS
mov ah,0ah          ; номер функции ввода с клавиатуры - в АН
lea dx,buf      ; адрес начала буфера ввода - в DX
int 21h     ; вызов системной функции DOS
 
call ASCII      ; вызов процедуры
mov x,ax        ; сохранение результата

;-------------
;вычисление значеня выражения
 
mov ax,a
mul x       ; A*X
mov f,ax
 
mov ax,f
add ax,b
mov g,ax    ;вычислили g
 
mov ax,x
mul x 
mov h,ax
 
mov ax,c
mul h
mov i,ax
 
mov ax,d
mul x
mov j,ax
 
mov ax,i
add ax,j
mov k,ax    ;вычислили k
 
mov ax,k
add ax,e
mov l,ax    ;вычислили l
 
;-----------------------------
;вывести результат на экран
mov dx,offset message7
mov ah,9
int 21h 
mov dx,ax
int 21h 
mov ax,4ch 
int 21h 
;-------------

ret         ; завершение программы
 
ASCII:      ; метка процедуры
xor di,di       ; DI = 0 - номер байта в буфере
xor ax,ax        ; АХ = 0 - текущее значение результата
mov cl,blength
xor ch,ch
xor bx,bx
mov si,cx       ; SI - длина буфера
mov cl,10       ; CL = 10, множитель для MUL
asc2hex:
mov bl,byte ptr bcontent[di]    ; считываем очередной символ
sub bl,'0'      ; цифра = код цифры - код символа "0",
jb asc_error    ; если код символа был меньше, чем код "0",
cmp bl,9        ; или больше, чем "9",
ja asc_error    ; выйти из программы с сообщением об ошибке,
mul cx      ; иначе: умножить текущий результат на 10,
add ax,bx       ; добавить к нему новую цифру,
inc di      ; увеличить счетчик
cmp di,si       ; если счетчик+1 меньше числа символов -
jb asc2hex  ; продолжить (счетчик считается от 0)
ret         ; завершение процедуры
 
asc_error:
mov dx,offset err_msg
mov ah,9
int 21h     ; вывести сообщение об ошибке
mov ax,4c00h    ; 4c - функция завершения программы (00=return 0)
;mov      ah,4ch – можно записать одной командой, а можно двумя
;mov      al,00h
int 21h     ; и завершить программу

.data
message1 db 0Dh,0Ah, "Enter A : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message2 db 0Dh,0Ah, "Enter B : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message3 db 0Ah,0Dh, "Enter C : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message4 db 0Dh,0Ah, "Enter D : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message5 db 0Dh,0Ah, "Enter E : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message6 db 0Ah,0Dh, "Enter X : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
err_msg db 0Dh,0Ah, "Error! ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message7 db 0Dh,0Ah, "Result: ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
;-------------
 
;-------------

; Буфер ввода
buf db 10       ; максимальное кол-во символов
blength db ?        ; для сохранения длины введённой строки
bcontent db 10 dup (32) ; для хранения введённой строки
 
a dw 0
b dw 0
c dw 0
d dw 0
e dw 0
x dw 0
 
f dw 0  ;для умножения
g dw 0
h dw 0
i dw 0
j dw 0
k dw 0
l dw 0
m dw 0  ;для умножения

end        start             ; конец программы

Решение задачи: «Найти значение выражения. Не получается вывести результат на экран»

textual
Листинг программы
.model tiny     ; модель (64 Кб) памяти, используемая для СОМ
.code           ; начало сегмента кода
org 100h        ; начальное значение счетчика инструкций (IP) - 100h
 
start:      ; метка начала программы, расположена по адресу 100h
 
 
        mov     dx,     offset message1 ; адрес начала строки - в DX
        call    InputInt
        mov     a,      ax      ; сохранение результата
 
        mov     dx,     offset message2 ; адрес начала строки - в DX
        call    InputInt
        mov     b,      ax        ; сохранение результата
 
        mov     dx,     offset message3 ; адрес начала строки - в DX
        call    InputInt
        mov     c,      ax        ; сохранение результата
 
        mov     dx,     offset message4 ; адрес начала строки - в DX
        call    InputInt
        mov     d,      ax        ; сохранение результата
 
        mov     dx,     offset message5 ; адрес начала строки - в DX
        call    InputInt
        mov     e,      ax        ; сохранение результата
 
        mov     dx,     offset message6  ; адрес начала строки - в DX
        call    InputInt
        mov     x,      ax        ; сохранение результата
 
 
;-------------
;вычисление значеня выражения
 
mov ax,a
mul x       ; A*X
mov f,ax
 
mov ax,f
add ax,b
mov g,ax    ;вычислили g
 
mov ax,x
mul x
mov h,ax
 
mov ax,c
mul h
mov i,ax
 
mov ax,d
mul x
mov j,ax
 
mov ax,i
add ax,j
mov k,ax    ;вычислили k
 
mov ax,k
add ax,e
mov l,ax    ;вычислили l
 
mov ax,g
mov dx, 0
div l
mov m,ax
 
;-----------------------------
;вывести результат на экран
        mov     ah,     09h
        mov     dx,     offset message7
        int     21h
 
        mov     ax,     m
        call    OutInt
 
        ;завершение программы
        int     20h
 
 
; преобразования строки в число
; на входе:
; ds:[si] - строка с числом
; ds:[di] - адрес числа
; на выходе
; ds:[di] - число
; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
Str2Num PROC
        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
        ret
@@Error:
        xor     ax, ax
        stc
        pop     si
        pop     es
        pop     ds
        pop     dx
        pop     cx
        pop     bx
        ret
Str2Num ENDP
 
;ввод числа
;вход
; ds:dx - строка приглашение
;выход
; ax - введённое число
InputInt        proc
        push    si
@@Another:
        push    dx
        mov     ah,     09h     ; номер функции вывода на экран - в АН
        ;mov    dx,offset message1 ; адрес начала строки - в DX
        int     21h             ; вызов системной функции DOS
        mov     ah,     0ah     ; номер функции ввода с клавиатуры - в АН
        lea     dx,     buf     ; адрес начала буфера ввода - в DX
        int     21h             ; вызов системной функции DOS
        pop     dx
 
        lea     si,     buf+1
        call    Str2Num         ; вызов процедуры
        jc      @@Another
        pop     si
        ret
InputInt        endp
 
OutInt proc
;; если число знаковое, то необходимо расскоментировать следующие строки
;; Проверяем число на знак.
   test    ax, ax
   jns     oi1
;
;; Если оно отрицательное, выведем минус и оставим его модуль.
   mov  cx, ax
   mov     ah, 02h
   mov     dl, '-'
   int     21h
   mov  ax, cx
   neg     ax
;; Количество цифр будем держать в CX.
oi1:
    xor     cx, cx
    mov     bx, 10 ; основание сс. 10 для десятеричной и т.п.
oi2:
    xor     dx,dx
    div     bx
; Делим число на основание сс. В остатке получается последняя цифра.
; Сразу выводить её нельзя, поэтому сохраним её в стэке.
    push    dx
    inc     cx
; А с частным повторяем то же самое, отделяя от него очередную
; цифру справа, пока не останется ноль, что значит, что дальше
; слева только нули.
    test    ax, ax
    jnz     oi2
; Теперь приступим к выводу.
    mov     ah, 02h
oi3:
    pop     dx
; Извлекаем очередную цифру, переводим её в символ и выводим.
;; раскоментировать если основание сс > 10, т.е. для вывода требуются буквы
;   cmp     dl,9
;   jbe     oi4
;   add     dl,7
;oi4:
    add     dl, '0'
    int     21h
; Повторим ровно столько раз, сколько цифр насчитали.
    loop    oi3
 
    ret
OutInt endp
 
.data
message1        db 0Dh,0Ah, "Enter A : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message2        db 0Dh,0Ah, "Enter B : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message3        db 0Ah,0Dh, "Enter C : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message4        db 0Dh,0Ah, "Enter D : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message5        db 0Dh,0Ah, "Enter E : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message6        db 0Ah,0Dh, "Enter X : ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
err_msg         db 0Dh,0Ah, "Error! ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
message7        db 0Dh,0Ah, "Result: ",0Dh,0Ah, '$' ; строка для вывода, символ $ - символ конца вывода
;-------------
 
;-------------
 
; Буфер ввода
buf             db 10           ; максимальное кол-во символов
blength         db ?            ; для сохранения длины введённой строки
bcontent        db 10 dup (0)   ; для хранения введённой строки
 
a               dw 0
b               dw 0
c               dw 0
d               dw 0
e               dw 0
x               dw 0
 
f               dw 0            ;для умножения
g               dw 0
h               dw 0
i               dw 0
j               dw 0
k               dw 0
l               dw 0
m               dw 0            ;для умножения
 
 
end             start           ; конец программы

Оцени полезность:

10   голосов , оценка 3.9 из 5
Похожие ответы