; ============================================================================================
; Read brand string and return trimmed ASCIIZ pointer in RAX.

;       ENTRY:  RBP + 40 = Pointer to suitably large enough results buffer (48 bytes).

;       LEAVE:  RAX = Pointer to trimmed string
;               RCX = Length of string including terminator.

;       FLAGS:  ZF = 1 Null or blank string.
; --------------------------------------------------------------------------------------------

  GetBrandString:

	push	rsi
	push	rdi			; Preserve non-volatile
	push	rbx

	push	rbp
	mov	rbp, rsp		; Frame to address ARG-0 @ RBP + 40

	mov	eax, 0x80000004 	; First interation of brand plus 1

   @@:	push	rax			; Register is going to get trashed
	cpuid				; Get 4 byte strings in RDX, RCX, RBX & RAX

   ; BIOS still only passes 4 bytes / register, so now they have to be compressed as we can't
   ; push dwords.

	shl	rdx, 32
	add	rdx, rcx
	xchg	[rsp], rdx		; Last 8 bytes on stack
	shl	rbx, 32
	add	rbx, rax
	push	rbx			; First 8 bytes on stack
	xchg	rdx, rax
	dec	 al
	cmp	 al, 2			; Keep going for 3 interations
	jnb	 @B

    ; Initialize values required by compression process.

	mov	rdi, rsp		; Establish pointer to NULL terminated string
	mov	rsi, [rbp + 40] 	; Get destination buffer from caller
	xor	ecx, ecx
	mov	 cl,  48		; Buffer size

    ; #1 Test for NULL string.  Highly unlikely

	cmp	byte [rdi], 0
	jnz	@F

    ; When ever string is NULL or completely blank (47 spaces), fill destination buffer with
    ; nulls and return zero in RCX.

  .Padd:
	mov	rdi, rsi
	push	rdi
	mov	 cl, 6			; Going to move QWORDS
	xor	eax, eax
	rep	stosq
	pop	rax
	jmp	.Done

    ; #2 Test for leading space(s).

   @@:	mov	 al, ' '
	cmp	[rdi], al
	jnz	@F

    ; Scan forward until first non-space character encountered.
	rep	scasb
	or	ecx, ecx
	jz	.Padd

    ; Adjust pointer and counter to represent actual position and length left.

	dec	rdi
	inc	ecx

    ; #3 Determine if there are trailing spaces by looking at char (StrLen - 1)

   @@:	cmp	[rdi + rcx - 2], al
	jnz	@F

   ; Scan backward through string until first non-space

	push	rdi
	lea	rdi, [rdi + rcx - 2]	; Point to position just before terminator
	std				; Auto decrement
	repz	scasb
	cld
	mov	byte [rdi + 2], 0	; Force new terminator
	pop	rdi
	inc	 cl			; Bump to reflect actual length again

    ; Now that string as been compressed for extraneous spaces, move it to buffer passed
    ; by caller. Caller must assure

   @@:	xchg	rsi, rdi
	push	rdi
	push	rcx
	rep	movsb
	pop	rcx
	pop	rax

  .Done:
	leave				; Kill procedure frame and local buffer
	or	ecx, ecx		; Set condition

	pop	rbx
	pop	rdi			; Restore non-volatile
	pop	rsi

	ret	8			; Waste parameter passed by caller.