Reputation: 45
I have a number stored in memory as ASCII and want to convert it to its binary value (multiplied by 100).
so 1.23 may be stored in memory in ASCII as 0x312E3233 and this should be converted to the binary value 123.
I currently have the following but is there a more efficient way?
mov eax,[esi]
xor eax, 0x302E3030
mov edx, eax
and edx, 0x000000FF
shr eax,8
jz skip
mov ecx,eax
and ecx, 0x000000FF
imul ecx, 10
add edx, ecx
shr eax,8
jz skip
shr eax,8
imul eax,100
add edx, eax
skip:
The ascii source is referenced by esi.
At the point of the label "skip", edx has the binary value.
Upvotes: 2
Views: 1781
Reputation: 39166
It's best to not include those conditional jumps if the routine can work with zero values. BSWAP should be faster than 2 times shifting by 8. IMUL could be changed into LEA/ADD combo.
mov eax,[esi]
mov edx,eax
and edx,0x0000000F
mov ecx,eax
shr ecx,8
and ecx,0x0000000F
;;;imul ecx,10
lea ecx,[ecx+ecx*4]
add ecx,ecx
add edx,ecx
bswap eax
and eax,0x0000000F
;;;imul eax,100
lea eax,[eax+eax*4]
add eax,eax
lea eax,[eax+eax*4]
add eax,eax
add edx,eax
skip:
EDIT
The original question never stated that the input range would be [0.00,1.00]. In fact the example given (1.23) lies outside this range and so I understood the full range was implied. That's the main reason that I no longer included those conditional jumps.
Testing everyone's codes on a Pentium 133 in real address mode revealed these execution times.
sudhanshu bahuguna Rudy Velthuis user3144770
[0.00,9.99] 19.640 sec 18.921 sec 19.161 sec
[0.00,1.00] 13.244 sec 11.460 sec 19.161 sec
After several tests I found that replacing imul ecx,10
with the well-known LEA/ADD combo was very profitable. Replacing imul eax,100
on the other hand made things worse (by approximately the same amount). I realised that given a limited input range the last jz skip
is crucial. So I introduced all these findings in both answers and got these execution times.
sudhanshu bahuguna Rudy Velthuis (2) user3144770 (2)
[0.00,9.99] 19.640 sec 17.843 sec 17.364 sec
[0.00,1.00] 13.244 sec 11.448 sec 12.035 sec
Still not overwhelmed by these results I conjured up a much faster solution that always executes in 9.580 sec.
movzx eax, byte [esi+3]
add eax,eax
lea eax,[eax+eax*4-480]
add al,[esi+1]
add eax,eax
lea eax,[eax+eax*4-480]
movzx edx, byte [esi]
lea edx,[eax+edx-48]
Upvotes: 2
Reputation: 28806
A few simple things could improve this a little. Get rid of the comparatively slow imul
and use lea
and add
:
mov eax,[esi]
xor eax,0x302E3030
mov edx,eax
jz skip
and edx,0x000000FF
shr eax,8
jz skip
mov ecx,eax
and ecx,0x000000FF
lea ecx,[ecx+4*ecx]
add ecx,ecx
add edx,ecx
shr eax,8
jz skip
shr eax,8
lea eax,[eax+4*eax]
lea eax,[eax+4*eax]
add eax,eax
add eax,eax
add edx,eax
skip:
On modern processors, it probably doesn't make a huge difference, but it should still be noticeable.
Upvotes: 0