Сортировка вставки не работает, 32-битная сборка

Я пытаюсь реализовать сортировку вставкой в ​​32-битной сборке в Linux с помощью NASM, и в середине запуска я получаю ошибку сегментации (не говоря уже о том, что по какой-то причине printf печатает случайные значения мусора, я не совсем уверен, почему), здесь это код: раздел.rodata MSG: БД "добро пожаловать в sortMe, пожалуйста, сортируйте меня",10,0 S1: БД "%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 ответа

Решение
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]

Возможно, вы можете опубликовать свой переработанный код как РЕДАКТИРОВАТЬ в своем оригинальном вопросе.

Ваш отредактированный код не решает ВСЕ проблемы, сигнализируемые пользователем 3144770!

Параметры для printf верны, но здесь есть некоторые дополнительные проблемы с вашей подпрограммой printArray.

  1. Поскольку ESI является индексом в массиве слов, вам нужно увеличить его!

    push dword [массив +esi*4]

  2. Уверены ли вы pusha сэкономит 32 бита? Возможно, вам лучше использовать pushad

ps Если вы решите переработать свой код и опубликовать изменения, пожалуйста, добавьте переработанный код после последней строки существующего сообщения. Таким образом, оригинальный вопрос будет иметь смысл для людей, просматривающих его впервые!

Другие вопросы по тегам