Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- format PE GUI 4.0
- include 'win32ax.inc'
- entry main_func ; точка старта программы
- .code
- generate_answer: ; точка входа в цикл, насчитывающего ответ на поставленную задачу
- ; Для начала нужно получить разность значений степенного ряда (следующего элемента и предыдущего)
- FADD st0, st5 ; лучили значение следующего на вершину стека, не трогая его в стеке
- FSUB st0, st4 ; получили разность между текущим и следующим значением степенного ряда
- FABS ; берём модуль от полученной разности
- ; Далее нам необходимо сравнить полученное значение с эпсилоном
- FCOM [eps] ; Сравниваем модуль разности и эпсилон
- FSTSW ax ; выгружаем значения битов SR
- SAHF ; загружаем значения битов во флаги
- JAE get_next ; проверяем на >=
- JMP print_answer ; прыгаем, чтобы вывести ответ
- get_next: ; точка генерации следующего элемента степенного ряда
- ; Нужно сделать текущее значение степенного ряда равному следующему
- FSUB st0, st0 ; обнуляем то, что сейчас лежит на вершине стека
- FXCH st4 ; вытаскиваем на вершину стека значение ряда сейчас
- FSUB st0, st0 ; затираем его
- FADD st0, st5 ; делаем равным следующему (на следующем шаге следующий станет текущим)
- FXCH st4 ; пихаем его на своё место
- ; Далее насчитаем следующее значение степенного ряда
- ; Для начала пересчитаем дельту
- ; Во избжании переполнения сначала будем делить, и только потом умножать
- FXCH st2 ; меняем местами с текущей степенью
- FADD [one] ; увеличиваем степень на единицу
- FXCH st2 ; меняем обратно
- FXCH st1 ; вытаскиваем дельту наверх
- FDIV st0, st2 ; делим на степень
- ; нужно повторить, чтобы посчитать факториал
- FXCH st2 ; меняем местами недосчитанную дельту и степень
- FADD [one] ; добавляем единицу к степени
- FXCH st2 ; загружаем степень на её законное место
- FDIV st0, st2 ; делим на следующую степень, чтобы получить факториал
- ; знаменатель дельты посчитан - теперь нам необходимо посчитать сичлитель
- FMUL st0, st3 ; умножаем на изначальное значение аргумента - получаем следующую степень
- FMUL st0, st3 ; умножаем на изначальное значение аргумента - получаем следующую степень
- FMUL st0, st6 ; умножаем полученное значение на -1
- FXCH st1 ; дельта посчитана и установлена на своё место
- ; Теперь необходимо посчитать следующее значение
- FXCH st5 ; перемещаем следующее значение на вершину стека для пересчёта
- FADD st0, st1 ; Прибавляем очередной шаг (дельту) к текущему значению - получаем следующее
- FXCH st5 ; устанавливаем следующее значение на место
- JMP generate_answer ; прыгаем обратно на условие цикла
- main_func:
- FINIT ; инициализация сопроцессора
- ; заполняем нужные регистры в FPU нулями (нужно, чтобы безболезненно реализовать алгоритм полностью на FPU)
- FLDZ
- FLDZ
- FLDZ
- FLDZ
- FLDZ
- FLDZ
- FLDZ
- ; теперь наш стек полностью состоит из 0 - для поддержания порядка стека
- ; будем пользоваться не FLD, который пихает на верх стека значение и всё сдвигает,
- ; а сложение, которое ничего сдвигать не будет
- FADD [minus_one] ; загружаем -1
- FXCH st6 ; ставим -1 на место
- FADD [x] ; загрузка в вершину стека параметра синуса
- FXCH st3 ; ставим значение параметра в его место на стеке
- FADD [x] ; загрузка в вершину стека значение ряда на данный момент
- FXCH st4 ; ставим значение параметра в его место на стеке
- FADD [one] ; загружаем в веришину стека значение степени на данный момент
- FXCH st2 ; ставим значение степени на её место на стеке
- ; Далее нам нужно предподсчитать дельту
- ; для начала посчитаем числитель x^3
- FADD [x] ; начинаем подсчёт дельты
- FMUL st0, st3 ; возводим числитель в квадрат
- FMUL st0, st3 ; возводим числитель в куб
- ; теперь идём считатть знаменатель 3!
- FXCH st2 ; меняем местами с текущей степенью
- FADD [one] ; увеличиваем степень на единицу
- FXCH st2 ; меняем обратно
- FDIV st0, st2 ; делим на степень
- ; нужно повторить, чтобы посчитать факториал
- FXCH st2 ; меняем местами недосчитанную дельту и степень
- FADD [one] ; добавляем единицу к степени
- FXCH st2 ; загружаем степень на её законное место
- FDIV st0, st2 ; делим на следующую степень, чтобы получить факториал
- FMUL st0, st6 ; умножаем полученное значение на -1
- FXCH st1 ; дельта посчитана и установлена на своё место
- FADD [x] ; начинаем подсчёт следующего значения степенного ряда
- FADD st0, st1 ; Прибавляем очередной шаг (дельту) к текущему значению - получаем следующее
- FXCH st5 ; устанавливаем следующее значение на место
- ;теперь переходим к написанию самого цикла, подсчитывающего знчение
- JMP generate_answer ; входим в начало цикла
- print_answer:
- FXCH st5 ; пушим следующее значение ряда на верх стека, чтобы вывести в качестве ответа
- FSTP [result] ; выгружаем ответ
- cinvoke sprintf,res_string,fmt_string, dword[x],dword[x+4], dword[x],dword[x+4], dword[result],dword[result+4]
- cinvoke MessageBox,0,res_string,"Сложение двух 'плавающих' чисел двойной точности", 0
- ;cinvoke ExitProcess, 0 ; выход из программы с кодом возврата 0
- .data ; data readable writable
- fmt_string db "Первое 'плаваюшее' число= %f , второе= %f , их сумма= %f",0
- res_string db 256 dup(?) ; строка результата форматирования
- x dq 3.14 ; первое слагаемое (формат двойной точности - 4 слова)
- pow dq 1.0 ; степень
- one dq 1.0 ; просто единица
- minus_one dq -1.0 ; просто -1
- eps dq 0.00005; значение эпсилона (по нему понимаем точность и когда следует остановиться)
- result dq ? ; результат сложения (формат двойной точности)
- data import ; импортируем стандартные функции Windows
- library user32, 'USER32.DLL', msvcrt, 'MSVCRT.DLL', kernel32, 'KERNEL32.DLL', shell32, 'SHELL32.DLL'
- import KERNEL32, ExitProcess, 'ExitProcess', GetCommandLine, 'GetCommandLineA'
- import user32, MessageBox, 'MessageBoxA'
- import msvcrt, sprintf, 'sprintf', sscanf, 'sscanf'
- end data
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement