插入排序不起作用 - 32位组装

时间:2015-01-23 11:16:53

标签: assembly 32-bit insertion-sort

我尝试使用NASM在Linux中的32位程序集中实现插入排序,但出了点问题。 这是代码:

section .rodata
MSG:    DB  "welcome to sortMe, please sort me",10,0
S1: DB  "%d",10,0 ; 10 = '\n' , 0 = '\0' 

section .data

array   DD 5,1,7,3,4,9,12,8,10,2,6,11   ; unsorted array
len DB 12   

section .text
    align 16
    global main
    extern printf

main:
    push MSG    ; print welcome message
    call printf
    add esp,4   ; clean the stack 

    call printArray ;print the unsorted array

    ;parameters
    ;push len
    ;push array
    mov eax, len
    mov ebx, array
    push eax
    push ebx

    call myInsertionSort
    call printArray

    mov eax, 1  ;exit system call
    int 0x80

printArray:
    push ebp    ;save old frame pointer
    mov ebp,esp ;create new frame on stack
    pusha       ;save registers

    mov eax,0
    mov ebx,0
    mov edi,0

    mov esi,0   ;array index
    mov bl, byte [len]
    add edi,ebx ; edi = array size

print_loop:
    cmp esi,edi
    je print_end
    push dword [array+4*esi]
    push S1
    call printf
    add esp, 8  ;clean the stack
    inc esi
    jmp  print_loop
print_end:
    popa        ;restore registers
    mov esp,ebp ;clean the stack frame
    pop ebp     ;return to old stack frame
    ret

myInsertionSort:
    push ebp
    mov ebp, esp
    push ebx
    push esi
    push edi
    mov ecx, [ebp+12]
    movzx ecx, byte [ecx]   ;put len in ecx, our loop variable
    mov eax, 4 ; size of one spot in array, one byte
    mov ebx, 0
    mov esi, [ebp+8] ; the array
    loop loop_1
    loop_1:
        cmp eax, ecx ; if we're done
        jge done_1 ; then done with loop
        push ecx ; we save len, because loop command decrements ecx
        mov ecx, [esi+eax] ; ecx now array[i]
        mov ebx, eax
        shr ebx, 2 ; number of times for inner loop
        loop_2:
            cmp ebx, 0 ; we don't use loop to not affect ecx so we use ebx and compare it manually with 0
            jl done_2
            cmp [esi+ebx], ecx ;we see if array[ebx] os ecx so we can exit the loop
            jle done_2
            lea edx, [esi+ebx]
            push dword [edx] ; pushing our array[ebx]
            add edx, eax
            pop dword [edx] ; poping the last one
            dec ebx ; decrementing the loop iterator
            jmp loop_2 ; looping again
        done_2:
            mov [esi+ebx+1], ecx
            inc eax ; incrementing iterator
            pop ecx ; len of array to compare now to eax and see if we're done
            jmp loop_1
    done_1:
        pop edi
        pop esi
        pop ebx
        pop ebp ; we pop them in opposite to how we pushed
        ret

该计划的输出是:

welcome to sortMe, please sort me
5
1
7
3
4
9
12
8
10
2
6
11

到目前为止它是未排序的数组,然后程序输出:

327681
1280
0
5
4
9
12
8
10
2
6
11

任何线索为什么会发生这种情况?问题出在哪儿?我经历了gdb,但不清楚为什么数组如下。排序或打印有问题吗?

1 个答案:

答案 0 :(得分:0)

在你call myInsertionSort之后,你仍然需要用add esp,8清理堆栈! 退出系统调用也使用EBX。

排序或打印有问题吗?打印工作正常,但您可以稍微清理一下代码。
没有必要使用经典的prolog / epilog,清除EAX也没用。 在 printArray pusha/popa更改pushad/popad

我认为 myInsertionSort 的代码是无法实现的。这是我的插入排序版本:

myInsertionSort:
 pushad                  ;This uses 32 bytes on the stack
 mov     ebp,esp
 mov     ebx,[ebp+32+4]  ;Address of array
 mov     ecx,[ebp+32+8]  ;Address of len
 movzx   ecx,byte [ecx]  ;len
 sub     ecx,1
 jbe     .exit           ;Nothing to sort
 xor     edi,edi         ;Index of candidate
.start:
 inc     edi 
 mov     eax,[ebx+edi*4] ;Value of candidate
 xor     esi,esi         ;Index within the underlying elements
.find:
 cmp     [ebx+esi*4],eax
 jg      .insert
 add     esi,1
 cmp     esi,edi
 jb      .find
 jmps    .next           ;No insertion needed
.insert:
 xchg    [ebx+esi*4],eax
 add     esi,1
 cmp     esi,edi
 jb      .insert
 mov     [ebx+esi*4],eax
.next:
 cmp     edi,ecx
 jb      .start
.exit:
 popad
 ret