Сортировка вставки не работает, 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.
Поскольку ESI является индексом в массиве слов, вам нужно увеличить его!
push dword [массив +esi*4]
Уверены ли вы
pusha
сэкономит 32 бита? Возможно, вам лучше использоватьpushad
ps Если вы решите переработать свой код и опубликовать изменения, пожалуйста, добавьте переработанный код после последней строки существующего сообщения. Таким образом, оригинальный вопрос будет иметь смысл для людей, просматривающих его впервые!