3

I am new to nasm and I really want to learn how to store a number with user input. I can't get rid of getting segmentation fault when using scanf. I have searched the web, but havent found any solution to this problem. I tried this code but it doesn't work for me.

Can someone explain me what am I doing wrong?

global main

extern printf, scanf

section .data
   msg: db "Enter a number: ",10,0
   format:db "%d",0

section .bss
   number resb 4

section .text
main:
   mov rdi, msg
   mov al, 0
   call printf

   push number
   push format
   call scanf
   ret

Thanks in advance!

Community
  • 1
  • 1
spafrou
  • 548
  • 1
  • 6
  • 19

1 Answers1

5

The x86-64 calling convention doesn't push the arguments generally. Additionally you have to tell a function with variable count of arguments, how many floating point arguments you provide.

This works:

global main
extern printf, scanf

section .data
   msg: db "Enter a number: ",10,0
   format:db "%d",0

section .bss
   number resb 4

section .text
main:
   sub  rsp, 8       ; align the stack to a 16B boundary before function calls

   mov rdi, msg
   mov al, 0
   call printf

   mov rsi, number
   mov rdi, format
   mov al, 0
   call scanf

   add   rsp, 8      ; restore the stack
   ret

BTW: If you want to work with floating point numbers, you have to align the stack to a 16 byte boundary before calling the function.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
rkhb
  • 14,159
  • 7
  • 32
  • 60
  • I find it a little strange that integers don't require stack alignment but floating point does. The floats are passed by register (at least the first eight) so they don't need to be read from the stack. But I guess `printf` pushes/pops them from the stack anyway. – Z boson Nov 12 '14 at 19:33
  • @Zboson: My GDB told me, that the XMM-registers will be stored in a local variable (stack). To store XMM-registers the memory must be aligned, which is obviously not (or not correctly) done by glibc. – rkhb Nov 12 '14 at 19:41
  • I don't understand why it will be stored on the stack the System V AMD64 ABI passes the first eight floats in XMM0-7. – Z boson Nov 12 '14 at 20:00
  • 1
    @Zboson: Gnu moves in mysterious ways. :-) – rkhb Nov 12 '14 at 20:10
  • This code lacks proper 16-byte alignment when making a call to the _C_ library per the AMD64 ABI. – Michael Petch Jun 27 '18 at 20:29
  • And the requirement to 16-byte (or 32-byte alignment depending on what is being passed) isn't dependent on whether you are using floats or not. The C library is free to use aligned SIMD instructions whether dealing with integers or floats. The fact it works with integers is just by luck because of the way the library was written, but that may not always be the case. To be compliant with a particular function written to spec you must ensure proper alignment, not rely on behavior that may be undefined. – Michael Petch Jun 27 '18 at 20:41
  • 1
    @Zboson: printf is a variadic function, and the way gcc generates code for `VA_ARG` etc. is to spill XMM registers to the stack so it can index them, if AL!=0. (glibc's printf is written in C and compiled by gcc). I fixed this answer with sub/add instead of push/pop just to make it most clear for beginners that only RSP matters, not saving / restoring a register. push/pop is generally more efficient, though. – Peter Cordes Jun 27 '18 at 21:08