MAX_THREADS=8

	format PE console
	include 'win32ax.inc'

.data

	STDOutputHandle	rd 1
	thread_counters	rd MAX_THREADS

.code

proc begin
		locals
			ProcessAffinityMask	rd 1
			SystemAffinityMask	rd 1
			ThreadID		rd 1
		endl
	invoke	GetStdHandle,STD_OUTPUT_HANDLE
	mov	[STDOutputHandle],eax
	invoke	GetCurrentThread
	invoke	SetThreadPriority,eax,THREAD_PRIORITY_ABOVE_NORMAL
	invoke	GetCurrentProcess
	invoke	GetProcessAffinityMask,eax,addr ProcessAffinityMask,addr SystemAffinityMask
	mov	edi,0			;edi=current number of threads
    .loop:
	invoke	CreateThread,0,0,thread_burner,addr edi*4+thread_counters,CREATE_SUSPENDED,addr ThreadID
	mov	ebx,eax
	invoke	SetThreadPriority,ebx,THREAD_PRIORITY_NORMAL
	invoke	SetThreadAffinityMask,ebx,[ProcessAffinityMask]
	invoke	ResumeThread,ebx
	inc	edi
	stdcall	display_thread_speeds,edi,thread_counters
	cmp	edi,MAX_THREADS
	jb	.loop
	invoke	ExitProcess,0
endp

proc thread_burner counter
	mov	eax,[counter]
    @@:	inc	dword[eax]
	jmp	@b
endp

proc display_thread_speeds uses edi esi ebx,threads,thread_counters
		locals
			copied_counters_1	rd MAX_THREADS
			copied_counters_2	rd MAX_THREADS
		endl
	mov	esi,[thread_counters]
	lea	edi,[copied_counters_1]
	mov	ecx,[threads]
	rep	movsd
	invoke	Sleep,10000
	mov	esi,[thread_counters]
	lea	edi,[copied_counters_2]
	mov	ecx,[threads]
	rep	movsd
	mov	edx,0			;edx=loop counter
	mov	ebx,0			;ebx=total count found
    .loop_compute_total:
	mov	eax,[edx*4+copied_counters_2]
	sub	eax,[edx*4+copied_counters_1]
	add	ebx,eax
	inc	edx
	cmp	edx,[threads]
	jb	.loop_compute_total
	ccall	sprintf_stdoutput,<'Total threads: %lu',13,10>,[threads]
	mov	esi,0			;esi=loop counter
    .loop_print_speed:
	mov	eax,[esi*4+copied_counters_2]
	sub	eax,[esi*4+copied_counters_1]
	mov	ecx,100
	mul	ecx
	div	ebx
	ccall	sprintf_stdoutput,<'Thread: %lu, %3lu%%',13,10>,esi,eax
	inc	esi
	cmp	esi,[threads]
	jb	.loop_print_speed
	ccall	sprintf_stdoutput,<13,10>
	ret
endp

proc sprintf_stdoutput c format,arglist
		local	print_buff[1024]:BYTE
		local	BytesWritten:DWORD
	invoke	wvsprintf,addr print_buff,[format],addr arglist
	invoke	WriteFile,[STDOutputHandle],addr print_buff,eax,addr BytesWritten,0
	test	eax,eax
	jz	.done
	mov	eax,[BytesWritten]
    .done:
	ret
endp

.end begin
