使用GDB,我看到了当它执行“call Mby5”时分段错误发生的地方,但即使调试它,我也不明白为什么当我调用函数时它会得到分段错误?
在这段代码中,我有两个数组,第一个我打印到屏幕上,然后第二个“ard2”我想把第一个的值乘以5,然后把这些新值存储在“ard2”中,然后打印它们。Mby5函数是我试图把它们相乘并把新值存储在ard2中的地方,然后返回并调用PrintArray。这里是完整的代码,并将附上GDB的屏幕截图,显示错误何时发生。
section .data
msg1: db 'Here are the array element values: ',10, 0
msgL1: equ $-msg1
msg2: db"Here are the new array element values after multiplying by 5! ",10, 0
msgL2: equ $-msg2
ard1: dd 2, 4, 6, 8, 10, 20, 40
ard1L: equ ($-ard1) / 4 ; Number of elments = array length / 4
ard2: dd 0, 0, 0, 0, 0, 0, 0
ard2L: equ ($-ard2) / 4 ; Number of elments = array length / 4
section .text
global _start ; declare _start as a global label
_start:
push ebp ; save ebp for whoever called main function (OS or other program)
mov ebp, esp ; create our new stack frame
mov ecx,msg1 ; print message #1
mov edx,msgL1
call PString
;save array base address in ebx and save size of the array in ecx
mov ebx, ard1
mov ecx, ard1L
;call PrintArray to print the array element
call PrintArray
;print message2
mov ecx, msg2
mov edx, msgL2
call PString
;restore the array address and its size to the stack before calling Mby5 function
mov ebx, ard1
mov ecx, ard1L
call Mby5 **[ERROR HAPPENS WHEN I CALL IT HERE]**
;After multplfying array1 elements by 5 and storing it in ard2 we call PrintArray and pass it ard2
mov ebx, ard2
mov ecx, ard2L
;Call PrintArray
call PrintArray
PrintArray:
section .text
push ebp
mov ebp, esp
top:
mov eax,[ebx] ;move the value of [ebx] to eax
call printDec
call println
add ebx, 4
loop top
mov esp, ebp ; destroy the stack
pop ebp
ret
Mby5:
section .text
push ebp
mov ebp, esp
top1:
mov eax, [ebx] ; access first array element. Move its value to eax
shl eax, 2 ; multiply by 4
add eax, [ebx] ; multiply by 5
mov [ard2 + ebx - ard1], eax ; store the result in array2
add ebx, 4
loop top1
popa ;restore registers
ret
println:
section .data
nl db"", 10
section .text
;save register values of the called function
pusha
mov ecx, nl
mov edx, 1
mov eax, 4
mov ebx, 1
int 80h
;restore the old register values of the called function
popa
ret
PString:
;Save register values of called function
pusha
mov eax, 4 ;use 'write' system call = 4
mov ebx, 1 ;file descriptor 1 = STDOUT
int 80h ;call the kernel
;restore the old register values of the called function
popa
ret
printDec:
section .bss
decstr resb 10;
ct1 resd 1
section .text
pusha ;save all registers
mov dword[ct1], 0 ; assume initially 0
mov edi, decstr ;edi points to dec-string in memory
add edi, 9 ;moved to the last element of string
xor edx, edx
whileNotZero:
mov ebx, 10 ;get ready to divide by 10
div ebx ;divide by 10
add edx,'0' ; convert to ascii char
mov byte[edi], dl ; put it in string
dec edi ;move to next char in string
inc dword[ct1]
xor edx, edx ;clear edx
cmp eax, 0 ;is remainder 0
jne whileNotZero ; keep looping
inc edi ; conversion finish
mov ecx, edi
mov edx, [ct1]
mov eax, 4
mov ebx, 1
int 0x80
popa ;restore registers
ret
错误图片
已使用GDP逐步检查寄存器值。似乎找不到问题。
我改变了Mby5但使用离开和ret
Mby5:
push ebp
mov ebp, esp
mov edi, 0 ; index variable
top1:
mov eax, [ebx] ; access first array element. Move its value to eax
shl eax, 2 ; multiply by 4
add eax, [ebx] ; multiply by 5
mov [ard2 + ebx - ard1], eax ; store the result in array2
add ebx, 4
loop top1
leave ; restore the original stack frame before returning
ret
但是我的输出是
Here are the new array element values after multiplying by 5!
10
20
30
40
50
100
200
10
0
825360384
2356
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
zsh: segmentation fault
1条答案
按热度按时间xfb7svmp1#
如果您从Mby5中“隐藏”与堆栈无关的指令,则仍然是:
显然
popa
没有被适当数量的压入字节匹配。这导致调用地址在到达ret
之前就被从堆栈中删除,因此调用返回到一个可疑的地址。你可以通过调整push和pop指令来解决这个问题,比如:
或者只是