News:

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

Shouldn't ustr$ do unsigned conversion?

Started by Phil, June 21, 2005, 04:59:30 AM

Previous topic - Next topic

Phil

I just noticed that the ustr$ macro invokes dwtoa which does signed conversion. Shouldn't it invoke udw2str instead? The only problem that I can see with using udw2str is that it doesn't store the final null byte. Also, the current library version needs to use the scaled approximation of 1/10 to avoid rounding problems that show up in numbers greater than 1000000000.

Also, why does sstr$ invoke wsprintf instead of just using the dwtoa procedure to do it's signed conversion?

MichaelW

Yes, I also noticed this about ustr$ for the first time when I was testing udw2str.


eschew obfuscation

hutch--

Thanks for pointing this one out Phil, I rarely ever work on conversions and it always stuck in my head that dwtoa was unsigned.

This will solve the problem in the short term.


main proc

    LOCAL buf   :DWORD
    LOCAL buffer[16]:BYTE

    mov buf, ptr$(buffer)

    invoke crt__ultoa,0FFFFFFFFh,buf,10

    print buf,13,10

    ret

main endp
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

Here is the tweak of the two macros.


      ustr$ MACRO DDvalue   ;; unsigned integer from string
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        ;; invoke dwtoa,DDvalue,ADDR rvstring
        invoke crt__ultoa,DDvalue,rvstring,10
        EXITM <OFFSET rvstring>
      ENDM

      sstr$ MACRO DDvalue   ;; signed integer from string
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        invoke dwtoa,DDvalue,ADDR rvstring
        ;; invoke ltoa,DDvalue,ADDR rvstring
        EXITM <OFFSET rvstring>
      ENDM


If anyone has the time to verify them, it would be appreciated.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MichaelW

After correcting an obvious error, I tested both of the tweaked macros against crt_atoi64 and the results were identical over the full range of values.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

     _ustr$ MACRO DDvalue   ;; unsigned integer to string <modified>
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        ;; invoke dwtoa,DDvalue,ADDR rvstring
        invoke crt__ultoa,DDvalue,ADDR rvstring,10    ; <added ADDR>
        EXITM <OFFSET rvstring>
      ENDM

      _sstr$ MACRO DDvalue   ;; signed integer to string <modified>
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        invoke dwtoa,DDvalue,ADDR rvstring
        ;; invoke ltoa,DDvalue,ADDR rvstring
        EXITM <OFFSET rvstring>
      ENDM
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        i64     dq 0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    invoke GetTickCount
    push  eax

    ;xor   ebx,ebx
    ;.WHILE (ebx < 0ffffffffh)

    mov   ebx,0ffffffffh
    .WHILE (ebx)
       
        mov   esi, _ustr$(ebx)
        invoke crt__atoi64, esi
        .IF (eax != ebx)
            print "_ustr$ error",13,10
            .BREAK
        .ENDIF
        ;inc   ebx
        dec   ebx
        test  ebx, 0fffffh
        jnz   @F
        print esi, 13, 10 ; pacifier every 1048576 values
      @@:
    .ENDW

    invoke GetTickCount
    pop   ebx
    sub   eax, ebx
    print ustr$(eax),'ms',13,10

    invoke GetTickCount
    push  eax

    ;xor   ebx,ebx
    ;.WHILE (ebx < 0ffffffffh)

    mov   ebx,0ffffffffh
    .WHILE (ebx)
       
        mov   esi, _sstr$(ebx)
        invoke crt__atoi64, esi
        .IF (eax != ebx)
            print "_sstr$ error", 13, 10
            .BREAK
        .ENDIF
        ;inc   ebx
        dec   ebx

        test  ebx, 0fffffh
        jnz   @F
        print esi, 13, 10 ; pacifier every 1048576 values
      @@:
    .ENDW

    invoke GetTickCount
    pop   ebx
    sub   eax, ebx
    print ustr$(eax),'ms',13,10


    mov   eax, input(13, 10, "Press enter to exit...")
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation

Jimg

Shouldn't ustr$ use an unsigned dwtoa?  e.g.-
dwtoau proc dwValue:DWORD, lpBuffer:DWORD   ; slightly modified from what masm32 lib's dwtoa

    push ebx
    push esi
    push edi

    mov eax, dwValue
    mov edi, [lpBuffer]

    test eax,eax
    jnz nonzero

    mov word ptr [edi],30h
    jmp dtaexit

nonzero:
    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
    .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
dwtoau endp


Phil

Yes, ustr$ should do unsigned conversion. Also, there is a problem with the precision in the current library routine that does unsigned conversion. Here's a link to a previous discussion: http://www.masmforum.com/simple/index.php?topic=1961.msg15406#msg15406


Jimg

Right.  This one is identical as it came from the same corrected dwtoa.  Sorry for the duplication.