Вычисления значения функции в формате с плавающей запятой - Assembler

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

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

Задание такое - Написать программу для решения функции y=х^2-x^4, где х меняется от -2 до +2 с шагом 0,5. Нужно вычислить функцию на каждом шаге. В формате вычисления с плавающей комой. Процессор х86.
TITLE Курсова робота
EXTERN MULFXX, MULFXY, ADDSUBFYZ, ADDSUBFYZ
 
STACK SEGMENT PARA STACK “STACK”
    DB  64 DUP (0)
STACK ENDS
 
DSEG SEGMENT PARA PUBLIC “DATA”
    X   DD  -2.0
        DX  DD    0.5
    Y   DD  1 DUP (0)
    Z   DD  1 DUP (0)
    R   DQ  8 DUP (0)
DSEG ENDS
 
CSEG SEGMENT PARA PUBLIC “CODE”
    ASSUME CS:CSEG, DS:DSEG, SS:STACK
 
MAIN PROC FAR
    mov ax,DSEG
    mov ds,ax
    mov cx,8  ; по скольку нужно сделать исчисления от -2 до +2 с шагом 0,5 заносим в счётчик(сх) 8
    push    cx  ; заносим в стек сх, по скольку в подпрограммах используется регистр сх
Start:  call    MULFXX  ; Возводим Х в квадрат и заносим результат в Y
    call    MULFYY  ; Возводим Х в 4 степень и заносим результат в Z
    call    ADDSUBFYZ  ; Y-Z
    pop cx  ; достаём сх из стека для цикла
    call    ADDSUBFXDX  ; для реализации шага выполняем эту подпрограмму, то есть x-dx, то есть 2.0-0,5, то есть, если сначала в Х было значение -2.0, то теперь там -1.5
    loop    Start  ; цикл
Такие вопросы Как после выполнения всех подпрограмм занести результат со смещением 4 байта и в какой регистр его лучше занести ? Будет ли уменьшатся сх после того как мы его достанем из стека и выполним цикл. То есть сначала в сх 8, после того выполнили цикл, он должен стать 7, но поскольку мы достаём из стека сх со значением 8, значит сх не уменьшается. Во общем если сх не уменьшается, то как сделать так что бы программа выполнилась 8 раз и закончилась ?

Решение задачи: «Вычисления значения функции в формате с плавающей запятой»

textual
Листинг программы
Start:          lea si,Y
lea di,Z
mov bx,[si+2]
mov si,[si]
mov dx,[di+2]
mov di,[di]
; Переход к подпрограммам сложения, вычитания
call    ADDSUBF
ADDSUBF PROC
 
; Сравнить знаки операндов и определить операцию
@addf:  mov al,bh   ; Сравнить
xor     al,dh   ; знаки операндов
jns     @addf1  ; Знаки операндов одинаковы
xor     dh,80h  ; Знаки различны,
jmp     @subf   ; перейти к вычитанию
;
; Проверить операнды на нуль
@addf1: mov ax,dx   ; Проверить на нуль
or  ax,di   ;   второй операнд
jz  @addf8  ;   Результат в BX:SI
mov ax,bx   ;   Проверить на нуль
or  ax,si   ;   первый операнд
jnz @addf2  ;   Оба операнда не нулевые
xchg    bx,dx   ;   Первый операнд равен нулю,
xchg    si,di   ;   сумма равна
jmp @addf8  ;   второму операнду
;
; Оба операнда не нулевые можно складывать.
@addf2: mov ah,bh   ; Сравнить общий знак в АН
shl bx,1    ; Восстановить скрытый бит
stc ; мантиссы первого операнда
rcr bl,1
shl dx,1    ; Восстановить скрытый бит
stc ; мантиссы второго операнда
rcr dl,1
; Сранить порядки, образовать разность порядков
cmp bh,dh   ; Сравнить порядки
jnc @addf3  ; Порядок числа в BX:SI больше
xchg    bx,dx   ; Передать большее число
xchg    si,di   ; в BX:SI
@addf3: sub bh,dh   ; Образовать разность порядков
jz  @addf6  ; Порядки одинаковы
cmp bh,24   ; Сравнить разность порядков с 24
jc  @addf5  ; Разность порядков меньше 24
jmp @addf7  ; Результата в BX:SI
; Необходимо сдвигать вправо мантиссу меньшего числа в DL:DI 
@addf5: shr     dl,1    ; Сдвинуть мантиссу
rcr di,1
inc dh      ; Увеличить меньший порядок
dec bh      ; Декремент разности порядков
jnz @addf5  ; Повторять сдвиг
mov bh,dh   ; Передать порядок в BH
;
; Можно складывать мантиссы. В регистре DH общий порядок 
@addf6: add     si,di   ; Сложить младшие части мантисс
adc     bl,dl   ; Сложить старшие части мантисс
jnc     @addf7  ; Нарушения нормализации влево нет
inc     dh      ; Скорректировать порядок
cmp     dh,255  ; Проверить переполнение
stc
jz  @addf8  ; Возникло пререполнение
rcr bl,1    ; Сдвинуть
rcr si,1    ; мантиссу вправо
mov bh,dh   ; Передать порядок в BH
;
; Форматировать результат
@addf7: add ah,ah   ; Знак во флаге переноса
rcr bh,1    ; Знак числа на месте
rcr ah,1    ; Младший бит порядка в АН7
or  ah,7fh  ; Образовать мантиссу
and bl,ah   ; Образовать второй байт числа
@addf8: ret
;
; Сохранить результат
lea di,Z
mov [di],si
mov [di+2],bx
jmp Start   ;ret
 
@subf:
; Проверить операнды на нуль
@subf1: mov ax,dx   ; Проверить на нуль
or  ax,di   ;   второй операнд
jz  @subfa  ;   Результат в BX:SI
mov ax,bx   ;   Проверить на нуль
or  ax,si   ;   первый операнд
jnz @subf2  ;   Оба операнда не нулевые
xchg    bx,dx   ;   Первый операнд равен нулю,
xchg    si,di   ;   разность равна
xor bh,80h  ;   второму операнду
jmp @subfa  ;   с измененным знаком
;
; Оба операнда не нулевые можно вычитать.
@subf2: mov ah,bh   ; Сохранить знак уменьшаемого
shl bx,1    ; Восстановить скрытый бит
stc ; мантиссы уменьшаемого
rcr bl,1
shl dx,1    ; Восстановить скрытый бит
stc ; мантиссы вычитаемого
rcr dl,1
; Проверить отношения между числами
cmp bh,dh   ;   Сравнить порядки
jnz @subf3  ;   Порядки не равны
cmp bl,dl   ;   Сранить старшие байты мантисс
jnz @subf3  ;   Они не равны
cmp si,di   ;   Сравнить младшие слова мантисс
jnz @subf3  ;   Они не равны
mov bx,0    ;   Числа равны,
mov si,0    ;   разность равна нулю
jmp @subfa
; Операнды не равны, необходимо вычитать.
@subf3: jnc @subf4  ; Уменьшаемое больше вычитаемого
xchg    bx,dx   ; Вычитаемое больше уменьшаемого,
xchg    si,di   ; обменять числа
xor ah,80h  ; Изменить знак результата
; Образовать разность порядков.
@subf4: sub bh,dh   ; Разность порядков в BH
jz  @subf7  ; Порядки одинаковы
cmp bh,24   ; Сравнить разность порядков с 24
jc  @subf6  ; Разность порядков меньше 24
jmp @subf9  ; Результата в BX:SI
; Необходимо сдвигать вправо мантиссу менишего числа в DL:DI 
@subf6: shr     dl,1    ; Сдвинуть мантиссу
rcr di,1
inc dh      ; Увеличить меньший порядок
dec bh      ; Декремент разности порядков
jnz @subf6  ; Повторять сдвиг
mov bh,dh   ; Передать общий порядок в BH
; Вычитание мантисс и образование результата.
@subf7: sub si,di   ; Вычесть мантиссы
sbb bl,dl
@subf8: or  bl,bl   ; Проверить старший бит мантиссы
js      @subf9  ;   Результат нормализован
dec     bh  ;   Декремент порядка
cmp     bh,255  ;   Проверить переполнение
stc ;   Установить флаг переноса
jz      @subfa  ;   Возникло антипереполнение
shl     si,1    ;   Сдвинуть мантиссу влево
rcl bl,1
jmp @subf8  ; Повторять до нормализации
; Форматировать результат
@subf9: add ah,ah   ; Знак во флаге переноса
rcr bh,1    ; Знак числа на месте
rcr ah,1    ; Младший бит порядка в АН7
or  ah,7fh  ; Образовать мантиссу
and bl,ah   ; Образовать второй байт числа
@subfa: ret
;
; Сохранить результат
mov ax,si   ; младшая часть ответа в ах
lodsw       ; младшая часть ответа из ах по адресу di, а di+2
mov ax,bx   ; старшая часть ответа в ах
lodsw       ; старшая часть ответа из ах по адресу di, а di+2
 
ADDSUBF ENDP

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

  1. Сначала код вычисляет значение функции в формате с плавающей запятой.
  2. В начале кода происходит загрузка значений функций в регистры SI и ZD.
  3. Затем происходит сравнение знаков операндов и определение операции.
  4. Если знаки операндов одинаковы, то выполняется сложение.
  5. Если знаки операндов различны, то выполняется вычитание.
  6. Далее происходит проверка операндов на нуль.
  7. Если один из операндов равен нулю, то результат функции равен второму операнду.
  8. Если оба операнда не равны нулю, то происходит проверка отношений между числами.
  9. Если числа равны, то результат функции равен нулю.
  10. Если числа не равны, то выполняется вычитание.
  11. Затем происходит образование разности порядков.
  12. Далее происходит сдвиг мантиссы меньшего числа вправо.
  13. Затем происходит вычитание мантисс и образование результата.
  14. После этого происходит форматирование результата.
  15. В конце кода результат функции сохраняется в памяти.

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

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