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?
Yes, I also noticed this about ustr$ for the first time when I was testing udw2str.
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
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.
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
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
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
Right. This one is identical as it came from the same corrected dwtoa. Sorry for the duplication.