; cmd_line.asm
; by renzo diomedi
; read+display command line arguments

section .note.GNU-stack

section .data

LF           equ 10       	;line feed, nuova riga
NULL         equ 0              ;end of string

TRUE         equ 1
FALSE        equ 0

EXIT_SUCCESS equ 0

STDIN        equ 0
STDOUT       equ 1
STDERR       equ 2

SYS_read     equ 0
SYS_write    equ 1
SYS_open     equ 2
SYS_close    equ 3
SYS_fork     equ 57             ; portabilita' in differenti OS
SYS_exit     equ 60
SYS_creat    equ 85
SYS_time     equ 201            ; get time

newLine db LF, LF, LF, LF, LF, NULL  ;5 rows above the string and 4 beneath

section .text

global main
main:
; get command line arguments and echo to screen
; standard calling convention: 
; RDI argc argument count
; RSI argv starting address of argument vector
mov r12, rdi
mov r13, rsi

; loop to display each argument to the screen.
; Each argument is a NULL terminated string, so can just print directly

printArguments:
mov rdi, newLine
call printString


mov rbx, 0
mov rcx, 0
mov r8, 0


printLoop0:
mov rdi, qword [r13+rbx*8]
call printString

mov rdi, newLine
call printString

printLoop1
mov rdi, qword [r13+rcx*8]
call printString

mov rdi, newLine
call printString

printLoop2
mov rdi, qword [r13+r8*8]
call printString

mov rdi, newLine
call printString

inc rbx
cmp rbx, r12
jl printLoop0

inc rcx
cmp rcx, r12
jl printLoop1

inc r8
cmp r8, r12
jl printLoop2


clDone:
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall

;
;
;
;
;###########################################################
;
; 
;
;

; procedure (therefore it returns nothing) to display a string to the screen.
; String must be NULL terminated.
; Algorithm:
; - Count characters in string (excluding NULL)
; - Use syscall to output characters
; Arguments: address, string

global printString
printString:

push rbp
mov rbp, rsp
push rbx
push rcx
push r8


;count characters in string
mov rbx, rdi
mov rcx, rdi
mov r8, rdi
mov rdx, 0

;
strCountLoop0:
cmp byte[rbx], NULL
je strCountDone
inc rdx
inc rbx
jmp strCountLoop0


strCountLoop1:
cmp byte[rcx], NULL
je strCountDone
inc rdx
inc rcx
jmp strCountLoop1


strCountLoop2:
cmp byte[r8], NULL
je strCountDone
inc rdx
inc r8
jmp strCountLoop2


strCountDone:
cmp rdx, 0
je printDone

;call OS to output string

mov rax, SYS_write
mov rsi, rdi                   ;address of characters
mov edi, STDOUT                ;FILE DESCRIPTOR

syscall

printDone: 
; inverse order
pop r8
pop rcx
pop rbx                        
pop rbp                        
ret
