Hi,
I used dwtoa (masm32) and from dwtoa i wrote CnvToRcl and ddToRcl.
With CnvToRcl i know the string length and it seems to give better results.
CnvToRcl uses push to the stack
ddToRcl is CnvToRcl but saves registers in mmx
Is there any other idea that gives better results ?
What are the results do you get with this code ?
Thanks.
Rui
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
.586
.mmx
include \masm32\macros\timers.asm
CnvToRcl proto :DWORD,:DWORD
ddToRcl proto :DWORD,:DWORD
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
_data0 dd 7FFFFFFFh ;0FFFFFFFFh
_data1 dd 70000000h ;4294967295
_data2 dd 0FF9FF8Fh ;3232323299
_data3 dd 00FF8F9Fh
_data4 dd 000F8F91h
_data5 dd 00008F91h
_data6 dd 10
_data7 dd 1255780
_data8 dd 0
_data9 dd 0FFFFFFFFh
dd 20 ; -8 max. string length
dd 0 ; -4 string length
_buffer0 db 20 dup (0)
db 0 ; can end with 0
;
dd 20
dd 0
_buffer1 db 20 dup (0)
db 0
dd 20
dd 0
_buffer2 db 20 dup (0)
db 0
dd 20
dd 0
_buffer3 db 20 dup (0)
db 0
dd 6 ; 6 <- with 6 the next buffer is protected
dd 0 ; using CnvToRcl
_buffer4 db 6 dup (0)
db 0
db 10 dup (0) ; protection
dd 9
dd 0
_buffer5 db 9 dup (0)
db 0
dd 20
dd 0
_buffer6 db 20 dup (0)
db 0
dd 20
dd 0
_buffer7 db 20 dup (0)
db 0
dd 20
dd 0
_buffer8 db 20 dup (0)
db 0
dd 20
dd 0
_buffer9 db 20 dup (0)
db 0
.code
; ##########################################
start:
;invoke Sleep, 40
; ##########################################
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data0, offset _buffer0
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer0, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data1, offset _buffer1
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer1, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data2, offset _buffer2
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer2, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data3, offset _buffer3
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer3, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data4, offset _buffer4
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer4, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data5, offset _buffer5
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer5, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data6, offset _buffer6
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer6, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data7, offset _buffer7
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer7, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data8, offset _buffer8
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer8, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data9, offset _buffer9
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer9, 13, 10
print chr$(13, 10)
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data0, offset _buffer0
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer0, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data1, offset _buffer1
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer1, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data2, offset _buffer2
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer2, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data3, offset _buffer3
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer3, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data4, offset _buffer4
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer4, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data5, offset _buffer5
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer5, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data6, offset _buffer6
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer6, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data7, offset _buffer7
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer7, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data8, offset _buffer8
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer8, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke CnvToRcl, _data9, offset _buffer9
counter_end
print ustr$(eax)," cycles ", "CnvToRcl "
print offset _buffer9, 13, 10
print chr$(13, 10)
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data0, offset _buffer0
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer0, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data1, offset _buffer1
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer1, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data2, offset _buffer2
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer2, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data3, offset _buffer3
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer3, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data4, offset _buffer4
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer4, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data5, offset _buffer5
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer5, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data6, offset _buffer6
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer6, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data7, offset _buffer7
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer7, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data8, offset _buffer8
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer8, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke ddToRcl, _data9, offset _buffer9
counter_end
print ustr$(eax)," cycles ", "ddToRcl "
print offset _buffer9, 13, 10
;----------------------------------------------------
print chr$(13, 10)
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
dwtoa proc dwValue:DWORD, lpBuffer:DWORD
push ebx
push esi
push edi
mov eax, dwValue
mov edi, [lpBuffer]
test eax,eax
jnz sign
zero:
mov word ptr [edi],30h
jmp dtaexit
;
; Removed for unsigned numbers
;
sign:
; jns pos
; mov byte ptr [edi],'-'
; neg eax
; add edi, 1
pos:
mov ecx, 3435973837
mov esi, edi
.while (eax > 0)
mov ebx,eax
mul ecx
shr edx, 3
mov eax,edx
lea edx,[edx*4+edx]
add edx,edx
sub ebx,edx
add bl,'0'
mov [edi],bl
add edi, 1
.endw
mov byte ptr [edi], 0 ; terminate the string
; We now have all the digits, but in reverse order.
.while (esi < edi)
sub edi, 1
mov al, [esi]
mov ah, [edi]
mov [edi], al
mov [esi], ah
add esi, 1
.endw
dtaexit:
pop edi
pop esi
pop ebx
ret
dwtoa endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 16
CnvToRcl proc Val:DWORD, pBuf:DWORD
push ebx
push esi
push edi
mov eax, [esp+16] ; Val
mov edi, [esp+20] ; pBuf
test eax, eax
jnz short @F
mov dword ptr [edi - 4], 1
mov word ptr [edi], 30h
jz _exit
@@:
mov ecx, 3435973837
xor esi, esi
@@: mov ebx, eax
mul ecx
shr edx, 3
mov eax, edx
lea edx, [edx*4+edx]
add edx, edx
sub ebx, edx
add bl, '0'
;
push ebx ; To stack
add esi, 1
or eax, eax
jnz short @B
;»»»»»» Buffer length control »»»»»»»»»»
cmp esi, dword ptr [edi - 8]
jbe short _go
;
@@: pop eax ; Get from stack
sub esi, 1
jnz short @B
mov dword ptr [edi - 4], 0
mov byte ptr [edi], 0 ; terminate the string
stc
jc short _exit
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
_go: mov dword ptr [edi - 4], esi
@@: pop eax ; Get from stack
mov byte ptr [edi], al
add edi, 1
sub esi, 1
jnz short @B
mov byte ptr [edi], 0 ; terminate the string
clc
_exit: pop edi
pop esi
pop ebx
ret 8
CnvToRcl endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 16
ddToRcl proc Val:DWORD, pBuf:DWORD
movd mm0, ebx
movd mm1, esi
movd mm2, edi
mov eax, [esp+4] ; Val
mov edi, [esp+8] ; pBuf
test eax, eax
jnz short @F
mov dword ptr [edi - 4], 1
mov word ptr [edi], 30h
jz _exit
@@:
mov ecx, 3435973837
xor esi, esi
@@: mov ebx, eax
mul ecx
shr edx, 3
mov eax, edx
lea edx, [edx*4+edx]
add edx, edx
sub ebx, edx
add bl, '0'
;
push ebx ; To stack
add esi, 1
or eax, eax
jnz short @B
;»»»»»» Buffer length control »»»»»»»»»»
cmp esi, dword ptr [edi - 8]
jbe short _go
;
@@: pop eax ; Get from stack
sub esi, 1
jnz short @B
mov dword ptr [edi - 4], 0
mov byte ptr [edi], 0 ; terminate the string
stc
jc short _exit
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
_go: mov dword ptr [edi - 4], esi
@@: pop eax ; Get from stack
mov byte ptr [edi], al
add edi, 1
sub esi, 1
jnz short @B
mov byte ptr [edi], 0 ; terminate the string
clc
_exit:
movd ebx, mm0
movd esi, mm1
movd edi, mm2
ret 8
ddToRcl endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Quote
;dwtoa with sign control
;**********************
;195 cycles dwtoa 2147483647 178 cycles CnvToRcl 2147483647
;197 cycles dwtoa 1879048192 179 cycles CnvToRcl 1879048192
;186 cycles dwtoa 268042127 161 cycles CnvToRcl 268042127
;159 cycles dwtoa 16748447 208 cycles CnvToRcl 16748447
;144 cycles dwtoa 1019793 130 cycles CnvToRcl 1019793
;104 cycles dwtoa 36753 98 cycles CnvToRcl 36753
;49 cycles dwtoa 10 47 cycles CnvToRcl 10
;144 cycles dwtoa 1255780 129 cycles CnvToRcl 1255780
;19 cycles dwtoa 0 19 cycles CnvToRcl 0
;37 cycles dwtoa -1 182 cycles CnvToRcl 4294967295
;Press any key to exit...
;-----------------------------------------------------------
; dwtoa without sign control
; *************************
;195 cycles dwtoa 2147483647 183 cycles CnvToRcl 2147483647
;201 cycles dwtoa 1879048192 183 cycles CnvToRcl 1879048192
;189 cycles dwtoa 268042127 164 cycles CnvToRcl 268042127
;164 cycles dwtoa 16748447 153 cycles CnvToRcl 16748447
;144 cycles dwtoa 1019793 134 cycles CnvToRcl 1019793
;106 cycles dwtoa 36753 98 cycles CnvToRcl 36753
;52 cycles dwtoa 10 47 cycles CnvToRcl 10
;144 cycles dwtoa 1255780 128 cycles CnvToRcl 1255780
;20 cycles dwtoa 0 18 cycles CnvToRcl 0
;196 cycles dwtoa 4294967295 182 cycles CnvToRcl 4294967295
;177 cycles ddToRcl 2147483647
;177 cycles ddToRcl 1879048192
;160 cycles ddToRcl 268042127
;150 cycles ddToRcl 16748447
;124 cycles ddToRcl
;94 cycles ddToRcl 36753
;44 cycles ddToRcl 10
;127 cycles ddToRcl 1255780
;12 cycles ddToRcl 0
;176 cycles ddToRcl 4294967295
;Press any key to exit...
I want to count the number of decimal digits in the EAX register
I used NumDigEAX and CountDigEAX
Is there any other idea that gives better results ?
What are the results do you get with this code ?
Thanks.
Rui
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
.686
.mmx
include \masm32\macros\timers.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
_data0 dd 7FFFFFFFh ;0FFFFFFFFh
_data1 dd 70000000h ;4294967295
_data2 dd 0FF9FF8Fh ;3232323299
_data3 dd 00FF8F9Fh
_data4 dd 000F8F91h
_data5 dd 00008F91h
_data6 dd 10
_data7 dd 1255780
_data8 dd 0
_data9 dd 0FFFFFFFFh
dd 20 ; -8 max. string length
dd 0 ; -4 string length
_buffer0 db 20 dup (0)
db 0 ; can end with 0
;
dd 20
dd 0
_buffer1 db 20 dup (0)
db 0
dd 20
dd 0
_buffer2 db 20 dup (0)
db 0
dd 20
dd 0
_buffer3 db 20 dup (0)
db 0
dd 6 ; 6 <- with 6 the next buffer is protected
dd 0 ; using CnvToRcl
_buffer4 db 6 dup (0)
db 0
db 10 dup (0) ; protection
dd 9
dd 0
_buffer5 db 9 dup (0)
db 0
dd 20
dd 0
_buffer6 db 20 dup (0)
db 0
dd 20
dd 0
_buffer7 db 20 dup (0)
db 0
dd 20
dd 0
_buffer8 db 20 dup (0)
db 0
dd 20
dd 0
_buffer9 db 20 dup (0)
db 0
.code
; ###############################################
start:
;invoke Sleep, 40
; #################################################
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data0, offset _buffer0
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer0, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data1, offset _buffer1
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer1, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data2, offset _buffer2
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer2, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data3, offset _buffer3
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer3, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data4, offset _buffer4
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer4, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data5, offset _buffer5
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer5, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data6, offset _buffer6
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer6, 13, 10
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data7, offset _buffer7
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer7, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data8, offset _buffer8
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer8, 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
invoke dwtoa, _data9, offset _buffer9
counter_end
print ustr$(eax)," cycles ", "dwtoa "
print offset _buffer9, 13, 10
print chr$(13, 10)
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data0
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data1
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data2
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data3
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data4
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data5
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data6
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data7
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data8
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data9
call NumDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "NumDigEAX "
print ustr$(edi), 13, 10
print chr$(13, 10)
;+++++++++++++++++++++++++++++++++++++++++++++++++++++
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data0
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data1
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data2
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data3
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data4
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data5
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data6
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data7
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data8
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data9
call CountDigEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "CountDigEAX "
print ustr$(edi), 13, 10
print chr$(13, 10)
;+++++++++++++++++++++++++++++++++++++++++++++++++++++
; ««««««««««««««««««««««««««««««««««««««««««««««««««««
counter_begin 1000000, HIGH_PRIORITY_CLASS
mov eax, _data9
call DigCountEAX
mov edi, ecx
counter_end
print ustr$(eax)," cycles ", "DigCountEAX "
print ustr$(edi), 13, 10
;----------------------------------------------------
print chr$(13, 10)
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
dwtoa proc dwValue:DWORD, lpBuffer:DWORD
push ebx
push esi
push edi
mov eax, dwValue
mov edi, [lpBuffer]
test eax,eax
jnz sign
zero:
mov word ptr [edi],30h
jmp dtaexit
;
; Removed for unsigned numbers
;
sign:
; jns pos
; mov byte ptr [edi],'-'
; neg eax
; add edi, 1
pos:
mov ecx, 3435973837
mov esi, edi
.while (eax > 0)
mov ebx,eax
mul ecx
shr edx, 3
mov eax,edx
lea edx,[edx*4+edx]
add edx,edx
sub ebx,edx
add bl,'0'
mov [edi],bl
add edi, 1
.endw
mov byte ptr [edi], 0 ; terminate the string
; We now have all the digits, but in reverse order.
.while (esi < edi)
sub edi, 1
mov al, [esi]
mov ah, [edi]
mov [edi], al
mov [esi], ah
add esi, 1
.endw
dtaexit:
pop edi
pop esi
pop ebx
ret
dwtoa endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Output:
; ECX - nº de dígitos
;
align 16
NumDigEAX proc
push eax
push ebx
push edx
push esi
test eax, eax
jnz short @F
mov esi, 1
jz _exit
@@:
mov ecx, 3435973837
xor esi, esi
@@: mov ebx, eax
mul ecx
shr edx, 3
mov eax, edx
lea edx, [edx*4+edx]
add edx, edx
sub ebx, edx
add bl, '0'
;
add esi, 1
or eax, eax
jnz short @B
_exit: mov ecx, esi
;
pop esi
pop edx
pop ebx
pop eax
ret
NumDigEAX endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Output:
; ECX - nº de dígitos
;
align 16
CountDigEAX proc
movd mm0, eax
movd mm1, ebx
movd mm2, edx
movd mm3, esi
test eax, eax
jnz short @F
mov esi, 1
jz _exit
@@:
mov ecx, 3435973837
xor esi, esi
@@: mov ebx, eax
mul ecx
shr edx, 3
mov eax, edx
lea edx, [edx*4+edx]
add edx, edx
sub ebx, edx
add bl, '0'
;
add esi, 1
or eax, eax
jnz short @B
_exit: mov ecx, esi
;
movd eax, mm0
movd ebx, mm1
movd edx, mm2
movd esi, mm3
ret
CountDigEAX endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 16
DigCountEAX proc
push eax
push ebx
push edx
;
mov ebx, 10
xor ecx, ecx
jz short _next
;
@@: xor edx, edx
div ebx
add ecx, 1
;
_next: or eax, eax
jnz short @B
;
pop edx
pop ebx
pop eax
ret
DigCountEAX endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Quote
;195 cycles NumDigEAX 10 144 cycles CountDigEAX 10
;196 cycles NumDigEAX 10 146 cycles CountDigEAX 10
;180 cycles NumDigEAX 9 130 cycles CountDigEAX 9
;163 cycles NumDigEAX 8 116 cycles CountDigEAX 8
;148 cycles NumDigEAX 7 101 cycles CountDigEAX 7
;122 cycles NumDigEAX 5 74 cycles CountDigEAX 5
;34 cycles NumDigEAX 2 31 cycles CountDigEAX 2
;150 cycles NumDigEAX 7 102 cycles CountDigEAX 7
;14 cycles NumDigEAX 1 9 cycles CountDigEAX 1
;192 cycles NumDigEAX 10 145 cycles CountDigEAX 10
;631 cycles DigCountEAX 10
;Press any key to exit...
Hi Rui,
Here is a quick attempt at a fast digit counting procedure. I did not have time to try and optimize it.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
.686
include \masm32\macros\timers.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
digits proc
mov edx, eax
xor eax, eax
N=10
REPEAT 9
inc eax
cmp edx, N
jb @F
N=N*10
ENDM
inc eax
@@:
ret
digits endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
N=1
REPEAT 10
print ustr$(N)," "
mov eax, N
call digits
print ustr$(eax),13,10
N=N*10
ENDM
print chr$(13,10)
invoke Sleep, 3000
N=1
REPEAT 10
print ustr$(N)," "
counter_begin 1000, HIGH_PRIORITY_CLASS
mov eax, N
call digits
counter_end
print ustr$(eax)," cycles",13,10
N=N*10
ENDM
print chr$(13,10)
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Here is the code generated for the procedure:
00401000 fn_00401000:
00401000 8BD0 mov edx,eax
00401002 33C0 xor eax,eax
00401004 40 inc eax
00401005 83FA0A cmp edx,0Ah
00401008 7246 jb loc_00401050
0040100A 40 inc eax
0040100B 83FA64 cmp edx,64h
0040100E 7240 jb loc_00401050
00401010 40 inc eax
00401011 81FAE8030000 cmp edx,3E8h
00401017 7237 jb loc_00401050
00401019 40 inc eax
0040101A 81FA10270000 cmp edx,2710h
00401020 722E jb loc_00401050
00401022 40 inc eax
00401023 81FAA0860100 cmp edx,186A0h
00401029 7225 jb loc_00401050
0040102B 40 inc eax
0040102C 81FA40420F00 cmp edx,0F4240h
00401032 721C jb loc_00401050
00401034 40 inc eax
00401035 81FA80969800 cmp edx,989680h
0040103B 7213 jb loc_00401050
0040103D 40 inc eax
0040103E 81FA00E1F505 cmp edx,5F5E100h
00401044 720A jb loc_00401050
00401046 40 inc eax
00401047 81FA00CA9A3B cmp edx,3B9ACA00h
0040104D 7201 jb loc_00401050
0040104F 40 inc eax
00401050 loc_00401050:
00401050 C3 ret
And here are the results on my P3:
1 1
10 2
100 3
1000 4
10000 5
100000 6
1000000 7
10000000 8
100000000 9
1000000000 10
1 3 cycles
10 3 cycles
100 5 cycles
1000 7 cycles
10000 7 cycles
100000 11 cycles
1000000 12 cycles
10000000 13 cycles
100000000 15 cycles
1000000000 14 cycles
Edit:
I made the obvious optimization of removing the last comparison and conditional jump.
Hi all,
Hello MichaelW !
Thank you !
We dont need quick attemps, Michael . We have time to do it, may be tommorow !
Or tommorrow ... Thank you
MichaelW, what can we do with mmx registers ? movd, movq and what else ?
Could anyone test digitos2.exe (see bellow) and show the results here
Thanks
Rui
Here are my results on P4 XP, sp3:
Quote
35 cycles dwtoa 9
49 cycles dwtoa 99
69 cycles dwtoa 999
85 cycles dwtoa 9999
107 cycles dwtoa 99999
122 cycles dwtoa 999999
144 cycles dwtoa 9999999
158 cycles dwtoa 99999999
181 cycles dwtoa 999999999
41 cycles dwtoa -1
20 cycles NumDigEAX 1
35 cycles NumDigEAX 2
86 cycles NumDigEAX 3
109 cycles NumDigEAX 4
122 cycles NumDigEAX 5
136 cycles NumDigEAX 6
150 cycles NumDigEAX 7
163 cycles NumDigEAX 8
176 cycles NumDigEAX 9
191 cycles NumDigEAX 10
17 cycles CountDigEAX 1
31 cycles CountDigEAX 2
44 cycles CountDigEAX 3
59 cycles CountDigEAX 4
73 cycles CountDigEAX 5
87 cycles CountDigEAX 6
102 cycles CountDigEAX 7
115 cycles CountDigEAX 8
130 cycles CountDigEAX 9
145 cycles CountDigEAX 10
621 cycles DigCountEAX 10
9 cycles CountDigits 1
5 cycles CountDigits 2
11 cycles CountDigits 3
9 cycles CountDigits 4
9 cycles CountDigits 5
14 cycles CountDigits 6
15 cycles CountDigits 7
17 cycles CountDigits 8
20 cycles CountDigits 9
17 cycles CountDigits 10
8 cycles CountDigit 1
9 cycles CountDigit 2
6 cycles CountDigit 3
11 cycles CountDigit 4
10 cycles CountDigit 5
13 cycles CountDigit 6
15 cycles CountDigit 7
12 cycles CountDigit 8
17 cycles CountDigit 9
13 cycles CountDigit 10
8 cycles digits 1
9 cycles digits 2
6 cycles digits 3
9 cycles digits 4
10 cycles digits 5
12 cycles digits 6
16 cycles digits 7
16 cycles digits 8
20 cycles digits 9
17 cycles digits 10
Press any key to exit...
[attachment deleted by admin]
Here are the results on my Intel Celeron CPU E1200 at 1.60Ghz
Ram : 3Gb - Video Card : NVIDIA GeForce 7300 LE
19 cycles dwtoa 9
26 cycles dwtoa 99
35 cycles dwtoa 999
43 cycles dwtoa 9999
54 cycles dwtoa 99999
61 cycles dwtoa 999999
70 cycles dwtoa 9999999
76 cycles dwtoa 99999999
90 cycles dwtoa 999999999
19 cycles dwtoa -1
5 cycles NumDigEAX 1
11 cycles NumDigEAX 2
18 cycles NumDigEAX 3
27 cycles NumDigEAX 4
35 cycles NumDigEAX 5
45 cycles NumDigEAX 6
52 cycles NumDigEAX 7
62 cycles NumDigEAX 8
79 cycles NumDigEAX 9
85 cycles NumDigEAX 10
5 cycles CountDigEAX 1
12 cycles CountDigEAX 2
19 cycles CountDigEAX 3
28 cycles CountDigEAX 4
36 cycles CountDigEAX 5
45 cycles CountDigEAX 6
53 cycles CountDigEAX 7
62 cycles CountDigEAX 8
73 cycles CountDigEAX 9
84 cycles CountDigEAX 10
299 cycles DigCountEAX 10
2 cycles CountDigits 1
3 cycles CountDigits 2
3 cycles CountDigits 3
4 cycles CountDigits 4
4 cycles CountDigits 5
5 cycles CountDigits 6
6 cycles CountDigits 7
7 cycles CountDigits 8
8 cycles CountDigits 9
8 cycles CountDigits 10
2 cycles CountDigit 1
3 cycles CountDigit 2
2 cycles CountDigit 3
4 cycles CountDigit 4
4 cycles CountDigit 5
5 cycles CountDigit 6
6 cycles CountDigit 7
7 cycles CountDigit 8
8 cycles CountDigit 9
8 cycles CountDigit 10
2 cycles digits 1
3 cycles digits 2
3 cycles digits 3
4 cycles digits 4
4 cycles digits 5
5 cycles digits 6
6 cycles digits 7
7 cycles digits 8
8 cycles digits 9
8 cycles digits 10
Press any key to exit...
These results are more than correct for me.
The subject of determining the number of decimal digits for a hex number came up on the other board. You may want to try the procedure I proposed. It is applicable to integers up to 64 bits. It is based on lookup tables and should definitely be much quicker.
http://www.asmcommunity.net/board/index.php?topic=29155.new;topicseen#new