如何在程序集x86中对数组进行排序

时间:2017-06-08 18:20:14

标签: sorting assembly x86

我在汇编中排序数组时遇到问题。为了用数字重新排序数组,我有两个函数。第一个是查找最小整数的索引,第二个是交换原始数组。我不知道为什么我的代码不起作用。欣赏很多!

__asm
{
    // YOUR CODE STARTS HERE
        push ebp
        mov ebp, esp

        push edi
        push esi
        push ebx

        mov eax, [ebp + 8] // array
        mov ebx, [ebp + 12] // i 
        mov ecx, [ebp + 16] //j
        mov edx, ebx //index 
BEGIN_LOOP :
        cmp ebx, ecx
        jge END_LOOP
        mov esi, [eax + 4 * ebx]
        mov edi, [eax + 4 * edx]
        cmp esi, edi
        jge CONTINUE
        mov edx, ebx
CONTINUE:
    inc ebx
    jmp BEGIN_LOOP
END_LOOP:
    mov eax, edx
    pop ebx
    pop esi
    pop edi

    mov esp, ebp
    pop ebp
    // YOUR CODE ENDS HERE
    ret
}

代码的另一部分:

void selectionSort (int integer_array[], int array_size)
{
    // YOUR CODE STARTS HERE
        mov eax, [ebp + 12] // array_size
        mov esi, [ebp + 8] // integer_array
        mov edi, 0 // j 
        sub eax, 1
    FORLOOP1: // for (j = 0; j < array_size-1; j++)
        cmp eax, edi
        jl FORLOOP1_END
        mov ebx, [ebp + 12]
        push ebx
        push edi
        push esi
        call findMinIndex
        add esp, 12
        mov ebx, edx
        cmp edi, ebx
        je LABEL
        mov edx, [esi + 4 * ebx]
        mov ecx,[esi + 4 * edi]
        xchg edx, ecx
        mov[esi + 4 * ebx], edx
        mov[esi + 4 * edi], ecx

    LABEL :
        inc edi
        jmp FORLOOP1

    FORLOOP1_END :
        mov[ebp + 8], esi

    // YOUR CODE ENDS HERE
}

1 个答案:

答案 0 :(得分:0)

为什么会出错

您的 selectionSort 例程有一个失败的迭代计数器!
您可以使用这对指令控制循环:

cmp eax, edi
jl FORLOOP1_END

但是 findMinIndex 调用会破坏EAX寄存器中的值。

现在解决方案很简单,因为你根本不需要EAX

FORLOOP1:
    mov ebx, [ebp + 12]   ;Array size
    cmp ebx, edi          ;EDI is current index
    jle FORLOOP1_END      ;"je FORLOOP1_END" would also work fine

要反思的事情

使用

移动EAX findMinIndex 的结果的用途是什么?
END_LOOP:
    mov eax, edx

稍后在 selectionSort 中,您会立即使用EDX吗?

call findMinIndex
add esp, 12
mov ebx, edx     <<<<< This makes more sense written as MOV EBX, EAX

当然,即使这最后一条指令也是多余的,因为您可以在后续指令中直接使用EAX作为索引寄存器。

总结

    mov  ebx, [ebp + 12]   ;Array size
    mov  esi, [ebp + 8]    // integer_array
    xor  edi, edi          // j=0
FORLOOP1:
    cmp  edi, ebx          ;EDI is current index
    jnb  FORLOOP1_END      ;Bail out if current index is not/no longer below array size

    push ebx
    push edi
    push esi
    call findMinIndex
    add  esp, 12
    cmp  edi, eax
    je   LABEL
    mov  edx, [esi + 4 * eax]
    mov  ecx, [esi + 4 * edi]
    mov  [esi + 4 * eax], ecx
    mov  [esi + 4 * edi], edx
LABEL:
    inc  edi
    jmp  FORLOOP1
FORLOOP1_END :
    mov  [ebp + 8], esi     <<<<< What's the use of this one? It's an identity!