;functions in file:	FillString
;				Hex2Str
include	definitions.inc

.code
;*******************************************************************
FillString	PROC	FS_OffsetOfString:HANDLE, FS_OffsetOfStringToAdd:HANDLE, FS_HowToChange:DWORD
;HowToChange: FS_AT_THE_END = 0 => paste StringToAdd at the end of StringToBeFilled
;		    FS_AT_OFFSET = 1 => paste StringToAdd at the offset that was passed in OffsetOfString
;			    (so it overwrites if something was there)
;
;THE STRINGS MUST END WITH 0h!
uses	ebx, edx, edi, esi		;eax and ecx are scratch registers
	pushf
	cld
	mov	edi, FS_OffsetOfString
	
	cmp	FS_HowToChange, NULL
	jne	@FS_paste_at_offset
	
	dec	edi
@FS_we_are_not_at_the_end_of_string:
	inc	edi
	cmp	byte ptr [edi], NULL
	jne	@FS_we_are_not_at_the_end_of_string
		
@FS_paste_at_offset:
;count the StringToAdd lenght

	mov	esi, FS_OffsetOfStringToAdd
	xor	ecx, ecx
	dec	esi
	
@FS_one_letter_more:
	inc	ecx
	inc	esi
	cmp	byte ptr [esi], NULL
	jne	@FS_one_letter_more
;now we have the number char. + 1 ( 0h to because we have to copy that to)
;if the StringToAdd doesn't have any char. function will copy 0h to string

	mov	esi, FS_OffsetOfStringToAdd
	
	cmp	ecx, 4					;ecx=lenght of StringToAdd
	jl	@FS_less_than_four			;jump if less
	
	mov	ebx, 4
	mov	eax, ecx
	xor	edx, edx
	div	ebx						;quotient=>eax, remainder=>edx
	xchg	eax, ecx			
	rep	movsd

	test	edx, edx					;if there is something in there we are not finished
	je	@FS_finished_copying_data
	mov	ecx, edx

@FS_less_than_four:
	rep	movsb

@FS_finished_copying_data:
	popf
	ret

ENDP
;*******************************************************************

;*******************************************************************
Hex2Str	PROC	number:ULONG, pConverted:POINTER, numberType:ULONG
USES ebx, edx, esi, edi
;POINTER Hex2Str{
;    number - Number we want to convert.
;		    NOTICE!
;		    This number is ALWAYS a 32bit number. It doesn't matter if we have just a byte2string conversion.
;		    (Use movzx,... to conver  to 32 bit.)
;    pConverted - Pointer to buffer that will receive converted number.
;	numberType - Type of number we want to convert.
;			   1 - byte2Str
;			   2 - word2Str
;			   4 - dword2Str
;}
;
;RETURN:
;Function returns pointer to the next character in pConverted so that if you want
;you can finish string with zero byte.
;
	mov	ebx, pConverted

;NUMBER TYPE
	mov	eax, [numberType]
	cmp	eax, 4			;dword2Str
	jne	@HexNotDwordConversion
	mov	ecx, 28
	jmp	@HexInitialize
@HexNotDwordConversion:
	cmp	eax, 2
	jne	@HexNotWordConversion
	mov	ecx, 12
	jmp	@HexInitialize
@HexNotWordConversion:
;byte is assumed
	mov	ecx, 4

@HexInitialize:	
;CLEAR ZEROS
;do not convert zeros (00000231=> 231; letter have 0 in front of them 0A00)
	mov	esi, ecx			;a back up
	mov	eax, number
	xor	edi, edi			;counter of how many zeros are in front of the number
	mov	edx, eax			;a back up

@HexClearZerosLoop:
	test	cl, cl
	js	@HexZerosAtTheEnd	;jump if less than 0=>this means that over number is NULL
	shr	eax, cl
	test	al, al
	jnz	@HexNotAZero
	mov	eax, edx
	sub	cl, 4
	inc	edi
	jmp	@HexClearZerosLoop

@HexNotAZero:
	shl	edi, 2			;edi*4
	sub	esi, edi
	mov	ecx, esi

;CONVERT
	mov	eax, edx			;number
@HexNotOver:
	shr	eax, cl			;get the nibble
	and	al, 01111b		;only last nibble
	cmp	al, 9
	ja	@HexMoreThan9
	add	al, '0'
	jmp	@HexJumpOver
@HexMoreThan9:
	add	al, 037h			;37h+0Ah=41h='A'
@HexJumpOver:
	mov	[ebx], al			;save
	sub	cl, 4
	mov	eax, edx
	inc	ebx
	test	cl, cl
	jns	@HexNotOver
	mov	eax, ebx			;points to next char in pConverted
	ret

@HexZerosAtTheEnd:
@HexNULL:
	mov	byte ptr [ebx], '0'
	inc	ebx
	mov	eax, ebx
	ret
ENDP
;*******************************************************************

;*******************************************************************
StringComplete	PROC string:POINTER, buffer:POINTER
;DWORD StringComplete {
;    string = Pointer to zero ended string we want to process.
;    buffer = Pointer to processed string buffer.
;}
;
;RETURN:
;Function returns pointer to end of the buffer. So you can add zero byte at the end of the buffer if you wish.
;If there is unsuported variableType than 'unknownVariableType' text will be inserted insted of variable.
;
;CAUTION:
;Before function variables we must push pointers or numbers of the string variables.
;Variables are pushed from right to left.
;So Name 1st, Time 2nd, ...
; db 'OvlNum: %X  LibIndex: %X  SegCount: %X  Time: %X  Name: %s'
;
;NOTICE!
;After procedure is finished you must fix stack number.
;So if you have 3 variables, after proc., you must add 3*DWORD to esp.
;
;Currently only %x(X)=hexNumber and %s(S)=string are supported.
;%1x => 1byte long
;%2x => 2byte long
;%4x => 4byte long
;%x  => 4byte long
;
USES ebx, edx, esi, edi

	mov	ebx, string
	lea	edx, [buffer+4]		;edx = offset to variable (edx= pBuffer+varNum*DWORD )
	mov	edi, buffer

@FS_NextCharacter:
	mov	al, byte ptr [ebx]
	test	al, al
	jz	@FS_End
	cmp	al, '%'
	je	@FS_Variable
	mov	byte ptr [edi], al		;move letter to buffer
	inc	ebx					;to next letter
	inc	edi					;to next 'letter'
	jmp	@FS_NextCharacter

@FS_Variable:
	inc	ebx					;to next character
	mov	al, byte ptr [ebx]
	cmp	al, '9'				;is it a number
	ja	@FS_ACharacter
	jmp	@FS_NotStringVariable_Number
@FS_ACharacter:
	or	al, 020h				;10 0000b => to lower charater
	cmp	al, 's'
	jne	@FS_NotStringVariable_Letter
;STRING
	xor	ecx, ecx
	mov	esi, dword ptr [edx]
@FS_StringCount:
	cmp	byte ptr [esi], 0
	je	@FS_FinishedStringCount
	inc	ecx
	inc	esi
	jmp	@FS_StringCount
@FS_FinishedStringCount:
	mov	esi, dword ptr [edx]
@FS_UpdateAndCopyString:
	add	edx, 4			;to next variable
	cld					;clear direction flag(if set)
	repnz movsb			;copy string to buffer
	inc	ebx				;to next character
	jmp	@FS_NextCharacter

;NOT A STRING
@FS_NotStringVariable_Number:
	inc	ebx				;to next character
	cmp	byte ptr [ebx], 'x'
	jne	@FS_NotHexVariable
	cmp	al, '4'
	je	@FS_Hex2Str4bytes
	cmp	al, '2'
	je	@FS_Hex2Str2bytes
	cmp	al, '1'
	je	@FS_Hex2Str1bytes
	jmp	@FS_NotHexVariable
@FS_NotStringVariable_Letter:
	cmp	al, 'x'
	jne	@FS_NotHexVariable
@FS_Hex2Str4bytes:
	push	4				;dword2Str
	push	edi				;pConverted
	push	dword ptr [edx]	;number
	add	edx, 4			;to next variable
	call	Hex2Str
	mov	edi, eax			;update pointer
	inc	ebx				;to next character
	jmp	@FS_NextCharacter

@FS_Hex2Str2bytes:
	push	2				;word2Str
	push	edi				;pConverted
	push	dword ptr [edx]	;number
	add	edx, 4			;to next variable
	call	Hex2Str
	mov	edi, eax			;update pointer
	inc	ebx				;to next character
	jmp	@FS_NextCharacter

@FS_Hex2Str1bytes:
	push	1				;byte2Str
	push	edi				;pConverted
	push	dword ptr [edx]	;number
	add	edx, 4			;to next variable
	call	Hex2Str
	mov	edi, eax			;update pointer
	inc	ebx				;to next character
	jmp	@FS_NextCharacter

;NOT A HEX
@FS_NotHexVariable:
.data
unkonwnVariableType		db"unknownVariableType",0
.code
	mov	esi, offset unkonwnVariableType
	mov	ecx, 19		;lenght of the string
	jmp	@FS_UpdateAndCopyString

@FS_End:
	mov	eax, edi
	ret
ENDP
;*******************************************************************

END