fork download
  1. section .data
  2. ; Рядки для сортування
  3. w1 db "Orange", 0
  4. w2 db "Apple", 0
  5. w3 db "Banana", 0
  6. w4 db "Apricot", 0
  7. w5 db "Zebra", 0
  8.  
  9. ; Масив вказівників на ці рядки
  10. ; Використовуємо dq, бо адреси 64-бітні
  11. ptr_array dq w1, w2, w3, w4, w5
  12.  
  13. ; Обчислення кількості елементів
  14. arr_len equ ($ - ptr_array) / 8
  15.  
  16. ; Символ нового рядка для виводу
  17. newline db 0xA
  18.  
  19. section .text
  20. global _start
  21.  
  22. _start:
  23. ; --- 1. Сортування ---
  24. ; Передаємо параметри через стек: адресу масиву і довжину
  25. push ptr_array
  26. push arr_len
  27. call bubble_sort
  28. add rsp, 16 ; Очищаємо стек (2 аргументи * 8 байт)
  29.  
  30. ; --- 2. Вивід результату ---
  31. push ptr_array
  32. push arr_len
  33. call print_array
  34. add rsp, 16 ; Очищаємо стек
  35.  
  36. ; --- 3. Вихід з програми ---
  37. mov rax, 60 ; sys_exit
  38. xor rdi, rdi ; status 0
  39. syscall
  40.  
  41. ; ---------------------------------------------------------
  42. ; Процедура виводу (Print Array)
  43. ; Параметри в стеку: [rbp+16] = count, [rbp+24] = array pointer
  44. ; ---------------------------------------------------------
  45. print_array:
  46. push rbp
  47. mov rbp, rsp
  48.  
  49. ; Збережемо регістри, які будемо використовувати (callee-saved)
  50. push rbx
  51. push r12
  52.  
  53. mov rcx, [rbp + 16] ; Кількість слів
  54. mov rbx, [rbp + 24] ; Адреса масиву
  55. xor r12, r12 ; Індекс по масиву (0)
  56.  
  57. .p_loop:
  58. push rcx ; Зберігаємо лічильник циклу
  59.  
  60. ; Отримуємо вказівник на рядок: rsi = array[r12]
  61. mov rsi, [rbx + r12*8]
  62.  
  63. ; --- Рахуємо довжину рядка ---
  64. xor rdx, rdx ; RDX буде лічильником довжини
  65. .calc_len:
  66. cmp byte [rsi + rdx], 0 ; Чи кінець рядка?
  67. je .do_print
  68. inc rdx
  69. jmp .calc_len
  70.  
  71. .do_print:
  72. ; --- Виводимо слово ---
  73. mov rax, 1 ; sys_write
  74. mov rdi, 1 ; stdout
  75. ; rsi вже має адресу рядка
  76. ; rdx вже має довжину
  77. syscall
  78.  
  79. ; --- Виводимо перенос рядка ---
  80. mov rax, 1
  81. mov rdi, 1
  82. mov rsi, newline
  83. mov rdx, 1
  84. syscall
  85.  
  86. pop rcx ; Відновлюємо лічильник циклу
  87. inc r12 ; Наступний елемент масиву
  88. dec rcx
  89. jnz .p_loop
  90.  
  91. ; Відновлюємо регістри
  92. pop r12
  93. pop rbx
  94.  
  95. mov rsp, rbp
  96. pop rbp
  97. ret
  98.  
  99. ; ---------------------------------------------------------
  100. ; Процедура сортування (Bubble Sort)
  101. ; Параметри: [rbp+16] = count, [rbp+24] = array pointer
  102. ; ---------------------------------------------------------
  103. bubble_sort:
  104. push rbp
  105. mov rbp, rsp
  106.  
  107. mov rcx, [rbp + 16] ; Кількість елементів
  108. dec rcx ; N-1
  109. cmp rcx, 0
  110. jle .bs_done
  111.  
  112. mov rbx, [rbp + 24] ; Адреса масиву
  113.  
  114. .bs_outer:
  115. push rcx
  116. mov rdx, rcx ; Лічильник внутрішнього циклу
  117. xor rsi, rsi ; Індекс (0)
  118.  
  119. .bs_inner:
  120. ; Завантажуємо два сусідні вказівники
  121. mov rdi, [rbx + rsi*8] ; Вказівник 1
  122. mov rax, [rbx + rsi*8 + 8] ; Вказівник 2
  123.  
  124. ; Зберігаємо контекст перед викликом порівняння
  125. push rsi
  126. push rdx
  127. push rcx
  128. push rbx
  129. push rax ; Зберігаємо RAX, бо він зміниться
  130.  
  131. mov rsi, rax ; Другий аргумент для str_compare
  132. call str_compare
  133. ; Результат в RAX: >0 якщо рядок1 > рядок2
  134.  
  135. ; Відновлюємо
  136. pop r8 ; Це був старий rax, забираємо в r8, щоб не затерти результат порівняння
  137. pop rbx
  138. pop rcx
  139. pop rdx
  140. pop rsi
  141.  
  142. cmp rax, 0
  143. jle .bs_noswap ; Якщо порядок правильний, пропускаємо
  144.  
  145. ; Обмін (Swap) вказівників у масиві
  146. ; rdi = ptr1, r8 = ptr2 (ми відновили його зі стеку)
  147. mov [rbx + rsi*8], r8
  148. mov [rbx + rsi*8 + 8], rdi
  149.  
  150. .bs_noswap:
  151. inc rsi
  152. dec rdx
  153. jnz .bs_inner
  154.  
  155. pop rcx
  156. loop .bs_outer
  157.  
  158. .bs_done:
  159. mov rsp, rbp
  160. pop rbp
  161. ret
  162.  
  163. ; ---------------------------------------------------------
  164. ; Порівняння рядків strcmp
  165. ; Вхід: RDI = str1, RSI = str2
  166. ; Вихід: RAX > 0 якщо str1 > str2, < 0 якщо str1 < str2
  167. ; ---------------------------------------------------------
  168. str_compare:
  169. xor rax, rax
  170. .cmp_loop:
  171. mov al, byte [rdi]
  172. mov bl, byte [rsi]
  173.  
  174. cmp al, bl
  175. jne .cmp_diff ; Знайшли різницю
  176.  
  177. test al, al ; Чи кінець рядка (0)?
  178. jz .cmp_equal ; Рядки ідентичні
  179.  
  180. inc rdi
  181. inc rsi
  182. jmp .cmp_loop
  183.  
  184. .cmp_diff:
  185. sub al, bl
  186. movsx rax, al ; Розширюємо результат до 64 біт зі знаком
  187. ret
  188.  
  189. .cmp_equal:
  190. xor rax, rax
  191. ret
Success #stdin #stdout 0s 5320KB
stdin
Standard input is empty
stdout
Apple
Apricot
Banana
Orange
Zebra