/**
* Программа находит решение уравнения 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
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎