Peculiar to my needs this algo finds all strings in command line that aren't delimited and if more than one, lets user select which one to return to caller. I use this as a means of selecting a filename to be used by my application.
I realize delimiting the string I want with -f would be the most logical thing to do, but that doesn't address the hobby aspect of my code in so much as to dream it up and then see if I can make it work.
; * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * -
; Parse command line for qualifying filenames denoted by lack of delimiter
; ENTRY: ARG 1 = Pointer to ArgV passed by kernel
; LEAVE: RAX = Pointer to filename, otherwise null
; R8 = Number of matching pointers, otherwise unchanged
; RCX = undetermined
; RDX = Could be modified
; FLAGS: ZR = 0 Success, othewise ZR = 1
; 0ACH = 172 bytes
; -------------------------------------------------------------------------------------------
; Looks a little unorthadox, but this method ensures RSI will be restore properly
; as procedure frame increases in size dynamically dependant upon contents of
; command line.
ParseCL push rsi
push rbx
push rbp
mov rbp, rsp ; Empty frame to accomadate STDCALL
; Determine if there is even anything to do. Maybe should have done this in caller
mov rsi, [rbp + 32] ; Get pointer to ArgV
lodsq ; Number of arguments passed to application
dec rax
jz .Exit ; ZR = 1, no arguments just app path & name
; Prepare for main body of procedure
mov rcx, rax ; Copy arguments left
lodsq ; Waste app path & name
; Cycle through each of the remaining arguments and ignore those beginning with
; GNU conventional delimiter being '-'
.Next lodsq ; Get pointer to next argument
cmp byte [rax], '-' ; Is string prefixed with delimiter
jz $ + 3
push rax ; Probably a valid filename
loop .Next ; Continue till RCX = 0
; Now we need to determine how many pointers in the array and if more than one
; prompt operator which is the valid one. Start by calculating array size
mov rcx, rbp ; Get TOS (Top Of Stack)
sub rcx, rsp ; RCX = Number of bytes
shr rcx, 3 ; RCX /= 8 Actual number qword pntrs
mov rax, rcx
jz .Exit ; Bail if there weren't any matching
cmp cl, 1 ; Hopefully less than 255 pointers
ja $ + 5
; Of all the arguments passed, only one qualified as a possible filename, so that
; is the one we'll return to caller.
pop rax
jmp .Exit
; In data section
; NmeQuery db 10, 10, 'Please select [ A - '
; MaxQuery db ' ] ', 0
; MaxQuery is dynamic and determined by the number of eligible strings in array
mov r8, rcx ; We'll need this for comparison later
mov al, cl
add al, 64 ; Determine A - Z
mov [MaxQuery], al ; And write to proper position
; Values needed by ShowNme
mov rbx, rsp ; Pointer to array of filename pointers
mov rsi, NmePrompt ; = 10, 9, '[?] - '
.ShowNme mov al, cl
add al, 0x40 ; Convert to uppercase A - Z
mov [rsi + 3], al ; and post @ question mark position
call Console
push rsi ; Incase entry invalid, we'll need pointer again
push rcx
dec rcx ; Zero index to proper pointer
mov rsi, [rbx+rcx*8]
call Console ; and display
pop rcx
pop rsi
loop .ShowNme ; Continue till RCX exhausted
; Now give operator oportunity to select which name
.Ask mov rsi, NmeQuery
call Console ; Prompt operator
push 0 ; and make a small input buffer
mov rsi, rsp
xor rdx, rdx
mov dl, 2 ; Single charater and return
call Keyboard
mov al, [rsp] ; Get first character of input
and al, 31
cmp al, r8b
ja .Ask ; If invalid, ask again
dec R8
mov rax, [rbx+R8*8] ; Grab pointer from array
.Exit leave ; Waste procedure frame
pop rbx
pop rsi
or rax, rax ; Set appropriate flags
ret 8 ; RAX = NULL or pointer to filename