Advertisement
Guest User

Untitled

a guest
Dec 7th, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.01 KB | None | 0 0
  1. format PE GUI 4.0
  2. include 'win32ax.inc'
  3. entry main_func ; точка старта программы
  4.  
  5. .code
  6.  
  7. generate_answer: ; точка входа в цикл, насчитывающего ответ на поставленную задачу
  8. ; Для начала нужно получить разность значений степенного ряда (следующего элемента и предыдущего)
  9. FADD st0, st5 ; лучили значение следующего на вершину стека, не трогая его в стеке
  10. FSUB st0, st4 ; получили разность между текущим и следующим значением степенного ряда
  11. FABS ; берём модуль от полученной разности
  12. ; Далее нам необходимо сравнить полученное значение с эпсилоном
  13. FCOM [eps] ; Сравниваем модуль разности и эпсилон
  14. FSTSW ax ; выгружаем значения битов SR
  15. SAHF ; загружаем значения битов во флаги
  16. JAE get_next ; проверяем на >=
  17. JMP print_answer ; прыгаем, чтобы вывести ответ
  18.  
  19. get_next: ; точка генерации следующего элемента степенного ряда
  20. ; Нужно сделать текущее значение степенного ряда равному следующему
  21. FSUB st0, st0 ; обнуляем то, что сейчас лежит на вершине стека
  22. FXCH st4 ; вытаскиваем на вершину стека значение ряда сейчас
  23. FSUB st0, st0 ; затираем его
  24. FADD st0, st5 ; делаем равным следующему (на следующем шаге следующий станет текущим)
  25. FXCH st4 ; пихаем его на своё место
  26. ; Далее насчитаем следующее значение степенного ряда
  27. ; Для начала пересчитаем дельту
  28. ; Во избжании переполнения сначала будем делить, и только потом умножать
  29. FXCH st2 ; меняем местами с текущей степенью
  30. FADD [one] ; увеличиваем степень на единицу
  31. FXCH st2 ; меняем обратно
  32. FXCH st1 ; вытаскиваем дельту наверх
  33. FDIV st0, st2 ; делим на степень
  34. ; нужно повторить, чтобы посчитать факториал
  35. FXCH st2 ; меняем местами недосчитанную дельту и степень
  36. FADD [one] ; добавляем единицу к степени
  37. FXCH st2 ; загружаем степень на её законное место
  38. FDIV st0, st2 ; делим на следующую степень, чтобы получить факториал
  39. ; знаменатель дельты посчитан - теперь нам необходимо посчитать сичлитель
  40. FMUL st0, st3 ; умножаем на изначальное значение аргумента - получаем следующую степень
  41. FMUL st0, st3 ; умножаем на изначальное значение аргумента - получаем следующую степень
  42. FMUL st0, st6 ; умножаем полученное значение на -1
  43. FXCH st1 ; дельта посчитана и установлена на своё место
  44. ; Теперь необходимо посчитать следующее значение
  45. FXCH st5 ; перемещаем следующее значение на вершину стека для пересчёта
  46. FADD st0, st1 ; Прибавляем очередной шаг (дельту) к текущему значению - получаем следующее
  47. FXCH st5 ; устанавливаем следующее значение на место
  48. JMP generate_answer ; прыгаем обратно на условие цикла
  49.  
  50. main_func:
  51. FINIT ; инициализация сопроцессора
  52.  
  53. ; заполняем нужные регистры в FPU нулями (нужно, чтобы безболезненно реализовать алгоритм полностью на FPU)
  54. FLDZ
  55. FLDZ
  56. FLDZ
  57. FLDZ
  58. FLDZ
  59. FLDZ
  60. FLDZ
  61. ; теперь наш стек полностью состоит из 0 - для поддержания порядка стека
  62. ; будем пользоваться не FLD, который пихает на верх стека значение и всё сдвигает,
  63. ; а сложение, которое ничего сдвигать не будет
  64. FADD [minus_one] ; загружаем -1
  65. FXCH st6 ; ставим -1 на место
  66. FADD [x] ; загрузка в вершину стека параметра синуса
  67. FXCH st3 ; ставим значение параметра в его место на стеке
  68. FADD [x] ; загрузка в вершину стека значение ряда на данный момент
  69. FXCH st4 ; ставим значение параметра в его место на стеке
  70. FADD [one] ; загружаем в веришину стека значение степени на данный момент
  71. FXCH st2 ; ставим значение степени на её место на стеке
  72. ; Далее нам нужно предподсчитать дельту
  73. ; для начала посчитаем числитель x^3
  74. FADD [x] ; начинаем подсчёт дельты
  75. FMUL st0, st3 ; возводим числитель в квадрат
  76. FMUL st0, st3 ; возводим числитель в куб
  77. ; теперь идём считатть знаменатель 3!
  78. FXCH st2 ; меняем местами с текущей степенью
  79. FADD [one] ; увеличиваем степень на единицу
  80. FXCH st2 ; меняем обратно
  81. FDIV st0, st2 ; делим на степень
  82. ; нужно повторить, чтобы посчитать факториал
  83. FXCH st2 ; меняем местами недосчитанную дельту и степень
  84. FADD [one] ; добавляем единицу к степени
  85. FXCH st2 ; загружаем степень на её законное место
  86. FDIV st0, st2 ; делим на следующую степень, чтобы получить факториал
  87. FMUL st0, st6 ; умножаем полученное значение на -1
  88. FXCH st1 ; дельта посчитана и установлена на своё место
  89. FADD [x] ; начинаем подсчёт следующего значения степенного ряда
  90. FADD st0, st1 ; Прибавляем очередной шаг (дельту) к текущему значению - получаем следующее
  91. FXCH st5 ; устанавливаем следующее значение на место
  92. ;теперь переходим к написанию самого цикла, подсчитывающего знчение
  93. JMP generate_answer ; входим в начало цикла
  94.  
  95. print_answer:
  96. FXCH st5 ; пушим следующее значение ряда на верх стека, чтобы вывести в качестве ответа
  97. FSTP [result] ; выгружаем ответ
  98.  
  99. cinvoke sprintf,res_string,fmt_string, dword[x],dword[x+4], dword[x],dword[x+4], dword[result],dword[result+4]
  100. cinvoke MessageBox,0,res_string,"Сложение двух 'плавающих' чисел двойной точности", 0
  101. ;cinvoke ExitProcess, 0 ; выход из программы с кодом возврата 0
  102.  
  103. .data ; data readable writable
  104.  
  105. fmt_string db "Первое 'плаваюшее' число= %f , второе= %f , их сумма= %f",0
  106. res_string db 256 dup(?) ; строка результата форматирования
  107. x dq 3.14 ; первое слагаемое (формат двойной точности - 4 слова)
  108. pow dq 1.0 ; степень
  109. one dq 1.0 ; просто единица
  110. minus_one dq -1.0 ; просто -1
  111. eps dq 0.00005; значение эпсилона (по нему понимаем точность и когда следует остановиться)
  112. result dq ? ; результат сложения (формат двойной точности)
  113.  
  114. data import ; импортируем стандартные функции Windows
  115. library user32, 'USER32.DLL', msvcrt, 'MSVCRT.DLL', kernel32, 'KERNEL32.DLL', shell32, 'SHELL32.DLL'
  116. import KERNEL32, ExitProcess, 'ExitProcess', GetCommandLine, 'GetCommandLineA'
  117. import user32, MessageBox, 'MessageBoxA'
  118. import msvcrt, sprintf, 'sprintf', sscanf, 'sscanf'
  119. end data
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement