首页 文章

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

提问于
浏览
0

我正在尝试使用NASM在Linux中实现32位汇编中的插入排序,并且我在运行中遇到了分段错误(更不用说由于某种原因'printf'打印随机垃圾值,我不完全确定原因),这里是代码:section .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 回答

  • 1

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

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

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

    推dword [array esi * 4]

    • 你确定 pusha 会节省32位吗?也许你最好用 pushad

    ps如果您决定重新编写代码并发布编辑,请 add the reworked code after the last line of the existing post . 通过这种方式,原始问题将继续为第一次观看它的人们带来意义!

  • 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]
    

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

相关问题