fork download
  1. section .data
  2. ; Масив слів (16-бітні знакові числа)
  3. array dw 10, -5, 20, 3, 0, -12, 8, 4
  4. ; Обчислення кількості елементів: (поточна адреса - адреса array) / 2 байти
  5. len equ ($ - array) / 2
  6.  
  7. section .text
  8. global _start
  9.  
  10. _start:
  11. ; --- Підготовка до виклику процедури ---
  12. ; Згідно з умовою, передаємо параметри через стек.
  13. ; У 64-бітній системі стек вирівнюється по 8 байт (qword).
  14.  
  15. push array ; Параметр 1: Адреса початку масиву (буде за адресою rbp + 24)
  16. push len ; Параметр 2: Кількість елементів (буде за адресою rbp + 16)
  17.  
  18. call bubble_sort ; Виклик процедури сортування
  19.  
  20. ; --- Очищення стеку після виклику ---
  21. ; Ми зробили 2 push по 8 байт, отже треба звільнити 16 байт
  22. add rsp, 16
  23.  
  24. ; --- Завершення програми (sys_exit) ---
  25. mov rax, 60 ; Номер системного виклику для exit
  26. xor rdi, rdi ; Код повернення 0
  27. syscall
  28.  
  29. ; ---------------------------------------------
  30. ; Процедура Bubble Sort (Сортування бульбашкою)
  31. ; Параметри у стеку:
  32. ; [rbp + 16] - Кількість елементів (N)
  33. ; [rbp + 24] - Адреса масиву
  34. ; ---------------------------------------------
  35. bubble_sort:
  36. ; Пролог функції (створення стекового кадру)
  37. push rbp
  38. mov rbp, rsp
  39.  
  40. ; Завантаження параметрів зі стеку в регістри
  41. mov rcx, [rbp + 16] ; RCX = лічильник (кількість елементів)
  42. dec rcx ; Для сортування потрібно N-1 ітерацій зовнішнього циклу
  43. cmp rcx, 0
  44. jle .done ; Якщо масив має 0 або 1 елемент, виходимо
  45.  
  46. mov rbx, [rbp + 24] ; RBX = базова адреса масиву
  47.  
  48. .outer_loop:
  49. push rcx ; Зберігаємо лічильник зовнішнього циклу
  50.  
  51. ; Налаштування внутрішнього циклу
  52. ; Ми будемо йти від початку до (N-1 - поточний прохід)
  53. ; Але для спрощення бульбашки можна проходити весь поточний діапазон
  54. mov rdx, rcx ; RDX буде лічильником внутрішнього циклу
  55. xor rsi, rsi ; RSI = індекс (0), використовуємо для непрямої адресації
  56.  
  57. .inner_loop:
  58. ; Порівняння елементів масиву: array[i] та array[i+1]
  59. ; Використовуємо непряму адресацію: [база + індекс * 2] (бо слово = 2 байти)
  60.  
  61. mov ax, [rbx + rsi*2] ; Завантажуємо поточне слово
  62. cmp ax, [rbx + rsi*2 + 2] ; Порівнюємо з наступним словом
  63.  
  64. jle .no_swap ; Якщо порядок правильний (<=), не міняємо
  65.  
  66. ; Обмін елементів (Swap)
  67. mov di, [rbx + rsi*2 + 2] ; Тимчасове збереження наступного елемента
  68. mov [rbx + rsi*2 + 2], ax ; Записуємо поточний на місце наступного
  69. mov [rbx + rsi*2], di ; Записуємо збережений на місце поточного
  70.  
  71. .no_swap:
  72. inc rsi ; Переходимо до наступної пари
  73. dec rdx ; Зменшуємо лічильник внутрішнього циклу
  74. jnz .inner_loop ; Якщо не 0, повторюємо
  75.  
  76. pop rcx ; Відновлюємо лічильник зовнішнього циклу
  77. loop .outer_loop ; Зменшує RCX і переходить, якщо не 0
  78.  
  79. .done:
  80. ; Епілог функції
  81. mov rsp, rbp ; Відновлення вказівника стеку
  82. pop rbp ; Відновлення попереднього RBP
  83. ret
Success #stdin #stdout 0s 5324KB
stdin
Standard input is empty
stdout
Standard output is empty