Search code examples
cprintfx86-64nasm

How do I print a command line argument using printf in assembly?


I'm trying to print the first argument to my 64-bit NASM program. I'm getting Segmentation fault (core dumped).

; L26.asm
section .data
    fmt db '%s', 10, 0

section .text
    global main
    extern printf

main:
    mov rdi, fmt
    ; +8 to skip the first argument, which is the program name
    mov rsi, [rsi + 8]
    xor rax, rax
    call printf

    ; Return from the main function
    ret

I'm creating an executable like so:

nasm -f elf64 -o L26.o L26.asm && gcc -no-pie -o L26 L26.o

And running like so:

./L26 foo

I'm very new to assembly (and C). Answers online and ChatGPT are making it seem like it should be this simple to print arguments (just offsetting rsi). I'd appreciate any guidance.


Solution

  • You should align the stack to 16-byte boundary before calling 64-bit functions. Otherwise, some functions that assumes this 16-byte boundary and using some SSE instructions (like movaps) may fail.

    Assuming your function is called with 16-byte aligned stack, a 8-byte return address should be pushed by the call, so you should add another 8-byte placeholder on the stack to achieve 16-byte alignment.

    main:
        sub rsp, 8 ; add this (stack alignment)
        mov rdi, fmt
        ; +8 to skip the first argument, which is the program name
        mov rsi, [rsi + 8]
        xor rax, rax
        call printf
    
        ; Return from the main function
        add rsp, 8 ; add this (cleanup)
        ret