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