Using GDB I see where the segmentation fault happens when it executes "call Mby5" but even debugging it, I don't see why it's getting a segmentation fault when I call the function?
In this code I have two arrays, the first I print to the screen and then the second "ard2" I want to multiply the values of the first one by 5 and then store those new values in "ard2" and then print them. The Mby5 function is where I'm trying to multiply them and store the new values inside ard2, then return and call PrintArray. Here is the complete code and will attach a screenshot of GDB showing when the error hits.
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
Error Picture
Stepped through with GDP and checked register values. Can't seem to find the issue.
I changed Mby5 but using leave and 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
But then my output is
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
If you 'hide' the instructions from Mby5 that don't have to do with the stack, this remains:
push ebp
mov ebp, esp
...
popa ;restore registers
ret
Obviously the popa
isn't matched by an appropriate number of pushed bytes. This leads to the call address being removed from the stack before the ret
is reached, and so the call returns to a dubious address.
You fix this by aligning push and pop instructions, like:
push ebp
pusha
...
popa
pop ebp
ret
or just
pushad
...
popad