Skip to content

Instantly share code, notes, and snippets.

@Gydo194
Last active November 3, 2024 20:54
Show Gist options
  • Save Gydo194/730c1775f1e05fdca6e9b0c175636f5b to your computer and use it in GitHub Desktop.
Save Gydo194/730c1775f1e05fdca6e9b0c175636f5b to your computer and use it in GitHub Desktop.
Command Line arguments in NASM assembly on 64-bit Linux
; print all command line arguments (5 characters) and exit
; for 64-bit systems, Linux syscalls
; for simplicity, this program does not calculate the length of the strings.
; assemble with: nasm -f elf64 -o args args.asm
; link with: ld -o args args.o
sys_write equ 1 ; the linux WRITE syscall
sys_exit equ 60 ; the linux EXIT syscall
sys_stdout equ 1 ; the file descriptor for standard output (to print/write to)
length equ 5 ; the length of the string we wish to print (fixed string length of the arguments)
section .data
linebreak db 0x0A ; ASCII character 10, a line break
section .text
global _start
_start:
pop r8 ; pop the number of arguments from the stack
pop rsi ; discard the program name, since we only want the commandline arguments
top:
; loop condition
cmp r8, 0 ; check if we have to print more arguments
jz exit ; if not, jump to the 'end' label
; print the argument
mov rax, sys_write ; set the rax register to the syscall number we want to execute (WRITE)
mov rdi, sys_stdout ; specify the file we want to write to (standard output in this case)
pop rsi ; pop a pointer to the string we want to print from the stack
mov rdx, length ; specify the (fixed) length of the string we want to print
syscall ; execute the system call
; print a newline
mov rax, sys_write ; rax is overwritten by the kernel with the syscall return code, so we set it again
mov rdi, sys_stdout
mov rsi, linebreak ; this time we want to print a line break
mov rdx, 1 ; which is one byte long
syscall
dec r8 ; count down every time we print an argument until there are none left
jmp top ; jump back to the top of the loop
; the program is finished, now exit cleanly by calling the EXIT syscall
exit:
mov rax, sys_exit ; load the EXIT syscall number into rax
mov rdi, 0 ; the program return code
syscall ; execute the system call
@Cvar1984
Copy link

Cvar1984 commented Dec 9, 2022

its also printing junk from rsi to know exact size of your argument we can create loop counter to count the rsi
should be done like this

sys_write   equ 1
sys_exit    equ 60
sys_stdout  equ 1

[section .data]
    linebreak db 0x0A

[section .text]
global _start

strlen:
    xor   eax, eax
s_loop:
    cmp   byte [rdi], 0
    je    return
    inc   rdi
    inc   rax
    jmp   s_loop
return:
    ret

_start:
    ; Pop the number of arguments from the stack.
    pop   rbx

    ; Discard the program name, since we only want
    ; the command line arguments.
    pop   rsi
    
    ; If there are no extra command line argments,
    ; just exit directly!
    dec   rbx
    jz    exit

top:
    ; Calculate the string len.
    ;
    ; The return value of strlen
    ; goes in rax.
    mov   rdi, [rsp]
    call  strlen

    mov   edx, eax
    mov   eax, sys_write
    mov   edi, sys_stdout
    pop   rsi
    syscall

    mov   eax, sys_write
    mov   edi, sys_stdout
    mov   esi, linebreak
    mov   edx, 1
    syscall

    ; If `dec r8` is not zero, goto top.
    dec   rbx
    jnz   top

exit:
    mov   eax, sys_exit
    xor   edi, edi
    syscall

@Gydo194
Copy link
Author

Gydo194 commented Dec 10, 2022

If I recall correctly, this was only meant to get one-character integer arguments, and was done as a learning excersise for myself. Aka not meant to be used in production.

@Cvar1984
Copy link

If I recall correctly, this was only meant to get one-character integer arguments, and was done as a learning excersise for myself. Aka not meant to be used in production.

i respect that, I'm doing some exercise too and i found your gist in top of google search, in fact my code is your code with some improvisation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment