'I want to call scanf but I still don't understand after doing research

I am trying to get scanf to work. I've been looking at past posts and I am not sure what I am doing wrong. I am able to enter a number but it always segfaults before the next line executes. I think the issue lies on me not understanding how to align the stack to be in multiples of 16.

I keep getting "no such file or directory" a thousand times before it lets the user ask for input. I am not sure if this relates to the issue but just something to point out.

Keep in mind, I am also calling scanf in a loop.

I currently want to store 3 things in the stack: 2 arguments (of the current function, not scanf's) + 1 integer (place to store user input).

Here is what I have so far:

    sub $48, %rsp # allocate space for rdi, rsi, input in multiples of 16
    mov %rdi, 24(%rsp) # store first arg
    mov %rsi, 8(%rsp) # store second arg
    push $0 # %rsp stores the user input, initialized as 0.
    ...
loop:
    mov $0, %rax
    mov $stringFormat, %rdi
    mov %rsp, %rsi
    call scanf
    ...

Here is what the stack looks like before scanf

(gdb) x/12w $rsp
0x7fffffffdfa0: 0       0       4199021 0
0x7fffffffdfb0: 800     0       4198944 0
0x7fffffffdfc0: 5       0       4198480 0


Solution 1:[1]

Below you find an example written in Intel Assembler (not gcc), which reads a number using scanf and then outputs the number using printf. I didn't add any kind of error checking just to keep the example clean. If I write assembler programs, I usually use nasm/sasm, but it shouldn't be magic to convert it into any other dialect.

; when using SASM, the next, commented out, include will be helpful
; %include "/usr/share/sasm/include/io64.inc"

default rel

section .data
    align 8
    fmt    db "%d",0      ; format for reading an int, zero terminated
    prtfmt db "%d", 10, 0 ; format for printing ending with nl, zero terminated
    
section .bss
    target resq 1         ; a quad to store the result    
    
section .text
global CMAIN

scanfcall:
    push rbp              ;
    mov  rbp, rsp         ; mainly for stack alignment
    
    lea  rdi, [fmt]
    lea  rsi, [target]
    xor  rax, rax         ; this sets the number of floating point arguments to zero
    call scanf
    pop  rbp
    ret

CMAIN:
    push rbp
    mov  rbp, rsp          ; for correct debugging
    
    call scanfcall
    
    ; check if read correctly
    lea  rdi, [prtfmt]
    mov  rsi, qword [target]
    xor  eax, eax         ; set al to zero to indicate no floating point arguments
    call printf
    
    pop  rbp              ; clean up stack
    xor  rax, rax         ; set exit code to zero
    ret

Since you want to use scanf somewhere in a function, so did I.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1