I'm supposed to solve this problem, where I am supposed to calculate the arithmetic mean of x (6) numbers using the CDECL convention:
The function in C looks like this: float average(const float *array, long N, float (*f)(float), long *error);
section .data
array dd 1.5,-100.0,30.0,1.0,-1.0,90.0
array_len dd 6
error dd -1
section .text
average:
push ebp
mov ebp, esp
; condition if array is empty
cmp [ebp 8], dword 0
je .array_zero
; condition if array_len is 0
cmp [ebp 12], dword 0
jle .count_zero
; condition if passed function is null
cmp [ebp 16], dword 0
je .function_zero
; preserving registers
push esi
push edi
mov esi, [ebp 8]
mov ecx, [ebp 12]
; define-ing Quiet NaN (used as a error return value)
QNAN EQU 0x7FFFFFFF
MASK_IS_NAN EQU 0000_0001_0000_0000b
; applying the user-defined function on the numbers
.loop:
push ecx
lodsd
push eax
call dword [ebp 16] ; the pointer to the function is at this address
add esp, 4
pop ecx
fxam
fstsw ax
and ax, 0100_0101_0000_0000b
cmp ax, MASK_IS_NAN
je .is_not_a_number
fstp dword [edi ecx*4 - 4] ; storing the number in edi register
loop .loop
; calculating the arithmetic average
mov ecx, [ebp 12]
fld dword [edi ecx*4 - 4]
dec ecx
.calc:
fld dword [edi ecx*4 - 4]
fadd
loop .calc
fild dword [ebp 12]
fdiv ; the result of the arithmetic average is as defined in CDECL in st0 FPU register
; setting error = 0 and exiting
mov [ebp 20], dword 0
jmp .exit
.is_not_a_number:
mov [ebp 20], dword 8
jmp .error
.array_zero:
cmp [ebp 12], dword 0
jle .array_count_zero
cmp [ebp 16], dword 0
je .array_function_zero
mov [ebp 20], dword 1
jmp .error
.count_zero:
cmp [ebp 8], dword 0
je .array_count_zero
cmp [ebp 16], dword 0
je .count_function_zero
mov [ebp 20], dword 2
jmp .error
.function_zero:
mov [ebp 20], dword 4
jmp .error
.array_count_zero:
cmp [ebp 16], dword 0
je .all_zero
mov [ebp 20], dword 3
jmp .error
.array_function_zero:
cmp [ebp 12], dword 0
jle .all_zero
mov [ebp 20], dword 5
jmp .error
.count_function_zero:
cmp [ebp 8], dword 0
je .all_zero
mov [ebp 20], dword 6
jmp .error
.all_zero:
mov [ebp 20], dword 7
jmp .error
.error:
push dword QNAN
fld dword [esp]
add esp,4
jmp .exit
.exit:
pop edi
pop esi
mov esp, ebp
pop ebp
ret
fn_example:
finit
fld dword [esp 4]
xor ecx,-1
xor edx,-1
xor eax,-1
ret
CMAIN:
push ebp
mov ebp,esp
sub esp,4
; un-mask FPU exceptions
fstcw [esp]
and [esp],word 1111_1111_1110_0000b
fldcw [esp]
push error
push fn_example
push dword [array_len]
push array
call average
add esp,16
mov esp,ebp
pop ebp
ret
I am getting a segmentation fault on the hosted server, where the results are checked, but on my local device, it's working fine.
Any ideas, why the segfault might be caused?
CodePudding user response:
So, I found out that the EDI register (fld dword [edi ecx*4 - 4]
) was causing the segfault since it was not malloc-ed. The weird thing is that in the VSCode debugger it was working properly, but the server-sided compiler had a problem with this.
What I added to the code:
...
mov esi, [ebp 8]
mov ecx, [ebp 12]
; ADDED SNIPET
lea eax, [ecx*4]
push eax
EXTERN malloc
call malloc
add esp, 4
mov edi, eax
mov ecx, [ebp 12]
; ADDED SNIPPET
; define-ing Quiet NaN (used as a error return value)
QNAN EQU 0x7FFFFFFF
...