fork download
  1. section .data
  2. ; Входные данные
  3. num1 db 0x12, 0x34, 0x56, 0x78 ; Первое число (4 байта)
  4. num2 db 0x9A, 0xBC, 0xDE, 0xF0 ; Второе число (4 байта)
  5. result times 4 db 0 ; Результат (4 байта)
  6.  
  7. ; Константы
  8. N equ 4 ; Размер чисел в байтах
  9.  
  10. ; Строки для вывода
  11. msg_result db "Результат: ", 0
  12. newline db 10, 0
  13. hex_chars db "0123456789ABCDEF"
  14.  
  15. ; Промежуточные буферы
  16. hex_buffer times (N*2+1) db 0 ; Буфер для hex-строки
  17.  
  18. section .bss
  19. ; Переменные для хранения CF
  20. carry_flag resb 1
  21.  
  22. section .text
  23. global _start
  24.  
  25. ; ============================================
  26. ; Вычитание чисел размером N байтов с учетом знака
  27. ; ============================================
  28.  
  29. _start:
  30. ; Вычитаем num2 из num1 (результат = num1 - num2)
  31. call subtract_big_numbers
  32.  
  33. ; Выводим результат в консоль
  34. call print_result
  35.  
  36. ; Завершаем программу
  37. mov rax, 60 ; sys_exit
  38. xor rdi, rdi ; код 0
  39. syscall
  40.  
  41. ; ============================================
  42. ; Процедура вычитания больших чисел
  43. ; ============================================
  44. subtract_big_numbers:
  45. mov rcx, N ; Счетчик байтов
  46. clc ; Сброс флага переноса (CF = 0)
  47.  
  48. subtract_loop:
  49. mov al, [num1 + rcx - 1] ; Берем байт из num1
  50. sbb al, [num2 + rcx - 1] ; Вычитаем с заемом байт из num2
  51. mov [result + rcx - 1], al ; Сохраняем результат
  52. loop subtract_loop ; Повторяем для всех байтов
  53.  
  54. ; Сохраняем флаг переноса для анализа переполнения
  55. pushf
  56. pop rax
  57. and al, 1 ; Извлекаем только бит CF
  58. mov [carry_flag], al
  59.  
  60. ret
  61.  
  62. ; ============================================
  63. ; Процедура вывода результата
  64. ; ============================================
  65. print_result:
  66. ; Выводим сообщение "Результат: "
  67. mov rsi, msg_result
  68. call print_string
  69.  
  70. ; Конвертируем результат в hex-строку
  71. mov rsi, result
  72. mov rdi, hex_buffer
  73. mov rcx, N
  74. call bytes_to_hex
  75.  
  76. ; Выводим hex-строку
  77. mov rsi, hex_buffer
  78. call print_string
  79.  
  80. ; Выводим перевод строки
  81. mov rsi, newline
  82. call print_string
  83.  
  84. ; Определяем знак результата
  85. call analyze_result
  86.  
  87. ret
  88.  
  89. ; ============================================
  90. ; Конвертация байтов в hex-строку
  91. ; Вход: RSI = указатель на байты
  92. ; RDI = указатель на буфер
  93. ; RCX = количество байтов
  94. ; ============================================
  95. bytes_to_hex:
  96. push rcx
  97. push rsi
  98. push rdi
  99.  
  100. add rdi, rcx ; Начинаем с конца буфера для прямого порядка
  101. add rdi, rcx
  102. mov byte [rdi], 0 ; Нуль-терминатор
  103.  
  104. convert_loop:
  105. dec rdi
  106. mov al, [rsi + rcx - 1]
  107. mov bl, al
  108.  
  109. ; Младшая тетрада
  110. and al, 0x0F
  111. mov al, [hex_chars + rax]
  112. mov [rdi], al
  113. dec rdi
  114.  
  115. ; Старшая тетрада
  116. shr bl, 4
  117. and bl, 0x0F
  118. mov bl, [hex_chars + rbx]
  119. mov [rdi], bl
  120.  
  121. dec rcx
  122. jnz convert_loop
  123.  
  124. pop rdi
  125. pop rsi
  126. pop rcx
  127. ret
  128.  
  129. ; ============================================
  130. ; Анализ и вывод информации о результате
  131. ; ============================================
  132. analyze_result:
  133. ; Проверяем на переполнение (OF)
  134. mov al, [result + N - 1] ; Берем старший байт
  135. test al, 0x80 ; Проверяем знаковый бит
  136. jz positive_result
  137.  
  138. negative_result:
  139. ; Если результат отрицательный
  140. mov rsi, msg_negative
  141. call print_string
  142. jmp check_carry
  143.  
  144. positive_result:
  145. mov rsi, msg_positive
  146. call print_string
  147.  
  148. check_carry:
  149. mov al, [carry_flag]
  150. test al, al
  151. jz no_carry
  152.  
  153. ; Был заем
  154. mov rsi, msg_borrow
  155. call print_string
  156. ret
  157.  
  158. no_carry:
  159. mov rsi, msg_no_borrow
  160. call print_string
  161. ret
  162.  
  163. ; ============================================
  164. ; Вывод строки
  165. ; Вход: RSI = указатель на строку (нуль-терминированную)
  166. ; ============================================
  167. print_string:
  168. push rax
  169. push rdi
  170. push rdx
  171. push rsi
  172.  
  173. ; Вычисляем длину строки
  174. mov rdi, rsi
  175. xor rcx, rcx
  176. not rcx
  177. xor al, al
  178. cld
  179. repne scasb
  180. not rcx
  181. dec rcx
  182.  
  183. ; Выводим строку
  184. mov rax, 1 ; sys_write
  185. mov rdi, 1 ; stdout
  186. mov rdx, rcx ; длина строки
  187. syscall
  188.  
  189. pop rsi
  190. pop rdx
  191. pop rdi
  192. pop rax
  193. ret
  194.  
  195. section .data
  196. msg_positive db " (Положительное число)", 10, 0
  197. msg_negative db " (Отрицательное число, представлено в доп. коде)", 10, 0
  198. msg_borrow db "Был заем (CF=1)", 10, 0
  199. msg_no_borrow db "Заема не было (CF=0)", 10, 0
Success #stdin #stdout 0s 5312KB
stdin
Standard input is empty
stdout
Результат: 7
 (Отрицательное число, представлено в доп. коде)
Был заем (CF=1)