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

时间:2014-12-28 21:35:05

标签: linux assembly insertion-sort

我尝试使用NASM在linux中的32位程序集中实现插入排序,并且我在运行中遇到了分段错误(更不用说出于某种原因' printf'打印随机垃圾值,我不完全确定为什么),这是 码:     部分.rodata     MSG:DB"欢迎来到sortMe,请为我排序",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 ; print the sorted one

    mov eax, 1  ;exit system call
    int 0x80

printArray:
    push ebp    ;save old frame pointer
    mov ebp,esp ;create new frame on stack
    pushad      ;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+esi*4]
    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, 0
    mov ebx, 0
    mov esi, [ebp+8] ; the array
    loop loop_1
    loop_1:
        cmp ecx, 0 ; if we're done
        je done_1 ; then done with loop
        mov edx, ecx
        push ecx ; we save len, because loop command decrements ecx
        sub edx, ecx
        mov ecx, [esi+4*edx] ;;;;;; ecx now array[i] ? how do I access array[i] in a similar manner?
        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, 4
            pop dword [edx] ; popping 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

关于printf的事情,我很肯定我应该以相反的方式推送参数(首先是S1,然后是整数,所以它是从左到右,因为我们在调用它时C),如果我切换它们,在我遇到分段错误时根本不会打印任何内容。我不知道该怎么做,它将这些作为输出打印出来:

welcome to sortMe, please sort me
5
16777216
65536
256
1
117440512
458752
1792
7
50331648
196608
768

2 个答案:

答案 0 :(得分:1)

mov ecx, [ebp+12]   ;put len in ecx, our loop variab  

这只会将LEN的地址移动到ECX而不是它的值!您需要添加movzx ecx, byte [ecx]

您还需要定义LEN = 48

loop loop_1  

LOOP在这里做什么用?? 您正在多次混合字节和双字。你需要重做代码。体育

dec ebx ; ebx is now number of times we should go through inner loop  

应该成为

shr ebx,2

这是不正确的,因为您需要地址而不是值。将MOV更改为LEA。

jle done_2
mov edx, [esi+ebx]

也许您可以在原始问题中将重新编写的代码作为编辑发布。

答案 1 :(得分:1)

您编辑的代码未解决user3144770发出的所有问题!

printf 的参数是正确的,但这是 printArray 例程的一些其他问题。

  1. 由于ESI是dword数组中的索引,因此需要对其进行扩展!

    推dword [array + esi * 4]

  2. 您确定pusha会节省32位吗?也许你最好使用pushad

  3. ps如果您决定重新编写代码并发布编辑,请在现有帖子的最后一行之后添加重新设计的代码。通过这种方式,原始问题将继续为第一次观看它的人们带来意义!