diff --git a/src/hw_4-1_sort/README.md b/src/hw_4-1_sort/README.md new file mode 100644 index 0000000..4333dcf --- /dev/null +++ b/src/hw_4-1_sort/README.md @@ -0,0 +1,21 @@ +# Инструкция по сборке + +Домашнее задание 4.1 "Оптимальная" сортировка + +1. Откройте терминал и перейдите в директорию с файлами приложения +2. Выполните команду компиляции: +```console +gcc -o sort_app с_4-1_sort.c sort.s +``` +3. Запустите программу: +```console +./sort_app +``` +### Использование +1. Введите целые числа, разделённые пробелами (не более 100 чисел) +2. Нажмите Enter для завершения ввода +3. Программа выведет осортированный массив +4. Код возврата будет содержать количество элементов, изменивших свою позицию. Посмотреть его можно командой: +```console +echo $? +``` diff --git a/src/hw_4-1_sort/c_4-1_sort.c b/src/hw_4-1_sort/c_4-1_sort.c new file mode 100644 index 0000000..cd9633c --- /dev/null +++ b/src/hw_4-1_sort/c_4-1_sort.c @@ -0,0 +1,44 @@ +#include + +extern int sort(int* arr, int n); + +int main() +{ + int arr[100]; + int n = 0; + int num; + char c; + + // сохранение чисел в массив до 100 или до конца строки (т.к. в условии "не более 100") + while (n < 100) { + // пытаемся прочитать число + int result = scanf("%d", &num); + if (result == 1) { + arr[n] = num; + n++; + } else { + // если не число, проверяем конец строки + scanf("%c", &c); + if (c == '\n') + break; + continue; + } + + // проверяем следующий символ + int next_char = getchar(); + if (next_char == '\n') { + break; // если конец строки - завершаем ввод + } + if (next_char != EOF) { + ungetc(next_char, stdin); // возвращаем символ обратно в поток + } + } + int changed = sort(arr, n); + + for (int i = 0; i < n; i++) + printf("%d ", arr[i]); + + printf("\n"); + + return changed; +} diff --git a/src/hw_4-1_sort/sort.s b/src/hw_4-1_sort/sort.s new file mode 100644 index 0000000..4c38e6c --- /dev/null +++ b/src/hw_4-1_sort/sort.s @@ -0,0 +1,91 @@ +.global sort +sort: + push %rbp + mov %rsp, %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + + # выделение памяти на стеке для массива + sub $100, %rsp + + # инициализация массива + mov $100, %r12 # максимальный размер массива + lea (%rsp), %r13 # указатель на массив + xor %rax, %rax # счетчик + +init_loop: + movb $0, (%r13,%rax,1) # обнуление байта + inc %rax + cmp %r12, %rax + jl init_loop + + # сортировка "пузырьком" + mov %rsi, %r8 # n + dec %r8 # n-1 + xor %r9, %r9 # i = 0 + +outer_loop: + cmp %r8, %r9 + jge end_outer + + xor %r10, %r10 # j = 0 + mov %r8, %r11 + sub %r9, %r11 # n-i-1 + +inner_loop: + cmp %r11, %r10 + jge end_inner + + # сравнение arr[j] и arr[j+1] + mov (%rdi,%r10,4), %eax # arr[j] + mov 4(%rdi,%r10,4), %ebx # arr[j+1] + + cmp %ebx, %eax + jle no_swap + + # обмен элементов + mov %ebx, (%rdi,%r10,4) + mov %eax, 4(%rdi,%r10,4) + + # установка флагов для перемещенных элементов + lea (%rsp), %rcx + movb $1, (%rcx,%r10,1) + movb $1, 1(%rcx,%r10,1) + +no_swap: + inc %r10 + jmp inner_loop + +end_inner: + inc %r9 + jmp outer_loop + +end_outer: + # подсчет количества элементов, изменивших позицию + xor %rax, %rax # счетчик + xor %rcx, %rcx # индекс + +count_loop: + cmp %rsi, %rcx + jge end_count + movb (%rsp,%rcx,1), %dl + test %dl, %dl + jz skip + inc %rax +skip: + inc %rcx + jmp count_loop + +end_count: + # эпилог функции + add $100, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret