1

I'm trying to read floating point input for array using loop and then printing the array. After reading n values, it gives segmentation fault. I can't figure out what is wrong. How can i correct the error?

%macro exit 0
    mov rax,60
    mov rdi,0
    syscall
%endmacro
extern printf 
extern scanf
;-------------------------------------------
section .data
    nfmt db "%d",0
    nfmtout db "%d",10,0
    formatsf db "%lf",0
    formatpf db "%lf",10,0
;-------------------------------------------
section .bss
    n resq 1
    array resq 10
;-------------------------------------------
section .code
global main
main:

    push rbp            ;creating stack frame
    mov rbp, rsp

;read no of elements in array n 
    mov rdi,nfmt
    mov rsi,n
    mov rax,0           ;no of floating pt params
    call scanf


; read elements
    mov rcx,[n]
    mov r8,0
    mov rbx,array
back:   
    push rcx                
    mov rdi,formatsf
    lea rsi, [rbx+r8*8]     
    mov rax,0
    call scanf
    add r8,1
    pop rcx 
    loop back


    xor rax,rax

;print the array    
    mov rcx,[n]
    mov r8,0
    mov rbx,array
back2:
    push rcx    
    mov rdi,formatpf
    movq xmm0, [rbx+r8*8]
    mov rax,1
    call printf
    add r8,1
    pop rcx
    loop back2              


    mov rsp,rbp         ;destroying stack frame
    pop rbp
    exit

Output of the program

5
12.0
12.2
158.9
156.3
256.7
Segmentation fault (core dumped)

When I change the format specifiers to read integer values the output is strange.

; read elements
    mov rcx,[n]
    mov r8,0
    mov rbx,array
back:   
    push rcx                
    mov rdi,nfmt       ;format specifier changed
    lea rsi, [rbx+r8*8]     
    mov rax,0
    call scanf
    add r8,1
    pop rcx 
    loop back


    xor rax,rax

;print the array    
    mov rcx,[n]
    mov r8,0
    mov rbx,array
back2:
    push rcx    
    mov rdi,nfmtout      ;format specifier changed
    mov rsi, [rbx+r8*8]  ;xmm0 register replaced by rsi
    mov rax,0
    call printf
    add r8,1
    pop rcx
    loop back2      

Output after making above changes

5
12
45
845
965
123
12
123
123
123
123
welkin
  • 43
  • 5
  • 2
    You need to make sure the stack is 16-byte aligned prior to calling into any _C_ library function that conforms to the System V 64-bit ABI. You also next to set _AL_ to the number of vector registers you are using to pass arguments. – Michael Petch Mar 20 '18 at 14:38
  • 2
    And glibc x86-64 `printf` specifically *will* fault when called with `al != 0`, because that makes it store XMM0-7 to the stack with `movaps`, which explains your symptoms of working with integer and faulting with FP. And BTW, choose a register other than `rcx` for your loop counter so you don't have to push/pop it. [The `loop` instruction is unfortunately slow and not worth using even in loops that don't clobber rcx](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently) – Peter Cordes Mar 20 '18 at 14:39
  • 1
    I just noticed you set _AL_ as expected in the code. One big thing I missed at first is that you picked `r8` as a register. This is a volatile register that can be clobbered by the functions you call. You need to pick a non-volatile register. Use r12 instead of r8. You can see a list of the registers that get clobbered in the 64-bit System V ABI which is summarized here: https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI – Michael Petch Mar 20 '18 at 15:00
  • Thanks @MichaelPetch. Using r12 instead of r8 solved the problem of reading and printing integers but it's still giving segmentation fault for floating point. – welkin Mar 20 '18 at 16:11
  • 2
    the issue with floating point is stack alignment as I said in my first comment. in fact the quick fix to that is to stop using _RCX_. Use a non-volatile register instead of _RCX_ (Try `r13`). To replace _RC_ you get rid if the `loop` instructions and and replace with `dec r12` `jnz target` .Not using RCX means you can remove to `push RCX` (and pop) on the stack causing it to be not aligned on a 16-byte boundary. – Michael Petch Mar 20 '18 at 16:14
  • @MichaelPetch It worked. Thank you very much. – welkin Mar 20 '18 at 16:19
  • Can you tell me where can i read more about stack alignment? – welkin Mar 20 '18 at 16:21

0 Answers0