He everybody, hope somebody finds this useful, if not maybe next time hehe,
I needed a method to put commas in my decimal numbers awhile ago cuz otherwise they way too hard to read. So I looked around but didn't find anything so I came up with this algo. It starts at the most significant end of the number thus overcoming some problems. It works quite good:) It is based on the observation that if any integer is divided by 3 the remainder (edx) follows this pattern:
edx = 0 then first comma is 3 places counting from left
edx = 2 then first comma is 2 places counting from left
edx = 1 then first comma is 1 places counting from left
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;adds comma delimiters where required
;szNumber is equal to decimal number e.g 49152
;dwNumberDigits is string length
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CommaProc proc uses edi edx szNumber:DWORD,dwNumberDigits:DWORD
LOCAL buffer[256]:BYTE
mov eax,dwNumberDigits
cmp eax,03h ;if only three digits no commas
jle @fini
mov ecx,03h
xor edx,edx
div ecx
xor ecx,ecx
mov ecx,dwNumberDigits
.if edx==00h
add edx,03h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter1
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter1:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.elseif edx==01h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter2
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter2:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.elseif edx==02h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter3
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter3:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.endif
@end:
mov eax,00h
stosb
invoke lstrcpy,Addr szTotalBytes,Addr buffer
;this is your new comma delimited decimal
; number, do what you want
@fini:
ret
CommaProc endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I needed a method to put commas in my decimal numbers awhile ago cuz otherwise they way too hard to read. So I looked around but didn't find anything so I came up with this algo. It starts at the most significant end of the number thus overcoming some problems. It works quite good:) It is based on the observation that if any integer is divided by 3 the remainder (edx) follows this pattern:
edx = 0 then first comma is 3 places counting from left
edx = 2 then first comma is 2 places counting from left
edx = 1 then first comma is 1 places counting from left
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;adds comma delimiters where required
;szNumber is equal to decimal number e.g 49152
;dwNumberDigits is string length
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CommaProc proc uses edi edx szNumber:DWORD,dwNumberDigits:DWORD
LOCAL buffer[256]:BYTE
mov eax,dwNumberDigits
cmp eax,03h ;if only three digits no commas
jle @fini
mov ecx,03h
xor edx,edx
div ecx
xor ecx,ecx
mov ecx,dwNumberDigits
.if edx==00h
add edx,03h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter1
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter1:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.elseif edx==01h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter2
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter2:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.elseif edx==02h
lea edi,buffer
mov esi,szNumber
@@:
cmp ecx,00h
jz @end
cmp edx,00h
jz @AddDelimiter3
lodsb
stosb
sub ecx,01h
sub edx,01h
jmp @b
@AddDelimiter3:
mov eax,2ch
stosb
mov edx,03h
jmp @b
.endif
@end:
mov eax,00h
stosb
invoke lstrcpy,Addr szTotalBytes,Addr buffer
;this is your new comma delimited decimal
; number, do what you want
@fini:
ret
CommaProc endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
This is more than 20 times faster:
The Svin ?
InsertComma proc len,lpszStringIn,lpStringOut
mov esi,lpszStringIn
mov edi,lpszStringOut
mov ecx,-1
mov eax,len
@@: inc ecx
sub eax,3
jnbe @B
test ecx,ecx ;if length less than 4
je lastmove
mov edx,[esi]
add eax,3
mov [edi],edx
add esi,eax
mov byte ptr [edi][eax],2Ch
dec ecx
lea edi,[edi][eax][1]
je lastmove
@@: mov eax,[esi]
add esi,3
mov al,2Ch
dec ecx
mov [edi],eax
lea edi,[edi][4]
jne @B
lastmove:
mov eax,[esi]
mov [edi],eax
ret
InsertComma endp
Thanks guys !
I have seen a C code from Jeffrey Richter that does that things too... I don't remember if it uses the same method but it can be worth a look...
I have seen a C code from Jeffrey Richter that does that things too... I don't remember if it uses the same method but it can be worth a look...