/** * Программа находит решение уравнения ln((x - 1) / 3) / 3 = 0 * методом Ньютона с подвижным полюсом */ /******** MAIN.CPP ********/ #include // cin, cout #include // 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