Рассмотрим сортировку массива:
.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