fork download
  1. section .data
  2. msg_input db 'Введите выражение (пример: 3+4*2): ', 0
  3. msg_result db 10, 'Результат: ', 0
  4. msg_error db 10, 'Ошибка!', 0
  5. msg_div_zero db 'Деление на ноль', 0
  6. buffer times 256 db 0
  7. num_stack times 20 dq 0 ; Стек для чисел
  8. op_stack times 20 db 0 ; Стек для операторов
  9. num_top dq 0 ; Вершина стека чисел
  10. op_top dq 0 ; Вершина стека операторов
  11.  
  12. section .text
  13. global _start
  14.  
  15. _start:
  16. ; Вывод приглашения
  17. mov rax, 1
  18. mov rdi, 1
  19. mov rsi, msg_input
  20. mov rdx, 35
  21. syscall
  22.  
  23. ; Чтение ввода
  24. mov rax, 0
  25. mov rdi, 0
  26. mov rsi, buffer
  27. mov rdx, 255
  28. syscall
  29.  
  30. ; Инициализация
  31. mov rsi, buffer ; Указатель на ввод
  32. mov qword [num_top], 0 ; Стек чисел пуст
  33. mov qword [op_top], 0 ; Стек операторов пуст
  34.  
  35. ; Главный цикл разбора
  36. process_char:
  37. mov al, [rsi] ; Читаем символ
  38. inc rsi
  39.  
  40. cmp al, 10 ; Конец строки (LF)
  41. je process_remaining_ops
  42. cmp al, ' ' ; Пропускаем пробелы
  43. je process_char
  44.  
  45. ; Если цифра
  46. cmp al, '0'
  47. jb not_digit
  48. cmp al, '9'
  49. ja not_digit
  50.  
  51. ; Преобразуем символ в число
  52. sub al, '0'
  53. mov rbx, rax ; Сохраняем цифру в RBX
  54.  
  55. ; Читаем остальные цифры числа
  56. read_number:
  57. mov al, [rsi]
  58. cmp al, '0'
  59. jb push_number
  60. cmp al, '9'
  61. ja push_number
  62.  
  63. ; RBX = RBX * 10 + новая цифра
  64. imul rbx, 10
  65. sub al, '0'
  66. add rbx, rax
  67. inc rsi
  68. jmp read_number
  69.  
  70. push_number:
  71. ; Помещаем число в стек
  72. mov rax, [num_top]
  73. mov [num_stack + rax*8], rbx
  74. inc qword [num_top]
  75. jmp process_char
  76.  
  77. not_digit:
  78. ; Обработка операторов
  79. cmp al, '+'
  80. je process_op
  81. cmp al, '-'
  82. je process_op
  83. cmp al, '*'
  84. je process_op
  85. cmp al, '/'
  86. je process_op
  87. jmp input_error ; Неизвестный символ
  88.  
  89. process_op:
  90. ; Обработка приоритетов
  91. cmp qword [op_top], 0
  92. je push_op ; Стек операторов пуст
  93.  
  94. ; Сравниваем приоритеты
  95. mov rbx, [op_top]
  96. dec rbx
  97. mov cl, [op_stack + rbx] ; Верхний оператор в стеке
  98.  
  99. ; Приоритет текущего оператора (AL)
  100. call get_priority
  101. mov dl, al
  102.  
  103. ; Приоритет оператора в стеке (CL)
  104. mov al, cl
  105. call get_priority
  106.  
  107. ; Если приоритет в стеке >= текущего, выполняем операцию
  108. cmp al, dl
  109. jge apply_operation
  110. jmp push_op
  111.  
  112. apply_operation:
  113. call do_operation
  114. jmp process_op
  115.  
  116. push_op:
  117. ; Добавляем оператор в стек
  118. mov rbx, [op_top]
  119. mov [op_stack + rbx], al
  120. inc qword [op_top]
  121. jmp process_char
  122.  
  123. process_remaining_ops:
  124. ; Выполняем оставшиеся операции
  125. cmp qword [op_top], 0
  126. je print_result
  127. call do_operation
  128. jmp process_remaining_ops
  129.  
  130. print_result:
  131. ; Вывод результата
  132. mov rax, 1
  133. mov rdi, 1
  134. mov rsi, msg_result
  135. mov rdx, 12
  136. syscall
  137.  
  138. mov rax, [num_stack] ; Результат в вершине стека
  139. call print_number
  140.  
  141. ; Перенос строки
  142. mov rax, 1
  143. mov rdi, 1
  144. mov rsi, 10
  145. push rsi
  146. mov rsi, rsp
  147. mov rdx, 1
  148. syscall
  149. pop rsi
  150.  
  151. mov rax, 60
  152. xor rdi, rdi
  153. syscall
  154.  
  155. ; --- Процедуры ---
  156.  
  157. get_priority:
  158. ; Возвращает приоритет оператора в AL
  159. cmp al, '+'
  160. je .low
  161. cmp al, '-'
  162. je .low
  163. cmp al, '*'
  164. je .high
  165. cmp al, '/'
  166. je .high
  167. mov al, 0
  168. ret
  169. .low:
  170. mov al, 1
  171. ret
  172. .high:
  173. mov al, 2
  174. ret
  175.  
  176. do_operation:
  177. ; Извлекаем оператор
  178. dec qword [op_top]
  179. mov rbx, [op_top]
  180. mov al, [op_stack + rbx]
  181.  
  182. ; Извлекаем операнды
  183. dec qword [num_top]
  184. mov rbx, [num_top]
  185. mov rcx, [num_stack + rbx*8] ; Правый операнд
  186.  
  187. dec qword [num_top]
  188. mov rbx, [num_top]
  189. mov rax, [num_stack + rbx*8] ; Левый операнд
  190.  
  191. ; Выполняем операцию
  192. cmp al, '+'
  193. je .add
  194. cmp al, '-'
  195. je .sub
  196. cmp al, '*'
  197. je .mul
  198. cmp al, '/'
  199. je .div
  200.  
  201. .add:
  202. add rax, rcx
  203. jmp .store_result
  204. .sub:
  205. sub rax, rcx
  206. jmp .store_result
  207. .mul:
  208. imul rcx
  209. jmp .store_result
  210. .div:
  211. cmp rcx, 0
  212. je division_error
  213. cqo
  214. idiv rcx
  215.  
  216. .store_result:
  217. mov [num_stack + rbx*8], rax
  218. inc qword [num_top]
  219. ret
  220.  
  221. print_number:
  222. ; Вывод числа из RAX
  223. mov rbx, 10
  224. xor rcx, rcx ; Счётчик цифр
  225.  
  226. .div_loop:
  227. xor rdx, rdx
  228. div rbx
  229. add dl, '0'
  230. push rdx
  231. inc rcx
  232. test rax, rax
  233. jnz .div_loop
  234.  
  235. .print_loop:
  236. pop rdx
  237. mov [msg_result + 12], dl ; Используем буфер для вывода
  238. mov rax, 1
  239. mov rdi, 1
  240. mov rsi, msg_result + 12
  241. mov rdx, 1
  242. syscall
  243. loop .print_loop
  244. ret
  245.  
  246. division_error:
  247. mov rax, 1
  248. mov rdi, 1
  249. mov rsi, msg_error
  250. mov rdx, 8
  251. syscall
  252.  
  253. mov rax, 1
  254. mov rdi, 1
  255. mov rsi, msg_div_zero
  256. mov rdx, 14
  257. syscall
  258. jmp exit
  259.  
  260. input_error:
  261. mov rax, 1
  262. mov rdi, 1
  263. mov rsi, msg_error
  264. mov rdx, 8
  265. syscall
  266. jmp exit
Success #stdin #stdout 0s 5324KB
stdin
Standard input is empty
stdout
Введите выражение (
Оши�