我尝试使用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
答案 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 例程的一些其他问题。
由于ESI是dword数组中的索引,因此需要对其进行扩展!
推dword [array + esi * 4]
您确定pusha
会节省32位吗?也许你最好使用pushad
ps如果您决定重新编写代码并发布编辑,请在现有帖子的最后一行之后添加重新设计的代码。通过这种方式,原始问题将继续为第一次观看它的人们带来意义!