MASM排序错误

时间:2013-11-25 05:22:09

标签: masm masm32

我正在使用MASM和Irvine的图书馆进行作业。在程序的这一步中,我正在尝试对接收到的数组进行排序,但是我在实现时遇到了问题。

ordr_array  PROC
    pushad
    mov     ebp, esp
    mov     edx, [ebp+40]   ; array value
    mov     ebx, 0          ; array position
    ; [ebp+36]  ; length of input_n

    mov     eax, [ebp+36]

    ; counts up to ecx
    mov     eax, 0
    looper:
        inc     eax         ; k++
        mov     ecx, eax
        inc     ecx         ; j = k + 1
        inner_looper:
            push    eax     ; we need these registers,
            push    ecx     ; save them
            mov     eax, [edx+4*eax]    ; move our values into our registers for comparison
            mov     ecx, [edx+4*ecx]
            cmp     eax, ecx

            jge     inner_looper_end

            mark: ; array[j] > array[i]
                mov     ebx, ecx ; put the inner counter value (j) to swap with the outer (i)

            inner_looper_end:
                pop     ecx     ; restore registers 
                pop     eax     ; ecx and eax

                inc     ecx
                cmp     ecx, [ebp+36]
                jl      inner_looper    ; if we're done with the inner loop, just fall out 

        looper_end:         ; finish looper

            ; exchange code

            push    [edx+4*eax]
            push    [edx+4*ecx]
            call    exchangeElements

            ; end exchange code

            ; see if we need to go again
            inc     eax
            inc     eax                 ; the '+ 1' then '- 1' was the best way I could think of doing '< result - 1' from memory
            cmp     eax, [ebp+36]
            dec     eax
            jl      looper

    popad
    ret     8
ordr_array  ENDP

调用的交换函数是:

exchangeElements    PROC
    pushad

    mov     eax, [ebp+36]    ;to be swapped
    mov     ebx, [ebp+40]    ;to be swapped

    push    [eax]
    push    [ebx]
    pop     [eax]    ;this should swap it
    pop     [ebx]    ;this should swap it

    popad       
    ret 8
exchangeElements    ENDP

非常感谢正确方向的推动。

1 个答案:

答案 0 :(得分:0)

尝试失败;-)除其他外:

  • 您以inc eax开始外部循环,这意味着您以EAX = 1开始。
  • 您将EAXECX用作元素的索引和值,并感到困惑。
  • 您似乎弄乱了数组的长度及其最后一个索引。
  • exchangeElements会获得相当随机的值,但需要元素的地址和后面的最小值的地址。

我建议先以一种高级编程语言解决该问题,直到算法生效。我想你想编写这样的东西:

PHP-CLI

<?php
$A = "Jacobm001";
$A = str_split ($A, 1);
$L = count($A);

ordr_array ($A,$L);
printf("%s\n",print_r($A,true));


function ordr_array (&$A, $L)
{
    for ($i = 0; $i < ($L-1); ++$i)
    {   $B = $A[$i]; $bb = $i;
        for ($j = ($i+1); $j < $L; ++$j)
        {
            if ($A[$j] < $B)
            {
                $B = $A[$j];
                $bb = $j;
            }
        }
        exchangeElements ($A[$i],$A[$bb]);
    }
}

function exchangeElements (&$A, &$B)
{
    $T = $A;
    $A = $B;
    $B = $T;
}

?>

Python

def ordr_array (A, L):
    # outer loop
    for i in range (0,L-1):
        B = A[i]
        bb = i

        # inner loop
        for j in range (i+1, L):
            if (A[j] < B):
                B = A[j]
                bb = j

        # exchangeElements
        A[i], A[bb] = A[bb], A[i]

A = ['J','a','c','o','b','m','0','0','1']
L = len (A)
ordr_array (A,L)
print (A)

C99

#include <stdio.h>
#include <string.h>

void exchangeElements (char* A, char* B)
{
    char T = *A;
    *A = *B;
    *B = T;
}

void ordr_array (char A[], size_t L)
{
    for (size_t i = 0; i < (L-1); i++)
    {
        char B = A[i];
        size_t bb = i;

        for (size_t j = i+1; j < L; j++)
        {
            if (A[j] < B)
            {
                B = A[j];
                bb = j;
            }
        }

        exchangeElements (&A[i], &A[bb]);
    }
}

int main ( void )
{
    char A[] = "Jacobm001";
    size_t L = strlen (A);

    ordr_array (A, L);

    printf ("%s\n",A);
    return 0;
}

很高兴我在您的个人资料中没有找到Haskell或Brainfuck:-)

如果该算法有效,则可以在汇编器中逐点转换。最好的是,您采用了C程序。恶意语言说C是高级汇编语言。不要忽略所使用的汇编器和库的功能。

MASM和IRVINE32

INCLUDE Irvine32.inc

.DATA
    arr DD 'J','a','c','o','b','m','0','0','1'

.CODE
main PROC
    push LENGTHOF arr                   ; https://docs.microsoft.com/en-us/cpp/assembler/masm/operator-lengthof
    push OFFSET arr                     ; https://docs.microsoft.com/en-us/cpp/assembler/masm/operator-offset?
    call ordr_array

    mov ecx, LENGTHOF arr
    lea esi, arr
    @@:
    lodsd
    call WriteChar                      ; Irvine: Writes a single character in AL to standard output
    loop @B
    mov al, 0Dh                         ; New Line
    call WriteChar

    exit
main ENDP

ordr_array PROC STDCALL, A:PTR, L:DWORD ; STDCALL & arguments forces MASM to produce `RET x`
LOCAL bb:DWORD
    pushad                              ; PUSHAD is elegant, but not effective ;-)
    mov edx, A                          ; Address of array
    dec L                               ; Convert length of array to number of last index

    xor eax, eax
    .WHILE (eax < L)                    ; https://docs.microsoft.com/en-us/cpp/assembler/masm/dot-while
        mov esi, [edx+4*eax]
        mov ebx, esi
        mov ecx, eax
        mov bb, ecx
        .WHILE (ecx < L)                ; Inner loop
            inc ecx
            mov edi, [edx+4*ecx]
            .IF (edi < esi && edi < ebx)    ; Looking for the minimum
                mov ebx, edi                ; Save value of minimum
                mov bb, ecx                 ; Save index of minimum
            .ENDIF
        .ENDW                           ; End of inner loop

        mov ecx, bb
        lea ecx, [edx+4*ecx]            ; B = Address of minimum
        push ecx
        lea ecx, [edx+4*eax]            ; A = Address of outer loop element
        push ecx
        call exchangeElements

;       mov ecx, bb                     ; exchangeElements inline
;       mov [edx+4*eax], ebx
;       mov [edx+4*ecx], esi

        inc eax
    .ENDW                               ; End of outer loop

    popad
    ret                                 ; = `ret 8` due to STDCALL & arguments
ordr_array ENDP

exchangeElements PROC STDCALL USES eax ecx esi edi, A:PTR, B:PTR
    mov esi, A
    mov edi, B
    mov eax, [esi]
    mov ecx, [edi]
    mov [esi], ecx
    mov [edi], eax
    ret                                 ; = `ret 8` due to STDCALL & arguments
exchangeElements    ENDP

END main