Search code examples
cassembly64-bitnasm

x64 NASM Assembly extern printf doesn't print anything


I was attempting to write a program that prints every prime number which is smaller than the user input. So I first tried a portion of the program that prints a message that users to induce the user input with printf, but it doesn't print anything. The problematic code is under below:

; Nasm v 2.15.05 (on Linux x64)

extern printf

SYS_EXIT        EQU     0x3C

section .data
        notificationMessage             DB      "Enter the upper limit: ", 0x0
        notificationFormatString        DB      "%s", 0x0

section .text
        global main

        main:
                ; initialize
                push    rbp
                mov     rbp, rsp

                mov     rdi, notificationFormatString
                mov     rsi, notificationMessage
                call    printf    ; it doesn't print anything. why?

                ; end program
                mov     rsp, rbp
                pop     rbp

                mov     rax, SYS_EXIT
                mov     rdi, 0x0
                syscall

(As far as I know, I should put the format string to rdi register and the following messages to rsi and so go on according to the SYSV Calling convention on Linux x64.) I built this Assembly program with the following Makefile.

prime_numbers_linux_x64: prime_numbers_linux_x64.asm
        nasm -f elf64 -o prime_numbers_linux_x64.o prime_numbers_linux_x64.asm
        gcc -o prime_numbers_linux_x64 prime_numbers_linux_x64.o -no-pie

clean:
        rm -f ./prime_numbers_linux_x64
        rm -f ./prime_numbers_linux_x64.o

When I run the program, this shows nothin and immediately finishes.

knightchaser@3rdfr13nds:~/assembly/loop$ ./prime_numbers_linux_x64
knightchaser@3rdfr13nds:~/assembly/loop$

Can you let me know which point I'm doing wrong? Thanks in advance.

My environment is WSL2(Ubuntu 22.04) on Windows 11, 64-bit CPU.


Solution

  • Thanks to @ecm's help, Finally solved. When I use external C libraries on my Assembly code, it's strongly recommended not to use a direct system call of system exit. Using ret(retn in this case.) is encouraged.

    ; Nasm v 2.15.05 (on Linux x64)
    
    extern printf
    
    SYS_EXIT        EQU     0x3C
    
    section .data
            notificationMessage             DB      "Enter the upper limit: ", 0x0
            notificationFormatString        DB      "%s", 0x0
    
    section .text
            global main
    
            main:
                    ; initialize
                    push    rbp
                    mov     rbp, rsp
    
                    mov     rdi, notificationFormatString
                    mov     rsi, notificationMessage
                    call    printf    ; it doesn't print anything. why?
    
                    ; end program
                    mov     rsp, rbp
                    pop     rbp
    
                    ; use this keyword to finish. (or just ret. assembler will code this into one of between retn or retf keyword, according to the situation.)
                    retn
    
                    ; delete
                    ;mov     rax, SYS_EXIT
                    ;mov     rdi, 0x0
                    ;syscall
    

    More reference to read