0

I am receiving a segmentation fault with the following fragment of code which, I cannot figure out why it would throw a segmentation fault if when doing multiplication it worked as it should. The code is essentially communicating with both the asm and c file to display certain information such as the sum, average, min, max, and multiplication / division for the certain data that is being entered. Below is my fully coded library which has the functions that will be called.

The main issue is when dividing

Here is the following code to show my division process:

#-----------------------------------------------------------------------------------
getStatsExtended:
    ; rdi array of bytes
    ; rsi is a quadword with the value being the number of elements in the array
    ; rdx is the address of a quadword to store the max
    ; rcx is the address of a quadword to store the min
    ; r8  is the address of a quadword to store the sum of the numbers
    ; r9  is the address of a quadword to store the average of the numbers
    ; Stack parameter 1 min*max the minimum number mulitiplied times the maximum
    # Stack parameter 2 max/min the maximum number divided by the minimum number

    ;prologue
    ; push the rbp value to the stack
    ;TBD
     push rbp
    ; save the stack pointer into rbp
    ; TBD
    mov rbp, rsp
    ; save any registers that will be used for calculations
    ; TBD
    push r12
    push r13
     
    ; max
    mov r15, rsi ; set the counter to start at the last value in the array
   
    mov rax, 0x0
    mov al, byte [rdi+r15-1]
    nextMaxE:
    dec r15
    cmp r15, 0x0
    jbe MaxE
    cmp al, byte [rdi+r15-1]
    jb greaterE
    jmp nextMaxE

    greaterE:
    mov al, byte [rdi+r15-1]
    jmp nextMaxE    

    MaxE:
    push rax ; put the value on the stack to pick up later

    ; min
    mov r15, rsi ; set the counter to start at the last value in the array
   
    mov rax, 0x0
    mov al, byte [rdi+r15-1]

    nextMinE:
    dec r15
    cmp r15, 0x0
    jbe MinE
    cmp al, byte [rdi+r15-1]
    ja lesserE
    jmp nextMinE

    lesserE:
    mov al, byte [rdi+r15-1]
    jmp nextMinE

    MinE:
    push rax ; put the value on the stack to pick up later
   
    ; sum
    mov r15, rsi ; set the counter to start at the last value in the array
   
    mov rax, 0x0
    mov al, byte [rdi+r15-1]

    nextSumE:
    dec r15
    cmp r15, 0x0
    jbe SumE
    mov r14b, byte[rdi+r15-1]
    add rax, r14
    jmp nextSumE

    SumE:
    push rax ; put the value on the stack to pick up later
   
    ; ave
    push rdx
    mov rdx, 0x0
    div rsi
    mov qword[r9], rax ; set the return value for ave
    pop rdx
   
    ; pull values from the stack
    pop qword [r8]      ; sum
    pop qword [rcx]     ; min
    pop qword [rdx]     ; max
   
    ; multiply min times max return in 7th parameter
    ; TBD
     mov rax, qword[rcx] ; moving into rax min
     imul qword[rdx] ; multiplying by rdx
     
     mov r12, qword[rbp+16] ; Setting r12 to addres of 7th parameter
     mov qword[r12], rax        ; setting value of rax (mul result) to 7th parameter
     
   
    ; divide max by min return in 8th parameter
    ; TBD
    mov rax, qword[rdx] ; moving max into rax
     xor rdx, rdx           ; zeroing out rdx
    div qword[rcx]           ; dividing by min
   
    call printRAX
   
    mov r13, qword[rbp+24] ; setting r13 to the address of 8th parameter
    mov qword[r13], rax       ; setting value of rax (div result) to 8th parameter
   
    ;epilogue
    ; pop the saved registers
    ; TBD
    pop r13
    pop r12
   
    ; pop the rbp
    ; TBD
    pop rbp
    ret
    
 
  • Can you please explain in detail what this code is supposed to do? How is the caller expected to set up registers/memory when calling it, and how does the caller expect to have results returned? If it's meant to follow C calling conventions, could you provide its declaration, and perhaps equivalent C code? – Nate Eldredge May 01 '21 at 01:08
  • 1
    You should read carefully the descriptions of what the `mul` and `div` instructions do, in particular how they affect `rdx`. Following `mul`, you no longer have the pointer value in `rdx` that you did before. – Nate Eldredge May 01 '21 at 01:12
  • @NateEldredge is there a way to keep the value of rdx the same to be re used in the division? – AssemblyLearner May 01 '21 at 01:15
  • 1
    You can use two-operand `imul` instead which doesn't widen. However you still have to zero `rdx` before dividing, like you did previously. – Nate Eldredge May 01 '21 at 01:20
  • @NateEldredge tried doing imul and tried zeroing out rdx by doing `xor rdx, rdx` before dividing but still get seg fault – AssemblyLearner May 01 '21 at 01:30
  • Show the new code, please. – Nate Eldredge May 01 '21 at 01:30
  • 1
    Your code still uses one-operand imul, not `imul rax, [rdx]` (like I commented on your previous question: [Attempting to store and return a mul and div value](https://stackoverflow.com/posts/comments/119030837)). Read the manual (https://www.felixcloutier.com/x86/imul) and single-step your code in a debugger. – Peter Cordes May 01 '21 at 01:43
  • There's a canonical answer about how to (not) use one-operand mul/imul, to avoid clobbering RDX when you don't care about the high half of the 128-bit product: [Why is imul used for multiplying unsigned numbers?](https://stackoverflow.com/q/42587607) – Peter Cordes May 01 '21 at 01:46

0 Answers0