Сортировка массива

Последнее обновление: 02.07.2023

Рассмотрим сортировку массива:

.data
    ; массив для сортировки:
    numbers dword 2, 1, 14, 11
        dword 5, 9, 4, 10
        dword 6, 8, 16, 12
        dword 7, 3, 15, 13
    elemSize = 4    ; размер одного элемента
    numbersLength = ($ - numbers) / elemSize  ; число элементов
    swap byte ? ; swap - индикатор, был ли на предыдущей итерации обмен значениями
.code

; Параметры
; в RCX - адрес массива
; в RDX - количество элементов
sort proc
    dec rdx ; нам надо пройти на 1 цикл меньше, поэтому уменьшаем на 1
; внешний цикл:
outer: 
    mov swap, 0
    xor rbx, rbx    ; RBX = 0 - счетчик проверенных элементов
inner: 
    cmp rbx, rdx    ; пока не сравним все элементы, то есть RBX < RDX
    jnb innerEnd      
    mov eax, [rcx + rbx*elemSize]  ; EAX = numbers[RBX]
    cmp eax, [rcx + rbx*elemSize + elemSize] ; сравниваем, большем ли число из EAX, чем numbers[RBX + 1]
    jna withoutSwap ; если EAX не больше, то переходим к метке withoutSwap
 
    ; если же numbers[RBX] > numbers[RBX + 1], то обмениваем значениями
    mov r8d, [rcx + rbx*elemSize + elemSize]
    mov [rcx + rbx*elemSize + elemSize], eax
    mov [rcx + rbx*elemSize], r8d
    mov swap, 1          ; устанавливаем, что был совершен обмен
withoutSwap:
    inc rbx         ; увеличиваем счетчик элементов
    jmp inner       ; переход для сравнения новой пары элементов
; Если был совершен обмен, то переходим обратно к outer
innerEnd: 
    cmp swap, 1
    je outer
    ret
sort endp

main proc
    lea rcx, numbers
    mov rdx, numbersLength ; 16 элементов в массиве
    call sort

    ; для примера получим последний элемент
    lea rbx, numbers
    mov eax, [rbx + (numbersLength-1) * elemSize ]
    ret
main endp
end

В секции данных определен массив numbers, который будет сортировать, а также длина массива в элементах - numbersLength, размер одного элемента - elemSize и переменная swap - индикатор обмена значениями между элементами. При сравнении если предыдущий элемент больше следующего, мы меняем их местами. Чтобы указать, что обмен был, переменной swap будет присваиваться значение 1. Если обмена не было, то есть предыдущий элемент оказался меньше последующего, то swap будет равно 0.

Затем идет определение функции sort, которая сортирует массив. Предполагается, что адрес массива будет передаваться через регистр RCX, а количество элементов в массиве - через RDX. Поскольку при сортировке пузырьком нам надо провести numbersLength-1 сравнений, то уменьшаем значение RDX на единицу:

dec rdx

На метку outer проецируется внешний цикл. В нем у переменной swap устанавливаем значение 0:

mov swap, 0

И обнуляем регистр RBX, который будет выступать в качестве счетчика сравнений:

xor rbx, rbx

Дальше идет условный внутренний цикл, который проецируется на метку inner. В нем мы сравниваем значения RBX и RDX - количество проведенных сравнений и максимальное количество сравнений.

cmp rbx, rdx
jnb innerEnd

Если значение RBX равно значению RDX, значит все сравнения проведены, и переходим к метке innerEnd.

Если же не все значения сравнены, то в регистр EAX помещаем первый элемент для сравнения (по адресу [rcx + rbx*elemSize] ) и сравниваем его со следующим элементом (по адресу [rcx + rbx*elemSize + elemSize])

mov eax, [rcx + rbx*elemSize] 
cmp eax, [rcx + rbx*elemSize + elemSize]

Если первый элемент оказался меньше, то переходим к метке withoutSwap:

jna withoutSwap

Если же первый элемент оказался больше второго, то обмениваем их значения:

mov r8d, [rcx + rbx*elemSize + elemSize]
mov [rcx + rbx*elemSize + elemSize], eax
mov [rcx + rbx*elemSize], r8d
mov swap, 1

После обмена переменная swap получает значение 1.

Далее на метке withoutSwap увеличиваем счетчик сравнений и переходим обратно к метке inner, пока не сравним все элементы.

withoutSwap:
    inc rbx
    jmp inner

Если сравнены все элементы, срабатывает код после метки innerEnd:

innerEnd: 
    cmp swap, 1
    je outer

Если сравнены все элементы, но произошел обмен, и соответственно переменная swap равна 1, то значит, что еще может потребоваться обмен значений. Поэтому, если swap равна 1, то переходим обратно к метке outer и повторно сравниваем все элементы друг с другом.

Если же swap равна 0, то есть при сравнениях не было не одного обмена, а это значит, что массив уже отсортирован, то выходим из функции.

В процедуре main вызываем процедуру sort, передавая в регистры RCX и RDX адрес массива и количество элементов:

lea rcx, numbers
mov rdx, numbersLength
call sort
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850