News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

atou_ex 64bit version

Started by fearless, April 25, 2015, 10:04:50 AM

Previous topic - Next topic

habran

Here is one with the counter:

  atou_ex PROC FRAME String:QWORD   
    xor eax,eax
    xor edx,edx
  .repeat
    movzx r8, BYTE PTR [rcx+rdx]
    .if (!r8)
      mov rcx, -1          ; non zero in RCX for success
      jmp done
    .endif
    lea rax, [rax+rax*4]
    lea rax, [r8+rax*2-48]
    inc edx
  .until (edx==20)
  xor ecx,ecx              ;zero means out of range error
done:     
    ret                    ; rax contains the number
atou_ex endp

atou_ex:
0000000000981147 33 C0                xor         eax,eax 
0000000000981149 33 D2                xor         edx,edx 
000000000098114B 4C 0F B6 04 0A       movzx       r8,byte ptr [rdx+rcx] 
0000000000981150 4D 85 C0             test        r8,r8 
0000000000981153 75 09                jne         atou_ex+17h (098115Eh) 
0000000000981155 48 C7 C1 FF FF FF FF mov         rcx,0FFFFFFFFFFFFFFFFh 
000000000098115C EB 12                jmp         atou_ex+29h (0981170h) 
000000000098115E 48 8D 04 80          lea         rax,[rax+rax*4] 
0000000000981162 49 8D 44 40 D0       lea         rax,[r8+rax*2-30h] 
0000000000981167 FF C2                inc         edx 
0000000000981169 83 FA 14             cmp         edx,14h 
000000000098116C 75 DD                jne         atou_ex+4h (098114Bh) 
000000000098116E 33 C9                xor         ecx,ecx 
0000000000981170 C3                   ret
Cod-Father

habran

#16
Here is one more complex:

;this function can convert up to 128 bit:
;binary:  b or y  base = 2
;octal:   o or q  base = 8
;decimal: d or t  base = 10
;hexadecimal:  h  base = 16
;hsize contains number of chars
;dst contains converted number in little endian
;that means you can load register directly from memory
;like mov rax,dst
hatoi128 PROC FRAME USES rbx src:QWORD,dst:QWORD,base:SDWORD,hsize:SDWORD
  movsxd r9,r9d
  mov    r11d,r8d
  mov    rbx,rdx
  add    r9,rcx

  xor    eax,eax
  mov    r10,rcx
  mov    [rdx],rax
  mov    [rdx+8],rax
  .repeat
    movzx   rax,BYTE PTR [r10]
    .if (al <= '9')
      sub   eax,'0'
    .else
      or     eax,20h
      sub    eax,57h
    .endif
     mov    rdx,rbx
    .for (r8d=8¦r8d¦r8d--)
      movzx   ecx,WORD PTR [rdx]
      lea     rdx,QWORD PTR [rdx+2]
      imul    ecx,r11d
      add     eax,ecx
      mov     [rdx-2],ax
      shr     eax,16
    .endfor
    inc r10
  .until (r10==r9)
  ret
hatoi128 ENDP
Cod-Father

jj2007

Quote from: rrr314159 on April 27, 2015, 07:53:37 AM
Listen to Habran, he is a doer

He's overdoing it :P

No, seriously: compliments to Habran, you are doing a great job :t

habran

It's a great pleasure to receive flowers from you jj2007 :biggrin:
Cod-Father

Gunther

Hi rrr,

Quote from: rrr314159 on April 27, 2015, 07:53:37 AM
BTW Gunther's reference (Wikipedia) is incomplete and has the standard mistake re. floating point (which I've mentioned often) - seems to be required for any write-up on the net. Use MSDN for info, the only place I've seen that gets this one right

that might be, but the following sources are complete: source 1, source 2, source 3. Interesting is the following overall view, too. A drawback is that __vectorcall is not mentioned. But the comparison between Windows and Unix is interesting.

By the way, good job Habran.  :t

Gunther
You have to know the facts before you can distort them.

rrr314159

#20
gunther, I know MSDN has the right info somewhere, when I get around to it I'll search my notes. The Visual Studio 2013 pages you give 1) may be correct for Visual Studio for all I know, 2) may have the right info somewhere if I read all the other pages, but, the specific pages on Register Usage are wrong for MASM and our environment. They have the same old error re floating point. - and it's not trivial, you will soon run into it if you do much 64-bitting

[edit] actually, come to think of it, as long as you use invoke in the normal way you don't have to worry about it. If you write an invoke macro for ML64, as I did, then it's inescapable; or if you load up registers then call a function, expecting those ref's to be correct. But JWasm invoke does it right, so u don't really have to deal with it
I am NaN ;)

Gunther

Hi rrr,

Quote from: rrr314159 on April 28, 2015, 04:38:46 AM
[edit] actually, come to think of it, as long as you use invoke in the normal way you don't have to worry about it. If you write an invoke macro for ML64, as I did, then it's inescapable; or if you load up registers then call a function, expecting those ref's to be correct. But JWasm invoke does it right, so u don't really have to deal with it

all the invoke and other fancy hll stuff isn't my way. I've another point of view.

Gunther
You have to know the facts before you can distort them.

rrr314159

Quote from: Guntherall the invoke and other fancy hll stuff isn't my way. I've another point of view.

- We're on the same page! I too want to get down to the nitty-gritty - know exactly how things work - like mabdelouahab, whose attitude I admire. Like him, if I want to know, and someone else has the answer - I ask
I am NaN ;)

Gunther

Quote from: rrr314159 on April 30, 2015, 08:10:17 AM
- We're on the same page! I too want to get down to the nitty-gritty - know exactly how things work - like mabdelouahab, whose attitude I admire. Like him, if I want to know, and someone else has the answer - I ask

Yes, of course. The tricky point with all that fancy macro stuff is that: Do you have the full control over the code? If not, you can do the same with HLL.

Gunther
You have to know the facts before you can distort them.

rrr314159

Tricky macro stuff: I have to admit I don't have "full control". That would mean knowing what macros will do before trying them. No, I have to run it: don't always know whether, for instance, a nested macro argument will be expanded, or how far, until I do. When it doesn't work, I put a lot of %'s and &'s in. Since it still doesn't work, I take them out; usually then, it works ;) I honestly don't think it's entirely consistent, the rules vary according to factors only qWord understands. However I'm getting better at it .. the key thing is, once it works it keeps working; without that, forget it; but that is the case. And, macros are so powerful they're worth some hair torn out.

HLL: I finally realized, when people refer to MASM HLL they mean those .if, .else statements! I thought it meant languages like C or Pascal - and sometimes, it does - or Randall Hyde's HLA, or something. Now that I know what goes on "under the hood" I use those HLL constructs and think they're great. Habran's example convinced me ... also an old thread from a couple years ago where nidud is fixing them in JWasm and argues convincingly for his project
I am NaN ;)

habran

Hey rrr314159 :biggrin:
I am happy to hear that you now understand the beauty of HLL :t
Easy to read and understand what's going on
BTW did you read your PM?
Cod-Father

fearless

Just wondering if anyone has a working 64bit code version of the utoa_ex function? ive had no success converting the existing code.

hutch--

 :biggrin:

Humerously enough, I forgot how it works as I wrote it years ago but just converted it and it works OK. If you want it as a library module, just put it into a bare procedure in ML64 and assemble it. I have added the NOSTACKFRAME to turn off the prologue/epilogue code that I am using with ML64.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

entry_point proc

    LOCAL decstr :QWORD

    mrm decstr, "12345678"

    mov rcx, decstr
    call atou_ex

    conout str$(rax),lf

    waitkey

    invoke ExitProcess,0

    ret

entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

NOSTACKFRAME

atou_ex proc

  ; ------------------------------------------------
  ; Convert decimal string into UNSIGNED QWORD value
  ; ------------------------------------------------
  ; argument in RCX

    xor r11, r11
    movzx rax, BYTE PTR [rcx]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+1]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+2]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+3]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+4]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+5]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+6]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+7]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+8]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+9]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+10]
    test rax, rax
    jnz out_of_range

  quit:
    lea rax, [r11]      ; return value in RAX
    or rcx, -1          ; non zero in RCX for success
    ret

  out_of_range:
    xor rax, rax        ; zero return value on error
    xor rcx, rcx        ; zero in RCX is out of range error
    ret

atou_ex endp

STACKFRAME

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end

hutch--

This one will do 19 digits.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

NOSTACKFRAME

atou_ex proc

  ; ------------------------------------------------
  ; Convert decimal string into UNSIGNED QWORD value
  ; ------------------------------------------------
  ; argument in RCX

    xor r11, r11
    movzx rax, BYTE PTR [rcx]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+1]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+2]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+3]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+4]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+5]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+6]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+7]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+8]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+9]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+10]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+11]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+12]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+13]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+14]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+15]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+16]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+17]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+18]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+19]
    test rax, rax
    jz quit

    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx+20]
    test rax, rax
    jnz out_of_range

  quit:
    lea rax, [r11]      ; return value in RAX
    or rcx, -1          ; non zero in RCX for success
    ret

  out_of_range:
    xor rax, rax        ; zero return value on error
    xor rcx, rcx        ; zero in RCX is out of range error
    ret

atou_ex endp

STACKFRAME

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

habran

Quote from: fearless on September 06, 2016, 12:26:15 PM
Just wondering if anyone has a working 64bit code version of the utoa_ex function? ive had no success converting the existing code.
Cod-Father