I was wondering if there is a library/Win32API out there that will convert any value to baseX and convert that again to ascii?

If not, I could post some code. I was asking, because I don't want to repeat some stuff that's already done :)
Posted on 2002-01-18 01:04:41 by stryker
The variety is good - post away.
Posted on 2002-01-18 10:14:57 by bitRAKE
Ok!


ToBaseXToAscii PROC USES esi intVal:UINT, baseX:UINT, ptBuffer:LPCSTR

mov eax, intVal
mov esi, ptBuffer
xor ecx, ecx

@@:
xor edx, edx
div baseX
push edx
inc ecx
or eax, eax
jne @b

mov eax, ecx
xor ecx, ecx

;intead of the 2 instructions above (mov...xor...)
;use xchg eax, ecx much more easier and less use of
;instructions.

@@:
pop edx
add dl, 48
mov BYTE ptr [esi+ecx], dl
inc ecx
dec eax
;or eax, eax ;Optional, added overhead
jne @b

mov BYTE ptr [esi+ecx], al

ret

ToBaseXToAscii ENDP


Prototype:ToBaseXToAscii PROTO stdcall :DWORD, :DWORD, :DWORD
Usage Example: invoke ToBaseXToAscii, eax, 10, OFFSET Bfr

intVal: Value to be converted
baseX: Convert to what base
ptBuffer: Pointer to a character string

As you can see, this code isn't optimized yet :) - I don't even know if its well optimized. It doesn't even preserved the registers. Anyway, anybody wants it can have it. This is a part of my homework in C that I converted.

Notice something: I'm using MASM now ... gotta ditch TASM because of mmx...long story. :)
Posted on 2002-01-18 11:02:46 by stryker
Nice method! I dont know much about opomizations as well, but from what i can tell its "tight" enough for me to like it!

Good Work!
:alright:
NaN
Posted on 2002-01-18 11:44:19 by NaN
Thanks, Nan!. In addition, there is no return value from the procedure. The output will be in the buffer. Also, you have to make sure the buffer is large enough to hold the character string, because it doesn't check if it will be succesful or not. Don't forget to preserve registers. :)

If you want to convert something to plain ascii, i mean if the intVal is 1234d and you want it to be 1234 in ascii, just pass the value 10 to baseX
Posted on 2002-01-18 12:40:04 by stryker
umberg6007,

Looks good! I'm still playing with it, but may I suggest: Push esi at the beginning and Pop esi at the end to preserve that register. That's the rule. I've screwed up so many times--and still do--that I've started to notice.

You can also use:

uses esi

farrier
Posted on 2002-01-18 14:24:11 by farrier
I've changed the code above. Thanks!!!(I knew somebody would notice :) )
Posted on 2002-01-18 14:58:24 by stryker


dec eax
or eax, eax
jne @b


i think u could change this to....



dec eax
jne @b


better than nothing! :)

cyaz

jean (coder7345)
Posted on 2002-01-18 17:08:17 by coder
Yes, I didn't notice that one...Thanks coder7345
Posted on 2002-01-18 17:12:35 by stryker
to the code be more tiny.... here are another things u may change, this:



mov eax, ecx
xor ecx, ecx

@@:
pop edx
add dl, 48
mov BYTE ptr [esi+ecx], dl
inc ecx
dec eax
;or eax, eax ;Optional, added overhead
jne @b

mov BYTE ptr [esi+ecx], 0


to....



xchg eax, ecx ;eax should be null or the loop don't gonna end... :)

@@:
pop edx
add dl, 48
mov BYTE ptr [esi+ecx], dl
inc ecx
dec eax
;or eax, eax ;Optional, added overhead
jne @b

mov BYTE ptr [esi+ecx], al ;<---- change the 0 to al remember to use registers everytime that u can


hoppe it help... :)

cyas

jean (coder7345)
Posted on 2002-01-18 17:28:48 by coder


mov eax, ecx
xor ecx, ecx


on a 486 cpu, this one will save me 1 clock but will add 1 byte. If I use xchg, I'll add 1 clock but will save me 1 byte. So there is a tradeoff here...But in a 386 xchg is much faster than the two instructions up there :) . I love assembly, even a byte or clock is very important :). So this one is kinda balance between a byte and clock cycle. On a 486 If you favor 1 byte less in your exe use the xchg, if you favor speed(less 1 clock cycle) use the mov...xor... On a 386, use xchg.

As for last one(terminating character), that is the right one, it should be al...I was thinking of the terminating character so I added 0...I should have notice that one before since eax is already 0 when it exits the loop... Thanks.
Posted on 2002-01-18 17:48:56 by stryker
Hi again!
I take a look on the code again, and i've notice that if u try to convert to base 16 of hex, it give u the wrong hex chars (A,B,C,D,E and F) NOT the numbers. Soo i try to fix this "bug", as i try to improve the code... with some bechmarking i get this:
50000 "calls" always with random numbers (GetTickCount), and the baseX was 10.
Your normal code: 35.5 mili-seconds (average)
Your code with hex chars support and speed improved: 34 mili-seconds (average)
Your code with hex chars support and size improved: 38.3 mili-seconds (average)
This times gonna be diferent if i put the code inside a proc (with reg saves) and make calls to it.

Wanna see the code? check it out...



BaseXToAscii PROC USES edi edx ecx ebx intVal:UINT, baseX:UINT, ptBuffer:LPCSTR

mov ebx,offset numberstable
mov eax,intVal
mov edi,ptBuffer
xor ecx,ecx
@@: xor edx,edx
div baseX ; 486 -> 40 Clocks!!! (damm! (using regs is the same))
push edx
inc ecx
or eax,eax
jne @b
@@: pop eax
;---------------------------------; Saves 2 bytes ------------------------------
; XLATB ; 486 -> 4 clocks (386 -> 5 clocks) | 1 byte
;=================================; Saves 3 clocks
mov al,byte ptr [ebx+eax] ; 486 -> 1 clock (?) | 3 bytes
;-------------------------------------------------------------------------------

;---------------------------------; Saves 2 bytes ------------------------------
; STOSB ; 486 -> 5 clocks | 1 byte
;=================================; Saves 3 Clocks
mov byte ptr [edi],al ; 486 -> 1 clock | 2 bytes
inc edi ; 486 -> 1 clock | 1 byte
;-------------------------------------------------------------------------------

;---------------------------------; Saves 1 byte ------------------------------
; Loop @B ; 486 -> 6 clocks | 2 bytes
;=================================; Saves 2 clocks
dec ecx ; 486 -> 1 clock | 1 byte
jnz @b ; 486 -> 3 clocks | 2 bytes
;-------------------------------------------------------------------------------

mov BYTE ptr [edi], cl
ret

numberstable db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

BaseXToAscii ENDP

Chose what u want... slimness or faster.

I like this code coz it can convert any value to the most used bases (Bin, Dec and Hex) strings quickly, the same proc does >3 jobs.
That division is the magic of this code :) but it is takes to long to execute. I don't understand anything about FPU instructions (by now..) but i think that replacing DIV be a FDIVP the code gonna execute more fastly.

Why don't u put here your code to convert ASCII to Hex, Dec, or Bin, so we can take a look? ;)
MASM brings some pieces of code on is M32LIB path that convert a number to SZ and again to numbers, but your code may be better/faster.

bye

jEAN (Coder7345)
Posted on 2002-01-19 16:26:44 by coder
While im happy this Question has spawned a good following, im of the opinion this discussion might be better suited to finish where you can "place your little gems, for all to use."

(moving it to the Algorithms section.)
:alright:
NaN
Posted on 2002-01-19 23:18:24 by NaN
That's the right one coder7345. That PROC has much better accuracy... :) Mine flops when it comes to hex :)
Posted on 2002-01-20 09:49:30 by stryker