0

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.

KnightChaser
  • 143
  • 1
  • 9
  • Could be buffering, try returning from `main` to the RTL's exit handler. – ecm Jul 16 '23 at 06:29
  • @ecm Well, I'm sorry but it seems that my program's problem isn't related to buffering because it runs and immediately finishes without printing anything, even though it's expected. (You can refer to my fixed question again.) – KnightChaser Jul 16 '23 at 06:35
  • Did you try to return from `main` or not? – ecm Jul 16 '23 at 07:04
  • @ecm Honestly, I didn't because I couldn't grasp how to do that. (BTW, I found two solutions to work; 1. Add '0xA' which means newline at the end of "Enter the upper limit: " the notificiationMessage that will go to rsi register / 2. Append another code like scanf(extern scanf). I was supposed to use scanf, so I just proceeded, and it worked without appending 0xA. But I don't know why these methods work.) – KnightChaser Jul 16 '23 at 07:11
  • 1
    Doesn't linux require eax to be set when [calling variadic functions](https://stackoverflow.com/a/6212835/2189500)? – David Wohlferd Jul 16 '23 at 08:12
  • 1
    I think your problem was the libc's buffering which would have been fixed by returning, as well. Or displaying a Line Feed (U+000A). Or calling `fflush`. If you don't want to try suggestions then why ask at all? (ETA: I misread your "grasp how to do that". Returning from `main` is as simple as replacing `mov rax, SYS_EXIT` and everything after by a `retn` "return near" instruction.) – ecm Jul 16 '23 at 10:38
  • @ecm Thanks. Finally understood what did you mean and it actually worked. – KnightChaser Jul 16 '23 at 11:21

1 Answers1

1

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

KnightChaser
  • 143
  • 1
  • 9
  • 1
    In NASM `retn` is actually always the same as `ret` (unless you specifically write macros to alter either), but I think that `retn` is clearer. That's why I use it. As an alternative you could call the `exit` function of your C library. – ecm Jul 16 '23 at 13:05