07-square-eq.asm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. ;;; Required packages: nasm, gcc
  2. ;;; compile commands:
  3. ;;; nasm -f elf 07-square-eq.asm -o bin/07-square-eq.o
  4. ;;; gcc -m32 -o bin/07-square-eq.out bin/07-square-eq.o
  5. %define SYSCALL_EXIT 1 ; system call sys_exit
  6. %define FLOAT32_SIZE_BYTES 4 ; 4 bytes per float32
  7. section .data
  8. scan_fmt db "%f", 0x0
  9. x1_fmt db "x1 = %f", 0xa, 0x0
  10. x2_fmt db "x2 = %f", 0xa, 0x0
  11. x_fmt db "x = %f", 0xa, 0x0
  12. message_enter_abc db "Please enter coefficients a, b, c of equation ax^2 + bx + c = 0", 0xa, 0x0
  13. result_no_roots db "No roots.", 0xa, 0x0
  14. result_infinite_roots db "Infinite roots", 0xa, 0x0
  15. enter_a_fmt db "a = ", 0x0
  16. enter_b_fmt db "b = ", 0x0
  17. enter_c_fmt db "c = ", 0x0
  18. section .bss
  19. a resb FLOAT32_SIZE_BYTES
  20. b resb FLOAT32_SIZE_BYTES
  21. c resb FLOAT32_SIZE_BYTES
  22. d resb FLOAT32_SIZE_BYTES
  23. x1 resb FLOAT32_SIZE_BYTES
  24. x2 resb FLOAT32_SIZE_BYTES
  25. section .text
  26. extern printf
  27. extern scanf
  28. global main
  29. main:
  30. push message_enter_abc
  31. call printf
  32. add esp, 4
  33. ; printf (enter_a_fmt)
  34. push enter_a_fmt
  35. call printf
  36. add esp, 4
  37. ; scanf (scan_fmt, a)
  38. push a
  39. push scan_fmt
  40. call scanf
  41. add esp, 8
  42. ; printf (enter_b_fmt)
  43. push enter_b_fmt
  44. call printf
  45. add esp, 4
  46. ; scanf (scan_fmt, &b)
  47. push b
  48. push scan_fmt
  49. call scanf
  50. add esp, 8
  51. ; printf (enter_c_fmt)
  52. push enter_c_fmt
  53. call printf
  54. add esp, 4
  55. ; scanf (scan_fmt, &c)
  56. push c
  57. push scan_fmt
  58. call scanf
  59. add esp, 8
  60. cmp DWORD [a], __float32__(0.0)
  61. je .aIsZero
  62. jmp .calcD
  63. .aIsZero:
  64. cmp DWORD [b], __float32__(0.0)
  65. je .abAreZero
  66. push DWORD __float32__(-1.0) ; push -1.0 in evaluation stack
  67. ; take value -1.0 from evaluation stack
  68. fld DWORD [esp] ; stack: [-1]
  69. add esp, 4 ; shift evaluation stack into initial point
  70. fld DWORD [c] ; stack: [-1, c]
  71. fmul ; stack: [-c]
  72. fld DWORD [b] ; stack: [-c, b]
  73. fdiv ; stack: [-c / b]
  74. fstp DWORD [x1] ; stack: [], result written into x1
  75. sub esp, 8 ; reserve stack for a float64 (%f requires float64 in printf)
  76. mov ebx, x1
  77. fld DWORD [ebx] ; load float32 in current stack place (32 bits)
  78. fstp QWORD [esp] ; store float64 (8087 does the conversion from float32 internally)
  79. push x_fmt
  80. call printf
  81. add esp, 12
  82. jmp .done
  83. .abAreZero:
  84. cmp DWORD [c], __float32__(0.0)
  85. je .abcAreZero
  86. jmp .noRoots
  87. .abcAreZero:
  88. push result_infinite_roots
  89. call printf
  90. add esp, 4
  91. jmp .done
  92. .calcD:
  93. fld DWORD [b] ; stack: [b]
  94. fld DWORD [b] ; stack: [b, b]
  95. fmul ; stack: [b * b]
  96. fld DWORD [a] ; stack: [b * b, a]
  97. fld DWORD [c] ; stack: [b * b, a, c]
  98. fmul ; stack: [b * b, a * c]
  99. push DWORD __float32__(4.0) ; push 4.0 in evaluation stack
  100. ; take value 4.0 from evaluation stack
  101. fld DWORD [esp] ; stack: [b * b, a * c, 4]
  102. add esp, 4 ; shift evaluation stack into initial point
  103. fmul ; stack: [b * b, 4 * a * c]
  104. fsub ; stack: [b * b - 4 * a * c]
  105. fstp DWORD [d] ; stack: [], result written into d
  106. push DWORD __float32__(0.0) ; push 0.0 in evaluation stack
  107. ; take value 0.0 from evaluation stack
  108. fld DWORD [esp] ; stack: [b * b, a * c, 4]
  109. add esp, 4 ; shift evaluation stack into initial point
  110. fld DWORD [d]
  111. fcom
  112. mov eax, DWORD 0
  113. fstsw ax
  114. cmp eax, DWORD 0x3100 ; eax = 0x3100 -> less
  115. je .noRoots
  116. jmp .calcRoots
  117. .calcRoots:
  118. ; calculate x1
  119. push DWORD __float32__(2.0) ; push -1.0 in evaluation stack
  120. ; take value 2.0 from evaluation stack
  121. fld DWORD [esp] ; stack: [2]
  122. add esp, 4 ; shift evaluation stack into initial point
  123. fld DWORD [a] ; stack: [2, a]
  124. fmul ; stack: [2 * a]
  125. push DWORD __float32__(-1.0) ; push -1.0 in evaluation stack
  126. ; take value -1.0 from evaluation stack
  127. fld DWORD [esp] ; stack: [2 * a, -1]
  128. add esp, 4 ; shift evaluation stack into initial point
  129. fld DWORD [b] ; stack: [2 * a, -1, b]
  130. fmul ; stack: [2 * a, -b]
  131. fld DWORD [d] ; stack: [2 * a, -b, d]
  132. fsqrt ; stack: [2 * a, -b, sqrt(d)]
  133. fadd ; stack: [2 * a, -b + sqrt(d)]
  134. fld
  135. fdiv ; stack: [(-b + sqrt(d)) / (2 * a)]
  136. fstp DWORD [x1] ; stack: [], result written into x1
  137. ; calculate x2
  138. push DWORD __float32__(2.0) ; push -1.0 in evaluation stack
  139. ; take value 2.0 from evaluation stack
  140. fld DWORD [esp] ; stack: [2]
  141. add esp, 4 ; shift evaluation stack into initial point
  142. fld DWORD [a] ; stack: [2, a]
  143. fmul ; stack: [2 * a]
  144. push DWORD __float32__(-1.0) ; push -1.0 in evaluation stack
  145. ; take value -1.0 from evaluation stack
  146. fld DWORD [esp] ; stack: [2 * a, -1]
  147. add esp, 4 ; shift evaluation stack into initial point
  148. fld DWORD [b] ; stack: [2 * a, -1, b]
  149. fmul ; stack: [2 * a, -b]
  150. fld DWORD [d] ; stack: [2 * a, -b, d]
  151. fsqrt ; stack: [2 * a, -b, sqrt(d)]
  152. fsub ; stack: [2 * a, -b - sqrt(d)]
  153. fld
  154. fdiv ; stack: [(-b - sqrt(d)) / (2 * a)]
  155. fstp DWORD [x2] ; stack: [], result written into x2
  156. ; print result
  157. sub esp, 8 ; reserve stack for a float64 (%f requires float64 in printf)
  158. mov ebx, x1
  159. fld DWORD [ebx] ; load float32 in current stack place (32 bits)
  160. fstp QWORD [esp] ; store float64 (8087 does the conversion from float32 internally)
  161. push x1_fmt
  162. call printf
  163. add esp, 12
  164. sub esp, 8 ; reserve stack for a float64 (%f requires float64 in printf)
  165. mov ebx, x2
  166. fld DWORD [ebx] ; load float32 in current stack place (32 bits)
  167. fstp QWORD [esp] ; store float64 (8087 does the conversion from float32 internally)
  168. push x2_fmt
  169. call printf
  170. add esp, 12
  171. jmp .done
  172. .noRoots:
  173. push result_no_roots
  174. call printf
  175. add esp, 4
  176. jmp .done
  177. .done:
  178. mov eax, SYSCALL_EXIT
  179. mov ebx, 0
  180. int 0x80