Найти значение выражения. Не получается вывести результат на экран - 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 ; конец программы
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д