Getting User Input in Nasm x64

Rawley AmankwahRawley Amankwah
4 min read

Getting User Input is a fundamental routine in programming. One may decide to get a user’s input for further computation, storage or simply to display to the screen.

The following is a code excerpt for getting a user’s input in Nasm x64:

    ; Get user input
    mov rax, 0        ; sys_read
    mov rdi, 0
    mov rsi, name     ; name variable is declared in .bss section 
    mov rdx, 10       ; get 10 bytes of the name variable
    syscall

Let’s work on a small project where the user inputs his or her name in our program then we display to the screen.

Code Outline

  1. Print prompt to screen “Enter your name: “

  2. Initialize name variable to receive prompt entry

  3. Display “Hello, name

  4. Exit gracefully.

  • Printing prompt to screen “Enter your name: “

      section .data 
          prompt db "What is your name: "
          promptLen equ $ - prompt 
    
      section .text
          global _start
    
      _start: 
          ; Print prompt to screen
          mov rax, 1
          mov rdi, 1
          mov rsi, prompt
          mov rdx, promptLen
          syscall
    
      _exit:
          ; Exiting
          mov rax, 60
          mov rdi, 0
          syscall
    

    The following is the same code as above but with a slight change by declaring some constants in the .text section to follow industry Standards. Do not fret.

    •   section .data 
            ; Define standard constants
            SYS_WRITE    equ 1
            SYS_READ     equ 0
            SYS_EXIT     equ 60
            STDOUT       equ 1
            EXIT_SUCCESS equ 0
      
            ; Define Strings
            prompt db "What is your name: "
            promptLen equ $ - prompt 
      
        section .text
            global _start
      
        _start: 
            ; Print prompt to screen
            mov rax, SYS_WRITE
            mov rdi, STD_OUT
            mov rsi, prompt
            mov rdx, promptLen
            syscall
      
        _exit:
            ; Exiting
            mov rax, SYS_EXIT
            mov rdi, EXIT_SUCCESS
            syscall
      
  • Initializing name variable to receive prompt entry

    Initialization of a variable in the .bss section follows the format:

    <variable_name> <resType> <num of bytes>

section .data 
    ; Define standard constants
    SYS_WRITE    equ 1
    SYS_READ     equ 0
    SYS_EXIT     equ 60
    STDOUT       equ 1
    EXIT_SUCCESS equ 0
    STDIN        equ 0

    ; Define Strings
    prompt db "What is your name: "
    promptLen equ $ - prompt 

section .bss
    name resb 10 ; Reserve 10 bytes for the name variable

section .text
    global _start

_start: 
    ; Print prompt to screen
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, prompt
    mov rdx, promptLen
    syscall

    ; Get user's input
    mov rax, SYS_READ
    mov rdi, STDIN
    mov rsi, name
    mov rdx, 10    ; How many bytes to read
    syscall

_exit:
    ; Exiting
    mov rax, SYS_EXIT
    mov rdi, EXIT_SUCCESS
    syscall

Note: There are significant changes in the .bss section and the second portion under _start.

  • Display “Hello, name”

    To be able to display “Hello, name”, we will need to initialize a string in the .data section for “Hello, “, then we append the name variable. So the final code looks like the following:

section .data 
    ; Define standard constants
    SYS_WRITE    equ 1
    SYS_READ     equ 0
    SYS_EXIT     equ 60
    STDOUT       equ 1
    EXIT_SUCCESS equ 0
    STDIN        equ 0

    ; Define Strings
    prompt db "What is your name: "
    promptLen equ $ - prompt 
    helloprompt db "Hello, "
    hellopromptLen equ $ - helloprompt

section .bss
    name resb 10    ; Reserve 10 bytes for the name variable

section .text
    global _start

_start: 
    ; Print prompt to screen
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, prompt
    mov rdx, promptLen
    syscall

    ; Get user's input
    mov rax, SYS_READ
    mov rdi, STDIN
    mov rsi, name
    mov rdx, 10    ; How many bytes to read
    syscall

    ; Print hello prompt to screen
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, helloprompt
    mov rdx, hellopromptLen
    syscall

    ; Print name variable to screen
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, name
    mov rdx, 10
    syscall

_exit:
    ; Exiting
    mov rax, SYS_EXIT
    mov rdi, EXIT_SUCCESS
    syscall

Note: prompt and helloprompt do not end with 10 because we want the name on the same line and not on the next line.

To run the code, enter the following in the terminal:


nasm -f elf64 -g -F dwarf print_name.asm -o print_name
ld -o print_name print_name.o
./print_name

FINAL REMARKS

  1. The user’s input will include a newline character (\n, ASCII 10) if they press Enter. So the name variable will likely contain something like:
J o h n \n ? ? ? ? ?

The remaining 5 bytes (since name has 10 bytes) will be replaced with garbage or nulls (?).

However, if a user inputs a name with length >10, then the number of bytes displayed will be the first ten bytes.

Test out different reserve bytes for name.

TEST

Did you notice that after printing the name, the shell does not go to a newline? To fix that;

  • Define a new string in the .data section called “newline”

      newline db 10
    
  • Print out newline after “Printing name variable to screen” and just before “_exit”

      ; Print newline
      mov rax, SYS_WRITE
      mov rdi, STDOUT
      mov rsi, newline
      mov rdx, 1
      syscall
    

Give it a shot. Test different buffer (name) sizes, try different inputs, and see what works best. Assembly isn’t just about writing code—it’s about understanding the machine. You're already on a great path.

Good luck—and keep those registers loaded!

0
Subscribe to my newsletter

Read articles from Rawley Amankwah directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rawley Amankwah
Rawley Amankwah