News:

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

Main Menu

Large number conversion to unsigned hexadecimal value

Started by colinr, August 17, 2023, 11:30:09 PM

Previous topic - Next topic

colinr

Hi Guys

I'm sure what I'm trying to do is straightforward, however, I'm getting nowhere.

I'm trying to convert a decimal number which is in ASCII format (user input) to an unsigned hexadecimal (binary) number.

The number, when converted, will not exceed 64 bits in length.

I've tried atoi and GetDlgItemInt, both of which only seem to support 32 bit integers.

I use WinAsm and Masm32 as they were released, so I'm not comfortable with using something like MasmBasic, surely there must be some built in API that can achieve this? It just seems to be the reverse of sprintf %llu.

Kind regards, and thanks in advance.

jj2007

It is indeed possible with MasmBasic:

include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals MyQ:QWORD
  Init
  Let esi="-4995072469926809587"
  MovVal MyQ, esi
  Print Hex$(MyQ)
EndOfCode

Output: BAADF00D BAADF00D

Check SOF, they might have a solution.

zedd151

Something like this? This is for unsigned integers.

From masm64.lib "atou_ex"
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .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

    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 EAX
    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 ECX is out of range error
    ret

atou_ex endp

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

    end

colinr

Quote from: zedd151 on August 18, 2023, 12:07:59 AMSomething like this? This is for unsigned integers.

I'm using MASM32, I don't suppose that you have anything in 32 bit?

zedd151

Quote from: colinr on August 18, 2023, 12:10:29 AMI'm using MASM32, I don't suppose that you have anything in 32 bit?
Ok, I just read that, I missed it the first time. Sorry.
I didn't realise that you were looking for ascii to qword conversion for masm32 code.

I don't have anything offhand, for 32 bit.

jj2007

See qw.zìp attached in reply #1.

-4995072469322841890 is a nice decimal to play with.

colinr

Quote from: jj2007 on August 18, 2023, 12:38:57 AMSee qw.zìp attached in reply #1.

-4995072469322841890 is a nice decimal to play with.

I can't seem to get my head around the syntax, if I don't have any luck with figuring this out via WinAPI or something I write, I'll stand it up in a clean environemnt as the project is too advanced to change how it works at the moment.

jj2007

The simple example I posted in reply #1 assembles fine with a standard Masm32 installation, and I didn't use any special syntax. Explain why you have difficulties.

colinr

Quote from: jj2007 on August 18, 2023, 01:30:32 AMExplain why you have difficulties.

Init - ??

Let esi="-4995072469926809587" -- ESI is a 32 bit register, how can it contain this ASCII value or is it a pointer?

MovVal MyQ, esi -- Makes more sense, but why MovVal and not mov?

Print Hex$(MyQ) -- How do I access MyQ as a 64 bit hex value, exampe:

mov   eax, [GET_LENGTH_INFORMATION].dLength
mov   ebx, [GET_LENGTH_INFORMATION].dLength+4



zedd151

Quote from: jj2007 on August 18, 2023, 01:30:32 AMExplain why you have difficulties.
1. Code from the zip does not match the code posted.
Code from zip file...
include \masm32\include\masm32rt.inc

.data
MyQ    dq ?

.code
start:
  print "Type your number: "
  invoke crt_scanf, chr$("%llu"), addr MyQ
  printf("The number read was %llx\n", MyQ)
  inkey " "
  exit

end start
The code from the zip assembles fine with "Console Assemble & Link" from qeditors menu.
And runs okay... result:
Type your number: 123456789123456789
The number read was 1b69b4bacd05f15

####################################################

Quote from: jj2007 on August 18, 2023, 01:30:32 AMExplain why you have difficulties.
2. Perhaps the code posted is a little misleading (references to MasmBasic)? Not the exact same code as in the zip file.
Posted code...
include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals MyQ:QWORD
  Init
  Let esi="-4995072469926809587"
  MovVal MyQ, esi
  Print Hex$(MyQ)
EndOfCode

jj2007


colinr

Quote from: zedd151 on August 18, 2023, 02:01:24 AMinclude \masm32\include\masm32rt.inc

.data
MyQ    dq ?

.code
start:
  print "Type your number: "
  invoke crt_scanf, chr$("%llu"), addr MyQ
  printf("The number read was %llx\n", MyQ)
  inkey " "
  exit

end start

Now this is looking more understandable, it apprears that crt_scanf is converting the inputted number to a QWORD, how could I do this if the value was taken from an input box on a dialog? I know how to use GetDlgItemText, just not how to take the numerical text value and convert it to the hex value. 

zedd151

#12
I think I have found an answer for you.

      include \masm32\include\masm32rt.inc

        WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
       
    .data
        dlgname      db "TESTWIN",0
        hInstance    dd 0
        Longnumber    dq 0
        longNumStr    db 32 dup (0)
        fmt1          db "%llu", 0
    .code

start:

; #########################################################################

        invoke GetModuleHandle, NULL
        mov hInstance, eax
       
        invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0

        invoke ExitProcess,eax

; #########################################################################

WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

      .if uMsg == WM_COMMAND
        .if wParam == 1000
          invoke GetDlgItemText, hWin, 100, addr longNumStr, 32  ;  get the long ascii string into buffer
          invoke crt_sscanf, addr longNumStr, addr fmt1, addr Longnumber  ; using crt_sscanf "Longnumber" will hold your qword value after conversion...
        .endif

      .elseif uMsg == WM_CLOSE
        invoke EndDialog,hWin,0

      .endif

    xor eax, eax
    ret

WndProc endp

; ########################################################################

end start

You can play around with it a bit for further conversion of the qword to readable format (ascii representation of the qword).  :smiley:
I only got as far as testing it in ollydbg... works apparently.  :tongue:

results from this code with "123456789123456789" as input:
15 5F D0 AC 4B 9B B6 01 as seen in ollydbg dump window


results from above posting:
QuoteType your number: 123456789123456789
The number read was 1b69b4bacd05f15

It took me a little while to get everything together and working as expected.  :cool:
I had never really had the need myself, so we both learned something today. :biggrin:

colinr

Quote from: zedd151 on August 18, 2023, 04:06:01 AMI had never really had the need myself, so we both learned something today. :biggrin:

Thank you very much, all that is needed is: invoke crt_sscanf, addr longNumStr, addr fmt1, addr Longnumber

As long the string is null terminated, it will work.

Just used "12345678123456", Longnumber ended up being populated with 004045A4  C0 51 C2 73|3A 0B

Perfect, turned out to be a simple solution to what could have been a lot of convoluted code.                             

zedd151

Quote from: colinr on August 18, 2023, 04:52:33 AM
Quote from: zedd151 on August 18, 2023, 04:06:01 AMI had never really had the need myself, so we both learned something today. :biggrin:
Perfect, turned out to be a simple solution to what could have been a lot of convoluted code.

Perfectly understandable. Some of my first attempts were indeed convoluted.  :biggrin:  I had the arguments in the wrong order once, and tried a different API with odd results.