As part of a larger hobby project that I'm undertaking being a doubly linked list for 95/98/XP, this is the first in a series that I will be posting.

Upon completion, I will have a complete application written in assembly for the Windows platform. Compiled with NASM

; 				     *** PARSE COMMAND LINE ***

;	ENTRY:	ESP + 4 > Points to callers bottom of stack

;	LEAVE:	ESP	> Points to address of array of string pointers
;		 AL	> Number of parameters passed to application
;		 AH	> Bit 0 = 1 If mismatched quotes, Bit 1 = 1, if array overflow.

; NOTE: As this routine modifies ESP,it is important calling routine take appropriate
;	measures to account for this fact.

;	Routine modifies original string, it is important ParseCL only be called once.

  ParseCL	pop	eax			; Get callers return.

	; Allocate 512 bytes from stack for a maximum of 128 32 bit pointers to strings. Max
	; value for ECX is 1020 due to the 8 bit unsigned value returned in AL.

		mov	ecx, 512
		sub	esp, ecx
		mov	edx, esp		; Needed later for base pointer.
		push	eax			; Callers return to top of stack again.

		push	esi
		push	edi			; Save essential registers
		push	ebx

	; Initialize pointers and data required by parsing loop

		mov	ebx, edx		; EBX = Base of parameter pointers
		call	_GetCommandLineA@0
		mov	esi, eax
		mov	edi, eax
		mov	edx, ecx
		shr	edx, 2			; EDX = Number of pointers that can be saved.
		xor	ecx, ecx
		mov	eax, ecx
		cld				; Assure STOS & LODS will auto-inc indices.

  .NextCh	mov	 ah,  al		; Save previously read character
		lodsb				; Get character from source
		and	 al,  al		; Is it NULL (termination byte)
		jz	.Done			; ZR = 1, if finished

	; Quotation marks have a special meaning as that inside quotes the other delimiting
	; character being the space are to be treated as literal.  Toggle bit 16 in EAX to
	; indicate this, and if bit 16 is on upon return we know there were mismatched quotes.

		cmp	 al, '"'
		jnz	.Space			; ZR = 0, if it wasn't a quotation mark

		xor	 al, al			; Quotes are always converted to null
		btc	eax, 16			; Toggle InQuotes flag
		jnc	.NextCh			; Pass over if it's leading quote

  .Post		stosb
		jmp	short	.NextCh

	; Spaces are the other delimiter and except when inside quotes are to be treated as 
	; end of string.  NOTE: Embedded spaces may cause paramter to be misiterpreted.

  .Space	cmp	 al, ' '
		jnz	.Default		; ZR = 0, if this is not a space

		bt	eax, 16			; Are we inside quotation marks
		jc	.Post			; NC = 1, if in quotes

		xor	 al,  al		; Nullify character
		and	 ah,  ah		; Determine if previous character is null
		jz	.NextCh			; Ignore leading spaces
		jmp	short .Post

	; All other characters are treated literaly, and if the previous character (AH) is null
	; then we know this is the begining of the next parameter

  .Default	and	 ah,  ah
		jnz	.Post			; Not first character of parameter

	; Check value of CX versus DX which is the maximum number of pointers that can be save
	; in allocated stack space.

		cmp	 cx,  dx
		ja	.NoRoomLeft

		mov	[ebx + ecx * 4], edi	; Save pointer
		inc	ecx
		jmp	short .Post

  .NoRoomLeft	bts	eax, 17			; Set error condition, buffer overflow
		jmp	short .Done + 2

  .Done		stosb

	; Establish return value in EAX, by shifting status bits 16 & 17 into 8 & 9 and then
	; moving number of parameters passed into AL, resulting in AX being retunred value

		shr	eax, 8			; Shift Status bits
		mov	 al,  cl		; Parameters passed into AL

	; Stack space must be compressed so last parameters pointer is on top of callers stack.

		add	ecx, 4			; Account for values on stack already
		sub	edx, ecx		; Offset from maximum allowable
		shl	edx, 2			; Determine actual number of bytes
		add	edx, ebx		; EDX = Offset from top of callers stack

	; Initialize indexes with appropriate values for block move MOVSD and move block.

		mov	edi, edx
		mov	esi, esp
		rep	movsd
		mov	esp, edx		; Now stack pointer can be relocated

	; Restore all register and return to caller with appropriate pointers on stack

		pop	ebx
		pop	edi
		pop	esi