section .data
; Масив слів (16-бітні знакові числа)
array dw 10, -5, 20, 3, 0, -12, 8, 4
; Обчислення кількості елементів: (поточна адреса - адреса array) / 2 байти
len equ ($ - array) / 2
section .text
global _start
_start:
; --- Підготовка до виклику процедури ---
; Згідно з умовою, передаємо параметри через стек.
; У 64-бітній системі стек вирівнюється по 8 байт (qword).
push array ; Параметр 1: Адреса початку масиву (буде за адресою rbp + 24)
push len ; Параметр 2: Кількість елементів (буде за адресою rbp + 16)
call bubble_sort ; Виклик процедури сортування
; --- Очищення стеку після виклику ---
; Ми зробили 2 push по 8 байт, отже треба звільнити 16 байт
add rsp, 16
; --- Завершення програми (sys_exit) ---
mov rax
, 60 ; Номер системного виклику для
exit xor rdi, rdi ; Код повернення 0
syscall
; ---------------------------------------------
; Процедура Bubble Sort (Сортування бульбашкою)
; Параметри у стеку:
; [rbp + 16] - Кількість елементів (N)
; [rbp + 24] - Адреса масиву
; ---------------------------------------------
bubble_sort:
; Пролог функції (створення стекового кадру)
push rbp
mov rbp, rsp
; Завантаження параметрів зі стеку в регістри
mov rcx, [rbp + 16] ; RCX = лічильник (кількість елементів)
dec rcx ; Для сортування потрібно N-1 ітерацій зовнішнього циклу
cmp rcx, 0
jle .done ; Якщо масив має 0 або 1 елемент, виходимо
mov rbx, [rbp + 24] ; RBX = базова адреса масиву
.outer_loop:
push rcx ; Зберігаємо лічильник зовнішнього циклу
; Налаштування внутрішнього циклу
; Ми будемо йти від початку до (N-1 - поточний прохід)
; Але для спрощення бульбашки можна проходити весь поточний діапазон
mov rdx, rcx ; RDX буде лічильником внутрішнього циклу
xor rsi, rsi ; RSI = індекс (0), використовуємо для непрямої адресації
.inner_loop:
; Порівняння елементів масиву: array[i] та array[i+1]
; Використовуємо непряму адресацію: [база + індекс * 2] (бо слово = 2 байти)
mov ax, [rbx + rsi*2] ; Завантажуємо поточне слово
cmp ax, [rbx + rsi*2 + 2] ; Порівнюємо з наступним словом
jle .no_swap ; Якщо порядок правильний (<=), не міняємо
; Обмін елементів (Swap)
mov di, [rbx + rsi*2 + 2] ; Тимчасове збереження наступного елемента
mov [rbx + rsi*2 + 2], ax ; Записуємо поточний на місце наступного
mov [rbx + rsi*2], di ; Записуємо збережений на місце поточного
.no_swap:
inc rsi ; Переходимо до наступної пари
dec rdx ; Зменшуємо лічильник внутрішнього циклу
jnz .inner_loop ; Якщо не 0, повторюємо
pop rcx ; Відновлюємо лічильник зовнішнього циклу
loop .outer_loop ; Зменшує RCX і переходить, якщо не 0
.done:
; Епілог функції
mov rsp, rbp ; Відновлення вказівника стеку
pop rbp ; Відновлення попереднього RBP
ret