; Kümmel Logical Core Count
format PE GUI 4.0
include '%fasminc%\win32axp.inc'

section '.code' code readable executable

	; Check if SSE2 is available and show message and exit if not
	mov		eax,00000001h							; Request Code 1 for CPUID 
	cpuid
	test	edx,0000010000000000000000000000000b	; If Bit 26 of EDX is set then SSE2 is there 
		jnz		.continue_progi
		invoke	MessageBox,HWND_DESKTOP,text_no_sse2,caption,MB_OK
		invoke	ExitProcess,0
	.continue_progi:
	
	; I wonder if this one also checks the correct logical core count...
	
	;mov		eax,00000001h							; Request Code 1 for CPUID 
	;cpuid											; Logical Core Count is in EBX at Bit 16...Bit 23
	;shr		ebx,16									; Shift...
	;and		ebx,00000000000000000000000011111111b	; ...and mask the logical core count
	
	; Here I try it with the GetProcessAffinityMask and the received ProcessAffinityMask...the question remains if that works,
	; as I want to count all cores of a system including the virtual ones from Hyper Threading...?
	
	invoke	GetCurrentProcess
	invoke	GetProcessAffinityMask, eax, ptr_ProcessAffinityMask, ptr_SystemAffinityMask
	
	mov edx, 1b								; Init Bit Count Mask
	mov ecx, 0								; Init Counter
	.next_bit_check:
		mov eax, [ptr_ProcessAffinityMask]	; Get ProcessAffinityMask where each Bit is one processor
		and	eax, edx
		jz  .next_bit_shift
			inc [processor_count]
		.next_bit_shift:
		shl edx,1
		add ecx,1
		cmp ecx,32
		jne .next_bit_check
		
	mov ebx,[processor_count]
	
	; done, now just display stuff
		
	mov [integer_value], ebx 				; That's the number that will be plotted
	
	; Preparation for number to string conversion for the timer result
	mov [address_text], text_result + 26 ;You can add constants together here @Madis@
	
	; Conversion of positive integer number to string
NumberToString_loop:				
	mov		eax, [integer_value]	
	mov		edi, buffer				; I reserved another buffer where we put our intermediate result in
	xor		ecx, ecx
	mov		esi, 10 				; Esi hold the 10 we are going to divide with
	test	eax, eax
	je		.integer_is_zero
.anotherchar:
	test	eax, eax				; Lets test eax for zero
	je		.x				        ; We are done if it holds true
	xor		edx, edx
	div		esi						; divide EDX:EAX with ESI putting the result in EAX and modulo in EDX
	mov		[edi+ecx], dl			; dl is in range 0..9
	inc		ecx						; increase the pointer by one
	jmp		.anotherchar
.x:
	mov		esi, [address_text]		
	jmp		.putonebyte
.integer_is_zero:
	mov		esi, [address_text]		
	inc 	ecx
.putonebyte:
	mov		al, [edi]				; Here we take bytes from [edi]...
	add		al, "0" 				; ...add 30h to them and...
	mov		[esi+ecx-1], al 		; ...finally write it back
	inc		edi						
	loop	.putonebyte				; loop command counts down ecx 

end_of_progi:

	invoke	MessageBox,HWND_DESKTOP,text_result,caption,MB_OK
	invoke	ExitProcess,0
	
;------------------------------------------------------------------------------------------
section '.idata' import data readable writeable
;------------------------------------------------------------------------------------------
library kernel32,'KERNEL32.DLL',\
	user32,'USER32.DLL'

include '%fasminc%/api/kernel32.inc'
include '%fasminc%/api/user32.inc'

;------------------------------------------------------------------------------------------
section '.data' data readable writeable
;------------------------------------------------------------------------------------------
integer_value		dd	0			
logical_core_count	dd	0			; logical core count
address_text		dd	0			; saves the pointer to text_result
text_result			db 'Number of logical cores : ',0
					rb 32			; reserve 32 characters for the result string including end zero
buffer				rb 32

ptr_ProcessAffinityMask		dd  0	; pointer to ProcessAffinityMask	
ptr_SystemAffinityMask		dd  0	; pointer to SystemAffinityMask

processor_count				dd	0

caption	 			db 'Logical Core Counter & SSE2-Test', 0
text_no_sse2		db 'Sorry, your CPU does not support SSE2...',0
