如何修复选择排序交换访问冲突

时间:2014-07-24 20:24:53

标签: c sorting assembly x86

我目前正在尝试学习汇编,并尝试使用该语言实现基本的排序算法。我认为我已经把它的逻辑降低了,但这也可能是错误的。在任何一种情况下,每当我尝试执行选择排序的交换部分时,我最终都会遇到访问冲突错误。根据我所看到的有关此主题的其他一些问题,我实施交换的方式是有效的(但如果我错了,请再次纠正我)。在任何情况下,假设交换是正确的,导致我的访问违规的原因是什么?

以下是代码:

int _tmain(int argc, _TCHAR* argv[])
{
    char * arr;
    arr = new char[5];
    arr[0] = '2';
    arr[1] = '5';
    arr[2] = '1';
    arr[3] = '3';
    arr[4] = '4';
    int len = 5;

    __asm{
        push eax
        push ebx
        push ecx
        push edx
        push esi
        push edi

        mov eax, 0; //i
        mov ebx, 0; //j
        mov ecx, arr; //the array
        mov edx, 0; //min
        mov esi, len; //array length
        mov edi, len; //array len - 1
        sub edi, 1;
        mov dl, 0;
        mov dh, 0;

OUTERLOOP:
        cmp eax, edi;
        jge END_OUTER;

        mov ebx, eax;
        add ebx, 1;

        mov edx, eax;

INNERLOOP:
        cmp ebx, esi;
        jge END_INNER;

        mov al, byte ptr[ecx+ebx*1];
        mov bl, byte ptr[ecx+edx*1];

        cmp al, bl;
        jl LESS;
        jge GREATER;

LESS:
        mov edx, ebx;
        inc ebx;
        jmp INNERLOOP;
GREATER:
        inc ebx;
        jmp INNERLOOP;

END_INNER:
        cmp edx, eax;
        je PASS;
        jne SWAP;
PASS:
        inc eax;
        jmp OUTERLOOP;
SWAP:
        mov dh, [ecx+eax];
        mov dl, [ecx+edx];

        mov[ecx+eax], dl;
        mov[ecx+edx], dh;
        inc eax;
        jmp OUTERLOOP;

END_OUTER:

        pop edi
        pop esi
        pop edx
        pop ecx
        pop ebx
        pop eax

 }
    for(int i = 0; i < len; i++)
    {
        printf("%c\n", arr[i]);
    }
    return 0;
}

我收到的错误消息如下:

First-chance exception at 0x012f1474 in Clean2.exe: 0xC0000005: Access violation reading location 0x004e67c8.

Unhandled exception at 0x012f1474 in Clean2.exe: 0xC0000005: Access violation reading location 0x004e67c8.

任何建议都将不胜感激,谢谢。

编辑:

我已经改变了我的代码,并尝试使用xchg,这似乎正在伎俩。我从下面的答案中得到了建议,并决定将我将用于字节的寄存器分开。在这一点上,我不再有任何错误。这是更新的代码。

int _tmain(int argc, _TCHAR* argv[])
{
    char temp;
    char * arr;
    arr = new char[5];
    arr[0] = '2';
    arr[1] = '5';
    arr[2] = '1';
    arr[3] = '3';
    arr[4] = '4';
    int len = 5;

    __asm{
        push eax
        push ebx
        push ecx
        push edx
        push esi
        push edi

        mov ebx, arr; //array
        mov ecx, 0; //i
        mov edx, 0; //j
        mov esi, 0; //min
        mov edi, len; //length

OUTERLOOP:
        cmp ecx, edi;
        jge END_OUTER;

        mov edx, ecx;
        add edx, 1;

        mov esi, ecx;

INNERLOOP:
        cmp edx, edi;
        jge END_INNER;

        mov ah, byte ptr[ebx + edx];
        mov al, byte ptr[ebx + esi];

        cmp ah, al;
        jl LESS;
        jge GREATER;

LESS:
        mov esi, edx; 
        inc edx;
        jmp INNERLOOP;

GREATER:
        inc edx;
        jmp INNERLOOP;

END_INNER:
        cmp esi, ecx;
        je PASS;
        jne SWAP;
PASS:
        inc ecx;
        jmp OUTERLOOP;
SWAP:
        xchg al, [ebx + ecx];
        inc ecx;
        jmp OUTERLOOP;

END_OUTER:

        pop edi
        pop esi
        pop edx
        pop ecx
        pop ebx
        pop eax

 }
    for(int i = 0; i < len; i++)
    {
        printf("%c\n", arr[i]);
    }
    return 0;
}

然而现在我在我的阵列中得到1,1,1,3,4而不是1,2,3,4,5。我将继续努力解决这个问题。如果有人能看到有什么问题,请告诉我。谢谢。

1 个答案:

答案 0 :(得分:1)

首先,它看起来你正在使用eax寄存器来处理多个事情。请注意,字节大小的寄存器aleax共享存储。具体来说,当您执行mov al, ...时,会覆盖eax中所用值的低8位。