Home > OS >  Assembly - calculating arithmetic mean - segmentation fault
Assembly - calculating arithmetic mean - segmentation fault

Time:05-06

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
...
  • Related