format PE Console
entry start

include 'win32ax.inc'

section '.data' data readable writeable
;----------------------------------------------------
include 'ascii.asm'
LOOPCOUNT = 2000000
_oh					dd 0
_consoleWritten		dd 0
_obuffer			rb 0xFF

align 8
_timeStart			dq 0
_timeEnd			dq 0
_sstimeStart		dq 0
_sstimeEnd			dq 0
_hahatimeStart		dq 0
_hahatimeEnd		dq 0
_johnfoundtimeStart	dq 0
_johnfoundtimeEnd	dq 0



section '.code' code readable executable
;----------------------------------------------------
start:
	invoke	GetStdHandle,STD_OUTPUT_HANDLE
			mov  [_oh],eax
	stdcall	consoleWrite,<13,10,'Benchmark Console',13,10,0>
	stdcall	consoleWrite,<'=================',13,10,0>
	stdcall	consoleWrite,<'- perform result comparing for each proc',13,10,0>

			mov  esi,LOOPCOUNT
			mov  ebx,string1

	invoke	QueryPerformanceCounter,_timeStart
	; will perform all the comparing here, make sure all proc return exact result
	ascii2d_start:
			cmp  esi,0
			je   ascii2d_end
			
	stdcall	sleepsleep_ascii2d,ebx
			push eax	; for haha
			push eax	; for johnfound
	stdcall	HaHaAnonymous_ascii2d,ebx
			pop  edx
			cmp  eax,edx
			je   equal_sshaha
			pop  eax
	cinvoke	wsprintf,_obuffer,<'error ebx string number : %ld | %lu',13,10,0>,ebx,ebx
	invoke	ExitProcess
	equal_sshaha:
	stdcall	johnfound_ascii2d,ebx
			pop  edx
			cmp  eax,edx
			je   equal_ssjohnfound
	cinvoke	wsprintf,_obuffer,<'error ebx string number : %ld | %lu',13,10,0>,ebx,ebx
	invoke	ExitProcess
	equal_ssjohnfound:
			dec  esi
	@@:
			inc  ebx
			cmp  byte [ebx], 0
			jne  @b
			inc  ebx
			jmp  ascii2d_start
	
	ascii2d_end:
	
	; result
	invoke	QueryPerformanceCounter,_timeEnd
			mov  eax, dword [_timeStart]
			mov  ecx, dword [_timeStart + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax, dword [_timeEnd]
			mov  ecx, dword [_timeEnd + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax,dword [_timeStart]
			mov  ecx,dword [_timeEnd]
			sub  ecx,eax
	cinvoke	wsprintf,_obuffer,<'difference : %lu',13,10,0>, ecx
	stdcall	consoleWrite,_obuffer

	
	; sleepsleep
	; ----------
	invoke	QueryPerformanceCounter,_sstimeStart

			mov  esi,LOOPCOUNT			; times to loop
			mov  ebx,string1
	ssascii2d_start:
			cmp  esi,0
			je   ssascii2d_end
	stdcall	sleepsleep_ascii2d,ebx
			dec  esi
	@@:
			inc  ebx
			cmp  byte [ebx], 0
			jne  @b
			inc  ebx
			jmp  ssascii2d_start
	ssascii2d_end:
	invoke	QueryPerformanceCounter,_sstimeEnd	
	
	
	; HaHaAnonymous
	; -------------
	invoke	QueryPerformanceCounter,_hahatimeStart

			mov  esi,LOOPCOUNT			; times to loop
			mov  ebx,string1
	hahaascii2d_start:
			cmp  esi,0
			je   hahaascii2d_end
	stdcall	HaHaAnonymous_ascii2d,ebx
			dec  esi
	@@:
			inc  ebx
			cmp  byte [ebx], 0
			jne  @b
			inc  ebx
			jmp  hahaascii2d_start
	hahaascii2d_end:
	invoke	QueryPerformanceCounter,_hahatimeEnd

	; johnfound
	; ---------
	invoke	QueryPerformanceCounter,_johnfoundtimeStart

			mov  esi,LOOPCOUNT			; times to loop
			mov  ebx,string1
	johnfoundascii2d_start:
			cmp  esi,0
			je   johnfoundascii2d_end
	stdcall	johnfound_ascii2d,ebx
			dec  esi
	@@:
			inc  ebx
			cmp  byte [ebx], 0
			jne  @b
			inc  ebx
			jmp  johnfoundascii2d_start
	johnfoundascii2d_end:
	invoke	QueryPerformanceCounter,_johnfoundtimeEnd




	
	
	; RESULT
	; ------
	; sleepsleep - Result
	; ----------------------
	stdcall	consoleWrite,<13,10,'[ sleepsleep ]',13,10,0>
			mov  eax, dword [_sstimeStart]
			mov  ecx, dword [_sstimeStart + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax, dword [_sstimeEnd]
			mov  ecx, dword [_sstimeEnd + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax,dword [_sstimeStart]
			mov  ecx,dword [_sstimeEnd]
			sub  ecx,eax
	cinvoke	wsprintf,_obuffer,<'difference : %lu',13,10,0>, ecx
	stdcall	consoleWrite,_obuffer	
	
	; HaHaAnonymous - Result
	; ----------------------
	stdcall	consoleWrite,<13,10,'[ HaHaAnonymous ]',13,10,0>
			mov  eax, dword [_hahatimeStart]
			mov  ecx, dword [_hahatimeStart + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax, dword [_hahatimeEnd]
			mov  ecx, dword [_hahatimeEnd + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax,dword [_hahatimeStart]
			mov  ecx,dword [_hahatimeEnd]
			sub  ecx,eax
	cinvoke	wsprintf,_obuffer,<'difference : %lu',13,10,0>, ecx
	stdcall	consoleWrite,_obuffer

	; johnfound - Result
	; ----------------------
	stdcall	consoleWrite,<13,10,'[ johnfound ]',13,10,0>
			mov  eax, dword [_johnfoundtimeStart]
			mov  ecx, dword [_johnfoundtimeStart + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax, dword [_johnfoundtimeEnd]
			mov  ecx, dword [_johnfoundtimeEnd + 4]
	cinvoke	wsprintf,_obuffer,<'time used to process : %lu %lu',13,10,0>, eax,ecx
	stdcall	consoleWrite,_obuffer
			mov  eax,dword [_johnfoundtimeStart]
			mov  ecx,dword [_johnfoundtimeEnd]
			sub  ecx,eax
	cinvoke	wsprintf,_obuffer,<'difference : %lu',13,10,0>, ecx
	stdcall	consoleWrite,_obuffer
	invoke	ExitProcess,0


; input :	asciiAddr = ascii string number starting address / pointer
; output :	EAX = holding translate number
;			ECX = 0 (signed) 1 (unsigned)
proc sleepsleep_ascii2d uses ebx esi edi, asciiAddr
			mov  eax,[asciiAddr]
			mov  edi,_tbl
			dec  eax
			xor  ecx,ecx
	@@:
			inc  eax
			inc  ecx
			cmp  byte [eax],0
			jne  @b
			sub  ecx,2
	; ecx got length now
			
			mov  ebx,[asciiAddr]
			xor  eax,eax
			xor  esi,esi	; hold total
			mov  al, [ebx+ecx]
			sub  al,'0'
			add  esi,eax
	@@:
			dec  ecx
			cmp  ecx,0
			je   .checkNegative
			add  edi,4
			xor  eax,eax
			mov  al,[ebx+ecx]
			sub  al,'0'
			mul  dword [edi]
			add  esi,eax
			jmp  @b
			
	.checkNegative:
			xor  eax,eax
			mov  al,[ebx]
			cmp  al,'-'
			je   .negativeFound
			add  edi,4
			sub  al,'0'
			mul  dword [edi]
			add  eax,esi
			inc  ecx
			ret
			
		.negativeFound:
			mov  eax,esi
			neg  eax
			ret

_tbl	dd 0
		dd 10
		dd 100
		dd 1000
		dd 10000
		dd 100000
		dd 1000000
		dd 10000000
		dd 100000000
		dd 1000000000
endp


HaHaAnonymous_ascii2d:
      push     ebx
      push     ebp
      push     edi
      push     esi
      mov      ebx,[esp+$14]
      mov      ebp,ebx
      xor      edi,edi
      mov      edx,edi
      movzx    ecx,bl
      cmp      byte [ebx],$2D
      jne      .offset
      inc      ebx
      movzx    ecx,bl
   .offset:
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      cmp      byte [ebx+$01],$00
      jz       .unsigned
      inc      ebx
      nop
   .unsigned:
      mov      esi,$00000001
   .start:
      mov      al,[ebx]
      sub      al,$30
      movzx    eax,al
      mul      esi
      add      edi,eax
      cmp      bl,cl
      je       .bye
      dec      ebx
      mov      eax,$0000000A
      mul      esi
      mov      esi,eax
      jmp      .start
   .bye:
      mov      eax,edi
      neg      edi
      sub      ebx,ebp
      cmovnz   eax,edi
      pop      esi
      pop      edi
      pop      ebp
      pop      ebx
      ret      $0004 

johnfound_ascii2d:
        push    esi

        xor     eax, eax
        mov     esi, [esp+8]
        mov     edx, eax
        mov     ecx, eax

        cmp     byte [esi], '-'
        jne     .loop

        add     esi, 1
        sub     ecx, 1

.loop:
        lodsb
        sub     al, '0'
        jc      .ends

        lea     edx, [5*edx]
        lea     edx, [2*edx+eax]
        jmp     .loop

.ends:
        xor     edx, ecx
        sub     edx, ecx
        mov     eax, edx
        pop     esi
        retn 4
	
;---------------------------
proc consoleWrite ascii
;---------------------------
			mov  eax,[ascii]
			dec  eax
			mov  ecx,-1
	@@:
			inc  eax
			inc  ecx
			cmp  byte [eax],0
			jne  @b
	invoke	WriteConsole,[_oh],[ascii],ecx,_consoleWritten,NULL
	.finish:
			ret
endp

section '.idata' import data readable
;----------------------------------------------------
library	kernel32,	'KERNEL32.DLL',\
		user32,		'USER32.DLL'

		include 'API\KERNEL32.INC'
		include 'API\USER32.INC'