Getting User Input in Nasm x64

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
Print prompt to screen “Enter your name: “
Initialize name variable to receive prompt entry
Display “Hello, name”
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
- The user’s input will include a newline character (
\n
, ASCII 10) if they press Enter. So thename
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!
Subscribe to my newsletter
Read articles from Rawley Amankwah directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
