Author Topic: atou_ex 64bit version  (Read 20973 times)

TWell

  • Member
  • ****
  • Posts: 743
Re: atou_ex 64bit version
« Reply #30 on: September 06, 2016, 05:47:11 PM »
And using loop ?
Code: [Select]
option epilogue:none
option prologue:none

.code
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

    xor r10, r10

@@:
    inc r10
    inc rcx
    lea r11, [r11+r11*4]
    lea r11, [rax+r11*2-48]
    movzx rax, BYTE PTR [rcx]
    test rax, rax
    jz quit
    cmp r10, 20
    jl @B

    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
end
Code: [Select]
option casemap :none
option epilogue:none
option prologue:none
ifdef __HJWASM__
OPTION STACKBASE:rsp
OPTION WIN64:2
endif
includelib msvcrt64.lib
exit proto :dword
printf proto args:vararg

extern atou_ex :proc

.data
fmt  db "%s %d",13,10,0
qstr db "12345678",0

.code
mainCRTStartup proc
  sub rsp, 30h
  mov rcx, offset qstr
  call atou_ex
  invoke printf,addr fmt, addr qstr, rax
  invoke exit, 0
mainCRTStartup endp

end
EDIT fix as habran suggested
« Last Edit: September 06, 2016, 07:05:17 PM by TWell »

habran

  • Member
  • *****
  • Posts: 1228
    • uasm
Re: atou_ex 64bit version
« Reply #31 on: September 06, 2016, 06:14:39 PM »
You can use r10 instead of r12 it is a volatile register, r12 is nonvolatile register and should be saved before use.
It is OK in your case, however, if you plan to use this function from other functions you may get in trouble :biggrin:
So, I am not sure were you looking for utoa_ex function or atou_ex function or both :dazzled:
Cod-Father

fearless

  • Member
  • ****
  • Posts: 578
    • Github
Re: atou_ex 64bit version
« Reply #32 on: September 06, 2016, 07:03:08 PM »
I was looking for utoa_ex, i used your version of the atou_ex for atou_ex. Both would be useful for others id imagine.
fearless

ASUS Crosshair 8 Hero, AMD 5950X, 32GB, MSI 5700XT, NZXT Kraken Z73, Seasonic 1000W PSU

Github Twitter Mastodon Gitbook

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10583
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: atou_ex 64bit version
« Reply #33 on: September 06, 2016, 08:40:14 PM »
The only version of utoa_ex I have was one of Lingo's from memory and it has magic numbers in it that I don't understand how it works. I will see what I can find.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

habran

  • Member
  • *****
  • Posts: 1228
    • uasm
Re: atou_ex 64bit version
« Reply #34 on: September 07, 2016, 12:56:47 AM »
Here is one that I converted from HJWasm:
It can be used for signed and unsigned qword and can convert to binary, octal, decimal and hex characters
you can call it something like :
mynum = 738h
invoke myqtoa, mynum,ADDR buff, 2, FALSE, FALSE     ;binary
invoke myqtoa, mynum,ADDR buff, 8, FALSE, FALSE     ;octal
invoke myqtoa, mynum,ADDR buff, 10, FALSE, FALSE   ;decimal
invoke myqtoa, mynum,ADDR buff, 16, FALSE, FALSE   ;hexadecimal

Code: [Select]
.data
  hextbl  db '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'

.code

myqtoa PROC FRAME USES rbx  value:qword, buffer:QWORD,radix:DWORD,sign:DWORD,addzero:DWORD
local tmpbuf[34] :BYTE 
       mov  rbx,rdx      ;buffer
       mov  r10,rdx      ;buffer
       .if (!rcx)
         mov rax,rdx
         mov byte ptr[rax],'0'
         jmp done
       .endif 
       .if (r9b)
         mov  byte ptr [rdx],'-'       
         lea  r10,[rdx+1]       
         neg  rcx
       .endif
      lea  r9,tmpbuf[33]                     
      mov  byte ptr tmpbuf[33],0
      lea  r11,hextbl
      .repeat
        xor   edx,edx                      ;clear rdx               
        mov   rax,rcx                      ;value into rax
        dec   r9                           ;make space for next char
        div   r8                           ;div value with radix (2, 8, 10, 16)
        mov   rcx,rax                      ;mod is in rdx, save result back in rcx
        movzx eax,byte ptr [rdx+r11]       ;put char from hextbl pointed by rdx
        mov   byte ptr [r9],al             ;store char from al to tmpbuf pointed by r9
      .until  (!rcx)                       ;repeat if rcx not clear
      .if (addzero && al > '9')            ;add a leading '0' if first digit is alpha
        mov byte ptr[r10],'0'
        inc r10
      .endif
      lea  r8,tmpbuf[34]                   ;end of the buffer in r8
      sub  r8,r9                           ;that will give a count of chars to be copied
      invoke memcpy,r10,r9,r8              ;call routine to copy
      mov        rax,rbx                   ;return the address of the buffer in rax
done: ret       
myqtoa ENDP
« Last Edit: September 07, 2016, 06:17:31 AM by habran »
Cod-Father

fearless

  • Member
  • ****
  • Posts: 578
    • Github
Re: atou_ex 64bit version
« Reply #35 on: September 07, 2016, 06:11:54 AM »
Thanks Habran, that works fine. I noticed that the addzero param if set to true displays as the ascii numeric value, and false displays as the hex value which is pretty neat as well. Also, I used RtlMoveMemory in place of the memcpy function, and it works fine with this as well.
fearless

ASUS Crosshair 8 Hero, AMD 5950X, 32GB, MSI 5700XT, NZXT Kraken Z73, Seasonic 1000W PSU

Github Twitter Mastodon Gitbook

habran

  • Member
  • *****
  • Posts: 1228
    • uasm
Re: atou_ex 64bit version
« Reply #36 on: September 07, 2016, 06:21:53 AM »
No worries fearless :biggrin:
I have modified explanation so that is more clear how it works and how to use it
It was very late last night when I posted it and I've had no time to clarify properly
Cod-Father

habran

  • Member
  • *****
  • Posts: 1228
    • uasm
Re: atou_ex 64bit version
« Reply #37 on: September 07, 2016, 08:55:32 AM »
Because HJWasm accepts '0x' for hexadecimal numbers it can be written:
      .if (addzero && al > '9')            ;add a leading '0x' if first digit is alpha
         mov word ptr[r10],'x0'
         add r10,2
      .endif

Then you should use : invoke myqtoa, mynum,ADDR buff, 16, FALSE, TRUE   ;hexadecimal
 
Or if you prefer asm style you can ad this here:
      lea  r9,tmpbuf[33]                     
      mov  byte ptr tmpbuf[33],0
      lea  r11,hextbl
      .f (radix == 16)
         dec r9
         mov byte ptr[r9],'h'
      .endif

      .repeat

If you prefer lower case letters in hexadecimal numbers you can change:
hextbl  db '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
to:
hextbl  db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

« Last Edit: September 07, 2016, 03:24:47 PM by habran »
Cod-Father

habran

  • Member
  • *****
  • Posts: 1228
    • uasm
Re: atou_ex 64bit version
« Reply #38 on: September 08, 2016, 10:27:43 AM »
I have optimized myqtoa function so that it doesn't need to call memcpy and it makes it much faster :
Quote
;value is in rcx and contains the number to be printed 
;buffer is in rdx and contains the destiny address where to store the string
;radix is in r8 and it can contain 2 for bin, 8 for octal, 10 for decimal or 16 for hex
;sign is TRUE for negative signed numbers, otherwise FALSE
;set addzero TRUE if you want hex numbers to be used by assembler
myqtoa PROC FRAME USES rbx rdi rsi value:qword, buffer:QWORD,radix:DWORD,sign:DWORD,addzero:DWORD
local tmpbuf[34] :BYTE 
       mov  rbx,rdx                         ;keep the original address of the buffer in rbx
       mov  rdi,rdx                         ;this is working buffer address
       .if (!rcx)                           ;number could be zero
         mov word ptr[rdx],30h              ;print '0',0
         jmp done                           ;the job done
       .endif 
       .if (r9d)                            ;if sign
         mov  byte ptr [rdx],'-'            ;print it out
         lea  rdi,[rdx+1]                   ;increase pointer 
         neg  rcx                           ;make it negative number
       .endif
      lea  rsi,tmpbuf[33]                   ;load last location of tmpbuf                     
      mov  byte ptr tmpbuf[33],0            ;mark the end of string
      lea  r11,hextbl                       ;r11 points to hextable
      ;if you want 'h' at the end, uncomment next 4 lines
      ;.if (radix == 16)                     ;if hex number
      ;  dec rsi                             ;make space for next char
      ;  mov byte ptr[rsi], 'h'              ;end it with 'h'
      ;.endif
      .repeat
        xor   edx,edx                       ;clear rdx               
        mov   rax,rcx                       ;value into rax
        dec   rsi                           ;make space for next char
        div   r8                            ;div value with radix (2, 8, 10, 16)
        mov   rcx,rax                       ;mod is in rdx, save result back in rcx
        movzx eax,byte ptr [rdx+r11]        ;put char from hextbl pointed by rdx
        mov   byte ptr [rsi],al             ;store char from al to tmpbuf pointed by rsi
      .until  (!rcx)                        ;repeat if rcx not clear
      .if (addzero && al > '9')             ;add a leading '0' if first digit is alpha
        mov byte ptr[rdi],'0'
        inc rdi
      .endif
      lea  rcx,tmpbuf[34]                   ;start of the buffer in r8
      sub  rcx,rsi                          ;that will give a count of chars to be copied
      rep movs byte ptr [rdi],byte ptr [rsi];copy bytes to the buffer
      mov        rax,rbx                    ;return the address of the buffer in rax
done: ret       
myqtoa ENDP

Cod-Father

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1196
Re: atou_ex 64bit version
« Reply #39 on: September 28, 2016, 06:05:20 AM »
Instead it puts the first 4 args in rcx, rdx, r8, r9...

I don't know what JWASM, or any of the assemblers, actually do, and not to be picking nits, but your description leaves out essential details. For the first four arguments, the integer and FP argument registers are matched by position, RCX:XMM0L, RDX:XMM1L, R8:XMM2L, R9:XMM3L, with the register that does not match the argument type ignored. And IIRC, for unprototyped or vararg functions, the FP values should be duplicated in the matching integer registers.
Well Microsoft, here’s another nice mess you’ve gotten us into.