1

The code below is an assembly code to read and write a single floating point number using scanf and printf.

extern scanf
extern printf

section .data
    x   dq  0.0
    fmts    db  "%lf", 0
    fmtp    db  "%lf", 0xA, 0

section .bss

section .text
    global main

main:
push    rbp

    ;push   rax
    ;push   rax
    mov rdi,    fmts ;scanf format
    mov rsi,    x    ;The address of the variable
    call    scanf

    mov rdi,    fmtp ;printf format
    movq    xmm0,   qword[x] ;The value of the variable
    mov rax,    1
    call    printf

Exit:
pop rbp
    mov rax,    1
    mov rbx,    0
    int 0x80

(To compile and run this code, it's easiest to use gcc: nasm -f elf64 ./a.asm && gcc -o ./a a.o -no-pie && ./a)

This code works fine; but when we uncomment one of the push rax lines, segmentation fault occurs. However, if we uncomment both of the push rax lines, it will work fine again. It seems we either shouldn't push anything on the stack, or at least 128bit. It's worth mentioning that the values of the variables pushed onto the stack (in this case, rax,) will be unchanged.

Can someone explain this behavior? Thanks in advance.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Shayan
  • 345
  • 1
  • 3
  • 13
  • 2
    Good detective work, BTW; made it easy to handle (only took a quick skim to verify it was actually a duplicate of the canonical answer about scanf requiring stack alignment), and the question is a pretty decent [mcve]. Note that loading a `double` is normally done with `movsd`, the FP version of `movq`. They both do exactly the same thing as a load, but performance could possibly differ if the result is used by `addsd` vs. `paddq`. Also, generally `ret` from `main` after using `printf`, don't make a raw exit syscall because that wouldn't flush stdio buffers (e.g. if output isn't a TTY). – Peter Cordes May 25 '21 at 09:34
  • 1
    ([On x64 Linux, what is the difference between syscall, int 0x80 and ret to exit a program?](https://stackoverflow.com/a/67677264)). Also, `int 0x80` in 64-bit code isn't recommended. ([What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730)) – Peter Cordes May 25 '21 at 09:35

0 Answers0