News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

DWordToDec

Started by bananix, September 12, 2005, 01:08:48 PM

Previous topic - Next topic

bananix

I used to do some assembly years ago and I tried to optimize this DWord to Dec conversion (or is it to string conversion =)...I'm just interested to know if I was on to something...but I suspect my code is ridiculous :lol

I think the original was 16bit code for Word to Dec conversion and this is conversion to 32bit of it and don't even remember if it works or for what I used it  :lol


DWordToDec proc src:DWORD, pdst:DWORD
        push    ebx
        push    ecx
        push    edx
        mov     ecx,1
        mov     ebx,pdst
        mov     eax,src
        cmp     ebx,0
        je      DWordToDec_Err
        cmp     eax,0
        je      DWordToDec_Err
        jmp     @F
        DWordToDec_10_  dd 1000000000
        DWordToDec_9_   dd 100000000
        DWordToDec_8_   dd 10000000
        DWordToDec_7_   dd 1000000
        DWordToDec_6_   dd 100000
        DWordToDec_5_   dd 10000
        DWordToDec_4_   dd 1000
        DWordToDec_3_   dd 100
        DWordToDec_2_   dd 10
    @@:
        cmp     eax,10
        jb      DWordToDec_1
        cmp     eax,100
        jb      DWordToDec_2
        cmp     eax,1000
        jb      DWordToDec_3
        cmp     eax,10000
        jb      DWordToDec_4
        cmp     eax,100000
        jb      DWordToDec_5
        cmp     eax,1000000
        jb      DWordToDec_6
        cmp     eax,10000000
        jb      DWordToDec_7
        cmp     eax,100000000
        jb      DWordToDec_8
        cmp     eax,1000000000
        jb      DWordToDec_9
        div     DWordToDec_10_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,10
        mov     eax,edx
    DWordToDec_9:
        div     DWordToDec_9_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,9
        mov     eax,edx
    DWordToDec_8:
        div     DWordToDec_8_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,8
        mov     eax,edx
    DWordToDec_7:
        div     DWordToDec_7_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,7
        mov     eax,edx
    DWordToDec_6:
        div     DWordToDec_6_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,6
        mov     eax,edx
    DWordToDec_5:
        div     DWordToDec_5_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,5
        mov     eax,edx
    DWordToDec_4:
        div     DWordToDec_4_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,4
        mov     eax,edx
    DWordToDec_3:
        div     DWordToDec_3_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        mov     ecx,3
        mov     eax,edx
    DWordToDec_2:
        div     DWordToDec_2_
        add     eax,'0'
        mov     [ebx],al
        inc     ebx
        inc     ecx
        mov     eax,edx
    DWordToDec_1:
        add     eax,'0'
        mov     [ebx],al
        mov     eax,ecx
        pop     edx
        pop     ecx
        pop     ebx
        ret
    DWordToDec_Err:
        mov     eax,0
        pop     edx
        pop     ecx
        pop     ebx
        ret
DWordToDec endp

AeroASM

About the naming:

DwordToDecimal is obviously wrong because dword is a size whereas decimal is a base. A correct name would be NumberToString.

About the function:

At first glance it looks very dodgy.

Snouphruh

check this out:


szBuffer         db 10 dup (0), 0         ; reserve 10 bytes (chars) for converting, 'cause eax can hold 10 digits max.
.....
                    mov eax, 2637488436 ; value to be converted to a string
                    mov edi, szBuffer + 9   ; pointer to the last char in the buffer
                    call myInt2Str
.....
myInt2Str:
                    xor ecx, ecx
                    xor ebx, ebx
                    mov cl, 5
                    mov bl, 100
ll_myI2S_Loop:
                    xor edx, edx               ; zero edx
                    div ebx                       ; here eax = 26374884 and edx = 36
                    xchg eax, edx             ; eax = 36, edx = 26374884
                    aam                           ; eax = 0306h, e. g. ah = 3, al = 6
                    or eax, 3030h             ; ah = '3', al = '6'
                    mov byte ptr [edi], al   ; store al into the buffer
                    dec edi                      ; decrement pointer to the previous char
                    mov byte ptr [edi], ah ; store ah into the buffer
                    dec edi                      ; decrement pointer to the previous char
                    mov eax, edx              ; eax = 26374884
                    dec ecx
                    jnz ll_myI2S_Loop        ; loop
                    retn

gabor

Hello!

Another method (recursive) I learnt some years ago. The base must be equal or less than 16.


Int2Str       PROC USES ebx edx edi Number:DWORD,Base:DWORD,lpString:DWORD
; a wrapper for the recursive procedure
; saves registers, loads initial values
              mov  eax,Number
              mov  ebx,Base
              mov  edi,lpString
              call @_Int2Str1
              ret
Int2Str       ENDP

@_Int2Str1:
              xor  edx,edx
              div  ebx              ; edx: remainder=a digit from the end
              or   eax,eax
              jz @_Int2Str2
              push edx              ; save the digit for later
              call @_Int2Str
              pop  edx
@_Int2Str2:
              cmp  dl,0Ah           ; decimal digit?
              jc @_Int2Str3
              add  dl,'A'-'0'       ; digits greater than 9 are represented as letters
@_Int2Str3:
              add  dl,'0'           ; convert digit into character
              mov  [edi],dl         ; store the digit
              inc  edi
              ret



I guess calling this function DWORD2DEC is not really a mistake, since DWORD can be interpreted as a type of INT (long I think), and DEC is referring to the representation of the number in the output string...But this comment does really not matter!

Greets, Gábor

Larry Hammick

A variation of gabor's way:

DumpEAXDecimal:    ;to asciiz at edi, return edi pointing at terminal null
    push eax
    push edx
    push ebx
    xor edx,edx
    push edx     ;a terminator
    mov ebx,10
@@: div ebx
    add dl,"0"   ;equivalent is "or dl,30h"
    push edx
    cdq              ;make edx zero
    or eax,eax
    jnz short @B
@@: pop eax
    stosb     ;possibly a null
    or eax,eax
    jnz short @B
    dec edi
    pop ebx
    pop edx
    pop eax
    retn

Instead of stosb you can call an output routine. If you don't want to pass the terminator zero, a simple revision is needed.