Вычисление выражения по формуле - Assembler (223260)

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

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

Необходимо посчитать след. формулу: Вот программа, которую собрал из учебника:
        title prim
        assume cs:cod, ds:d, ss:s
 
s        segment stack
        dw 128 dup (?)
s        ends
d        segment
;резервируем области под переменные a, b, c
a        dw ?
b        dw ?
c        dw ?
;размещаем строки – подсказки для ввода переменных
msga         db ‘Введите a:$’
msgb         db ‘Введите b:$’
msgc         db ‘Введите c:$’
;размещаем строки – сообщения об ошибках
err1         db ‘Деление на ноль (первая дробь)$’
err2         db ‘Деление на ноль (вторая дробь)$’
;описываем данные для процедур ввода и вывода целых чисел
.
.
.
    d    ends
    c    od segment
    ;описываем процедуры ввода и вывода целых чисел
    cr = 0dh ;cr присваиваем значение кода символа
    ;возврата каретки (клавиши «Enter»)
    lf = 0ah ;lf присваиваем значение кода символа
    ;перевода строки
IntegerIn proc
    start: mov ah,0ah ;функцией 0a вводим строку
    ;символов и размещаем ее в
    ;области string
    lea dx,string
    int 21h
    xor ax,ax ;обнуляем ax, в котором
    ;будем формировать число
    lea si,string+2 ;устанавливаем si на
    ;первый символ введенной
    ;строки
    mov negflag,ax ;обнуляем флаг
    ;отрицательности числа
    ;(предполагаем, что оно
    ;будет неотрицательным)
    cmp byte ptr [si],'-';первый символ – это
    ;минус?
    jne m2 ;если нет – на m2
    not negflag ;отмечаем, что число
    ;отрицательное
    ;(negflag не равен 0)
    inc si ;продвигаем si со
    ;знака числа к первой
    ;цифре
    jmp m ;прыгаем на разбор
    ;строки цифр
    m2: cmp byte ptr [si],'+';первый символ – это
    ;плюс?
    jne m ;если нет – на m
    inc si ;продвигаем si со
    ;знака числа к первой
    ;цифре
    ;анализируем текущий символ
    m: cmp byte ptr [si],cr ;если это cr – строка
    ;закончилась, выходим
    ;из цикла разбора
    ;символов
    je ex1
    cmp byte ptr [si],'0';если код символа
    ;меньше кода '0' –
    ;это не цифра
    jb err ;прыгаем на метку err
    cmp byte ptr [si],'9';если код символа
    ;больше кода '9' –
    ;это не цифра
    ja err ;прыгаем на метку err
    mov bx,10 ;домножаем полученное
    ;число на основание
    ;системы счисления
    mul bx
    sub byte ptr [si],'0';вычитаем код символа
    ;'0' (получаем
    ;очередную цифру)
    add al,[si] ;добавляем цифру к
    ;числу
    adc ah,0
    inc si ;продвигаем si к
    ;следующему символу
    jmp m ;организуем цикл
    ;функцией 09 выводим сообщение об ошибке
    err: lea dx,errmsg
    mov ah,9
    int 21h
    jmp start ;повторяем ввод
    ex1: cmp negflag,0 ;число положительное?
    je ex ;если да – выходим
    neg ax ;меняем знак числа
    ex: ret
IntegerIn endp
 
IntegerOut proc
    xor cx,cx ;обнуляем счетчик цифр
    mov bx,10 ;в bx помещаем делитель
    cmp ax,0 ;проверяем знак числа
    jge m ;если неотрицательное – на m
    neg ax ;иначе – меняем знак числа
    pushax ;сохраняем число перед вызовом
    ;функции, использующей ax
    mov ah,2 ;функцией 02 выводим знак '-'
    mov dl,'-'
    int 21h
    pop ax ;восстанавливаем число в ax
    m: inc cx ;считаем количество
    ;получающихся цифр
    xor dx,dx ;преобразуем делимое к 32
    ;разрядам
    div bx ;получаем очередную цифру
    pushdx ;сохраняем ее в стеке
    or ax,ax ;проверяем есть ли еще цифры
    jnz m ;если да – на метку m
    ;при выходе из цикла в стеке лежат цифры, в cx – их
    ;количество
    m1: pop dx ;извлекаем цифру из стека
    add dx,'0' ;преобразуем в код символа
    mov ah,2 ;функцией 02 выводим на экран
    int 21h
    loopm1 ;повторяем cx раз
    ret ;возвращаемся из процедуры
 
IntegerOut endp
        ;устанавливаем ds на сегмент данных
    string db 255, 0, 255 dup (?)
    errmsg db 'Недопустимый символ, можно'
    db 'использовать только цифры',cr,lf,'$'
 
start:  mov ax,d
    mov ds,ax   ;вводим значение переменныой a
    Mov ah,09 ;выводим строку – подсказку для a
    Lea dx,msga
    Int 21h
    Call IntegerIn ;вводим число
    Mov a,ax ;помещаем его в область a
        ;вводим значение переменныой b
    Mov ah,09 ;выводим строку – подсказку для b
    Lea dx,msgb
    Int 21h
    Call IntegerIn ;вводим число
    Mov b,ax ;помещаем его в область b
        ;вводим значение переменныой c
    Mov ah,09 ;выводим строку – подсказку для c
    Lea dx,msgc
    Int 21h
    Call IntegerIn ;вводим число
    Mov c,ax ;помещаем его в область c
        ;проверяем знаменатели на равенство 0
    Cmp c,0 ;проверяем первый знаменатель
    Jnz m ;если не 0 – на m
    Mov ah,09 ;выводим сообщение об ошибке
    Lea dx,err1
    Int 21h
    Jmp err ;выходим
m:  Mov ax,b ;считаем второй знаменатель
    Add ax,c
    Jnz m1 ; если не 0 – на m1
    Mov ah,09 ;выводим сообщение об ошибке
    Lea dx,err2
    Int 21h
    Jmp err ;выходим
        ;рассчитываем значение выражения
m1: Mov bx,ax ;помещаем второй знаменатель в bx
    Mov ax,a ;считаем второй числитель
    Imul ax
    Mov cx,3
    Imul cx
    Idiv bx ;считаем значение второй дроби
    Push ax ;сохраняем его в стеке
    Mov ax,a ;считаем первый числитель
    Add ax,b
    Mov bx,c ;считаем значение первой дроби
    Cwd
    Idiv bx
    Pop bx ;извлекаем из стека значение второй
        ;дроби
    Sub ax,bx ;вычитаем
    call IntegerOut ;выводим результат
        ;завершаем работу программы
    mov ax,4c00h ;с кодом завершения 0 – без ошибок
    int 21h
err:    mov ax,4cffh ;с кодом завершения 0ffh (-1) – с ошибкой
    int 21h
c od ends
    end start

Решение задачи: «Вычисление выражения по формуле»

textual
Листинг программы
        title prim
        assume cs:cod, ds:d, ss:s
LOCALS
s        segment stack
        dw 128 dup (?)
s        ends
d        segment
;резервируем области под переменные a, b, c
a        dw ?
b        dw ?
y        dw ?
;размещаем строки – подсказки для ввода переменных
msga         db 'Введите a:$'
msgb         db 'Введите b:$'
;размещаем строки – сообщения об ошибках
err1         db 'Деление на ноль (первая дробь)$'
err2         db 'Деление на ноль (вторая дробь)$'
;описываем данные для процедур ввода и вывода целых чисел
    string db 255, 0, 255 dup (?)
    errmsg db 'Недопустимый символ, можно'
    db 'использовать только цифры',cr,lf,'$'
negflag     dw  0
    d    ends
    cod segment
    ;описываем процедуры ввода и вывода целых чисел
    cr = 0dh ;cr присваиваем значение кода символа
    ;возврата каретки (клавиши «Enter»)
    lf = 0ah ;lf присваиваем значение кода символа
    ;перевода строки
IntegerIn proc
    @@start: mov ah,0ah ;функцией 0a вводим строку
    ;символов и размещаем ее в
    ;области string
    lea dx,string
    int 21h
    xor ax,ax ;обнуляем ax, в котором
    ;будем формировать число
    lea si,string+2 ;устанавливаем si на
    ;первый символ введенной
    ;строки
    mov negflag,ax ;обнуляем флаг
    ;отрицательности числа
    ;(предполагаем, что оно
    ;будет неотрицательным)
    cmp byte ptr [si],'-';первый символ – это
    ;минус?
    jne @@m2 ;если нет – на m2
    not negflag ;отмечаем, что число
    ;отрицательное
    ;(negflag не равен 0)
    inc si ;продвигаем si со
    ;знака числа к первой
    ;цифре
    jmp @@m ;прыгаем на разбор
    ;строки цифр
    @@m2: cmp byte ptr [si],'+';первый символ – это
    ;плюс?
    jne @@m ;если нет – на m
    inc si ;продвигаем si со
    ;знака числа к первой
    ;цифре
    ;анализируем текущий символ
    @@m: cmp byte ptr [si],cr ;если это cr – строка
    ;закончилась, выходим
    ;из цикла разбора
    ;символов
    je @@ex1
    cmp byte ptr [si],'0';если код символа
    ;меньше кода '0' –
    ;это не цифра
    jb @@err ;прыгаем на метку err
    cmp byte ptr [si],'9';если код символа
    ;больше кода '9' –
    ;это не цифра
    ja @@err ;прыгаем на метку err
    mov bx,10 ;домножаем полученное
    ;число на основание
    ;системы счисления
    mul bx
    sub byte ptr [si],'0';вычитаем код символа
    ;'0' (получаем
    ;очередную цифру)
    add al,[si] ;добавляем цифру к
    ;числу
    adc ah,0
    inc si ;продвигаем si к
    ;следующему символу
    jmp @@m ;организуем цикл
    ;функцией 09 выводим сообщение об ошибке
    @@err: lea dx,errmsg
    mov ah,9
    int 21h
    jmp @@start ;повторяем ввод
    @@ex1: cmp negflag,0 ;число положительное?
    je @@ex ;если да – выходим
    neg ax ;меняем знак числа
    @@ex: ret
IntegerIn endp
 
IntegerOut proc
    xor cx,cx ;обнуляем счетчик цифр
    mov bx,10 ;в bx помещаем делитель
    cmp ax,0 ;проверяем знак числа
    jge @@m ;если неотрицательное – на m
    neg ax ;иначе – меняем знак числа
    push ax ;сохраняем число перед вызовом
    ;функции, использующей ax
    mov ah,2 ;функцией 02 выводим знак '-'
    mov dl,'-'
    int 21h
    pop ax ;восстанавливаем число в ax
    @@m: inc cx ;считаем количество
    ;получающихся цифр
    xor dx,dx ;преобразуем делимое к 32
    ;разрядам
    div bx ;получаем очередную цифру
    push dx ;сохраняем ее в стеке
    or ax,ax ;проверяем есть ли еще цифры
    jnz @@m ;если да – на метку m
    ;при выходе из цикла в стеке лежат цифры, в cx – их
    ;количество
    @@m1: pop dx ;извлекаем цифру из стека
    add dx,'0' ;преобразуем в код символа
    mov ah,2 ;функцией 02 выводим на экран
    int 21h
    loop @@m1 ;повторяем cx раз
    ret ;возвращаемся из процедуры
 
IntegerOut endp
        ;устанавливаем ds на сегмент данных
 
start:  mov ax,d
    mov ds,ax   ;вводим значение переменныой a
    Mov ah,09 ;выводим строку – подсказку для a
    Lea dx,msga
    Int 21h
    Call IntegerIn ;вводим число
    Mov a,ax ;помещаем его в область a
        ;вводим значение переменныой b
    Mov ah,09 ;выводим строку – подсказку для b
    Lea dx,msgb
    Int 21h
    Call IntegerIn ;вводим число
    Mov b,ax ;помещаем его в область b
    mov ax, a
    sub ax, b
    Cmp ax,0 ;проверяем первый знаменатель
    Jnz m ;если не 0 – на m
    Mov ah,09 ;выводим сообщение об ошибке
    Lea dx,err1
    Int 21h
    Jmp error ;выходим
m:  Mov ax,a ;считаем второй знаменатель
    Add ax,b
    Jnz m1 ; если не 0 – на m1
    Mov ah,09 ;выводим сообщение об ошибке
    Lea dx,err2
    Int 21h
    Jmp error ;выходим
        ;рассчитываем значение выражения
m1: Mov ax, a
    imul a ;ax:=a^2
    Imul b
    Imul b
    Imul b ;ax:=a^2*b^3
    mov bx,3
    imul bx  ;ax:=3*a^2*b^3
    add ax, 1 ;ax:=3*a^2*b^3+1
    cwd
    mov bx, a ;bx:=a-b
    sub bx, b
    idiv bx ;ax:=(a^2*b^3+1)/(a-b)
    mov cx,ax ;сохранение значения первой дроби в cx
    Mov ax,a
    sal ax,1
    sal ax,1 ;ax:=a/4
    add ax,b ;ax:=a/4+b
    mov bx,a
    add bx,b
    Idiv bx ;считаем значение второй дроби
    Sub cx,ax ;вычитаем
    mov ax,cx
    call IntegerOut ;выводим результат
        ;завершаем работу программы
    mov ax,4c00h ;с кодом завершения 0 – без ошибок
    int 21h
error:    mov ax,4cffh ;с кодом завершения 0ffh (-1) – с ошибкой
    int 21h
cod ends
    end start

Объяснение кода листинга программы

В данном коде происходит вычисление выражения по формуле a^2*b^3+1/(a-b). Список действий:

  1. Ввод значений переменных a и b с помощью процедуры IntegerIn.
  2. Проверка значения первого знаменателя (a) на ноль. Если он равен нулю, выводится сообщение об ошибке и происходит переход на метку m.
  3. Вычисление второго знаменателя (b) и проверка его значения на ноль. Если он равен нулю, также выводится сообщение об ошибке и происходит переход на метку m.
  4. Вычисление значения выражения по формуле a^2*b^3+1/(a-b).
  5. Сохранение значения первой дроби (a^2*b^3+1) в переменной cx.
  6. Вычисление значения второй дроби (a/4+b) и вычитание ее из значения первой дроби (cx).
  7. Вывод результата вычисления на экран с помощью процедуры IntegerOut.
  8. Завершение работы программы с кодом завершения 0 (без ошибок) или 0ffh (-1) (с ошибкой), в зависимости от наличия ошибок в процессе выполнения программы.

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

15   голосов , оценка 4 из 5