Gistrec icon

asm lab 3

Gistrec | PRO | 12/03/18 09:07:01 PM UTC | 0 ⭐ | 12618 👁️ | Never ⏰ | []
ASM (NASM) |

0 B

|

None

|

0 👍

/

0 👎

/**
 * Программа находит решение уравнения ln((x - 1) / 3) / 3 = 0
 * методом Ньютона с подвижным полюсом
 */
 
/******** MAIN.CPP ********/
#include <iostream> // cin, cout
#include <iomanip>  // setprecision
 
using std::cout;
using std::endl;
 
/**
 * Процедура реализует метод 'Ньютона с подвижным полюсом'
 * Возвращает значение X в уравнении ln((x - 1) / 3) / 3 = 0
 * С точностью |X - nextX| < accuracy
 */
extern "C" void __fastcall calculate();
 
extern "C" float X     = 1.5f; // Начальное значение
extern "C" float NextX = NULL; // Следующее значение функции
 
extern "C" float accurecy = 1e-6f; // Точность |X - NextX|
 
int main() {
    cout << X << endl;
 
    calculate();
    cout << std::setprecision(10) << NextX << endl;
 
    return 0;
}
 
 
 
/******** FUNCT.ASM ********/
.386
.MODEL FLAT;
 
EXTERN _X: DWORD
EXTERN _NextX: DWORD
EXTERN _accurecy: DWORD
 
.DATA
BUFFER DWORD 0.0
THREE  DWORD 3.0 ; Константа 3
TWO    DWORD 2.0 ; Константа 2
.CODE
 
; Получаем значение функции  f(x) = ln((x - 1) / 3) / 3
; Постфиксная запись         f(x) = x 1 - 3 / ln 3 /
; Входное значение    _X
; Выходное значение   BUFFER
getF PROC
fld1 ; Для логарифма...
 
FLD _X ; Загружаем X
FLD1   ; Загружаем 1
FSUB   ; Отнимаем от X, 1
 
FLD THREE ; Загружаем в стек 3
FDIV      ; Делим первый раз на три
 
; Натуральный логарифм X = ln(X) = ln(2) * log2(X) = fyl2x(fldln2, X)
; URL: http://www.cyberforum.ru/assembler/thread525843.html
FYL2X  ; st(0) = st(1) * log2( st(0) )
FLDLN2 ; st(0) = ln(2)   st(1) = (X - 1) / 3
FMUL
 
FLD THREE ; Загружаем в стек 3
FDIV      ; Делим второй раз на три
 
FSTP BUFFER ; Сохраняем значение в переменную BUF
 
RET
getF ENDP
 
; Получаем значение производной функции   fdx(x) = 1 / (3 * (x - 1))
; Постфиксная запись                      fdx(x) = 1 3 x 1 - * /
; Входное значение    _X
; Выходное значение   BUFFER
getFdx PROC
FLD1
FLD THREE
FLD _X
FLD1
FSUB
FMUL
FDIV
 
FSTP BUFFER
 
RET
getFdx ENDP
 
; Получаем значение      xk+1 = xk + f(xk) * (f(xk) - 2) / 2 * fdx(xk)
; Постфиксная запись     xk+1 = xk f(xk) f(xk) 2 - * 2 / fdx(xk) * +
; Входное значение  (xk)     _X
; Выходное значение (xk+1)   _NextX
next PROC
FLD _X ; Загружаем X
 
call getF  ; Вычисляем f(xk)
FLD BUFFER ; Загружаем f(xk)
FLD BUFFER
 
FLD TWO
FSUB
FMUL
FLD TWO
FDIV
 
call getFdx  ; Вычисляем fdx(xk)
FLD BUFFER   ; Загружаем fdx(xk)
 
FMUL
FADD
 
FSTP _NextX
 
RET
next ENDP
 
@calculate@0 PROC
; Инициализируем сопроцессор
FINIT
call next;
 
@start:
FLD _X                      ;
FLD _NextX                  ;    Сравниваем точность нашего решения, которая вычисляется
FSUB                        ;    по формуле |_X - _NextX|
FABS                        ;    с заданной точностью, которая хранится в accurecy
                            ;
FLD _accurecy               ;
FCOMIP ST(0), ST(1)         ;
                            ;    Если наше реiение точно, то переходим на метку @exit
JNC @exit                   ;    Иначе продолжаем цикл
 
 
MOV EAX, _NextX
call next         ; Получаем xk+1
MOV _X, EAX
call next ; Какого хуя это тут нужно?!
loop @start
 
 
@exit:
RET
@calculate@0 ENDP
 
 
END

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎