IonicWind Software

IWBasic => General Questions => Topic started by: Andy on August 10, 2017, 12:58:19 am

Title: Converting C to IWB
Post by: Andy on August 10, 2017, 12:58:19 am
Here is an example in C of how to convert a uint64 number to hex:

Code Select
static char hex [] = { '0', '1', '2', '3', '4', '5', '6', '7',
                        '8', '9' ,'A', 'B', 'C', 'D', 'E', 'F' };

int uintToHexStr(unsigned int num,char* buff)
{
    int len=0,k=0;
    do//for every 4 bits
    {
        //get the equivalent hex digit
        buff[len] = hex[num&0xF];
        len++;
        num>>=4;  //shift right 4 chars
    }while(num!=0);


buff receives the corresponding hex (in reverse order - but that's easy enough to sort out).

I'm having trouble converting the above to IWB - can anyone help please?

On the face of it, it looks simple enough - but how do I translate the line:
buff[len] = hex[num&0xF];

I'm quite happy if the number to be converted is a string - if that makes it easier.

OR:

Could this code be placed in an IWB sub routine and called? - never attempted that before.

Thanks,
Andy.
Title: Re: Converting C to IWB
Post by: Andy on August 10, 2017, 04:16:42 am
As far as I can work out (and I could be wrong as usual), the line:

buff[len] = hex[num&0xF]; is getting the binary XOR value by comparing the binary number against 1111 (0xF), which then gets the corresponding hex value stored in the hex[] Array.

Title: Re: Converting C to IWB
Post by: Egil on August 10, 2017, 04:44:24 am
Hi Andy,

I think the characters & is the result of conversion errors when copying the code. And should read just & instead.

Then for  the decimal to hex conversion... why not use hex$(nnnn), where nnnn is the decimal value to be converted, and  then arrange the hex expression in 8 bit chunks so the result is presented in the wanted order (reverse or normal)?

As far as I can see (whithout remebering much C coding), that's what your code example does.




EDIT:  Forgot to say that by using  8 bit chunks, it is easy to see if you need to insert a leading zero into the expressions, e.g. 07 instead of just 7.

Title: Re: Converting C to IWB
Post by: LarryMc on August 10, 2017, 07:07:14 am
I guess I'm not understanding something.
Why are you trying to create a function that converts a Uint64 to HEX when we already have one called HEX$
What am I missing?

Title: Re: Converting C to IWB
Post by: Andy on August 10, 2017, 08:17:50 am
Thanks Egil I will have a look now, been out all day.

Larry,

If I take a uint64 number for example.....    12345678901234567890
and use HEX$ I get:   FFFFFFFFEB1F0AD2

Now when a registry qword displays the hex version of the above decimal number it gives:
AB54A98CEB1F0AD2 which is different from FFFFFFFFEB1F0AD2 (not displaying the AB54A98C part but replacing them with F's).

Title: Re: Converting C to IWB
Post by: LarryMc on August 10, 2017, 11:07:28 am
This is the HEX$ code. See if you can see why you get a different answer.
Code Select
SUB HEX$(num as UINT64)
DEF strrev[17] as ISTRING
DEF outstr as POINTER
DEF count,i as INT
DEF remain as INT
DEF div as UINT64:div = 16
count = 0
outstr = AllocHeap(17)
do
remain = num % div
num = num / div
if remain > 9
strrev[count] = (remain-10) + asc("A")
else
strrev[count] = remain + asc("0")
endif
count = count + 1
until num = 0q
strrev[count] = chr$(0)

for i = 0 to count-1
#<STRING>outstr[i] = strrev[count-1-i]
next i
#<STRING>outstr[i] = 0
RETURN #<STRING>outstr
ENDSUB
Title: Re: Converting C to IWB
Post by: LarryMc on August 10, 2017, 12:39:30 pm
OK, we can fix this but we need someone smarter than me to sort it out.
I know why it's not working and I know HOW to fix it but I just don't know how to write the code to do it.
First I wrote this simple little sub that right shifts 4 bits at a time and then uses the existing HEX$ function to get the hex value and add it on to a string and then return it.
Code Select
openconsole
UINT64 numin = 12345678901234567890
'AB54A98CEB1F0AD2 which is different from FFFFFFFFEB1F0AD2.
'FFFFFFFFEB1F0AD2
? hex$2(NUMIN)


waitcon



SUB HEX$2(num as UINT64),string
string outstr
uint64 num2

NUM2=NUM
FOR i = 1 TO 15
  outstr = Hex$(num2 & 0xF) +outstr
? outstr
num2=num2 >> 4
if num2=0 then break
NEXT i
RETURN outstr
ENDSUB

When you run the program with Andy's input you get the same wrong result as you do with the HEX$ FUNCTION.
It demonstrates the problem with the HEX$ function: after 32 bits there is a problem with shifting.

Now, I found a discussion about a problem with shifting 64 bits numbers past 32 bits.  The discussion, with Turley's reasoning for using his implementation, and Sapero's workaround fix, is all in assembly and in terms of LEFT shifting.   To solve our problem, we need a version of my little sub(or a variation thereof) to be built around RIGHT shifting and with Sapero's assembly workaround converted over to right shifting.

Like I implied, the info is there. We just need someone smart enough to take it and run. I'm not the who on this one.

http://www.ionicwind.com/forums/index.php?topic=1707.msg15766#msg15766
Title: Re: Converting C to IWB
Post by: Andy on August 10, 2017, 12:53:38 pm
Larry, I think that's the answer, wether I'm clever enough to do it remains to be seen, I will have a look at it in the morning as I really need to get some sleep now.

Thanks Larry.
Title: Re: Converting C to IWB
Post by: jalih on August 10, 2017, 01:03:11 pm
Hi all,

You could probably use this simple asm trick to convert one byte to ascii hexadecimal and process INT64 one byte at a time:

Code Select

istring hexnum[2]
char num = 255

_asm
mov al, [$num]
aam 16

@digit2:
add al, 090h
daa
adc al, 040h
daa
@digit1:
xchg al, ah
add al, 090h
daa
adc al, 040h
daa

mov word [$hexnum], ax
_endasm

print hexnum

Title: Re: Converting C to IWB
Post by: fasecero on August 10, 2017, 10:12:38 pm
Try using the q modifier literal

Code Select

UINT64 numin = 12345678901234567890q
print HEX$(NUMIN)
waitcon
Title: Re: Converting C to IWB
Post by: jalih on August 11, 2017, 12:59:29 am
I wrote a fast 32-bit hex32$() subroutine in asm for quick ascii hex conversion. Fast 64-bit version should be possible by just calling routine twice to handle hi -and low-dwords separately.

I will post some code later today...
Title: Re: Converting C to IWB
Post by: Andy on August 11, 2017, 03:38:40 am
Fasecero,

I forgot about adding the Q to the end of the uint64 - that works, but brings back the old Problem of adding a Q to a number you don't know.

Larry,

I copied the Hex$ Code, renamed it - that's all, added a Q to the unit64 number and that didn't work, but the built in IWB Hex$ function does.

Jalih,
That would be great if you could post a copy and explain how to use it.

Thanks guys.
Title: Re: Converting C to IWB
Post by: jalih on August 11, 2017, 09:04:46 am
Quote from: Andy on August 11, 2017, 03:38:40 am
Jalih,
That would be great if you could post a copy and explain how to use it.


Here are hex32$() and hex64$() functions:

Code Select



uint num1 = 0xFF00FF00
uint64 num2 = 12345678901234567890q

print hex32$(num1)
print hex64$(num2)

waitcon
end


$option "/p 1"
sub hex32$(uint num), string
    istring hexnum[9]

_asm
    lea esi, [num]
    lea edi, [hexnum]

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax
    mov [edi+4], edx

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax
    mov [edi], ecx

    mov byte [edi+8], 0
_endasm

    return hexnum

endsub


sub hex64$(uint64 num), string
    istring hexnum[17]

_asm
    lea esi, [num+4]
    lea edi, [hexnum]

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax
    mov [edi+4], edx

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax
    mov [edi], ecx

    sub esi, 4
    add edi, 8

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax
    mov [edi+4], edx

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax
    mov [edi], ecx

    mov byte [edi+8], 0

_endasm

    return hexnum

endsub
$option "/p 0"

Title: Re: Converting C to IWB
Post by: Andy on August 11, 2017, 09:15:52 am
Jalih,

I will try that, thanks for posting it, the only problem is you have added the letter q to the uint64 number, and I don't know what the number will be and cannot hard code it.

Title: Re: Converting C to IWB
Post by: jalih on August 11, 2017, 09:51:08 am
Quote from: Andy on August 11, 2017, 09:15:52 am
I will try that, thanks for posting it, the only problem is you have added the letter q to the uint64 number, and I don't know what the number will be and cannot hard code it.


You don't need to hard code a number. The q modifier is  only needed when you enter a numeric literal (constant) in code. Without the q modifier, compiler treats it as INT.
Title: Re: Converting C to IWB
Post by: srvaldez on August 11, 2017, 02:43:09 pm
Andy, maybe make a union with a Uint64 and two ints, then take the hex of the two ints.
Title: Re: Converting C to IWB
Post by: fasecero on August 11, 2017, 04:32:10 pm
Quote
I forgot about adding the Q to the end of the uint64 - that works, but brings back the old Problem of adding a Q to a number you don't know.


Wow, I didn't know that.

It seems that INT() return an INT64 from a double, so theoretically you can use this to "attach" the q to a non literal integer.

Code Select

INT a = 106335683 ' MAX: 2147483647
INT b = 12772387
INT c = 9090

INT64 a64 = MakeINT64(a)
INT64 b64 = MakeINT64(b)
INT64 c64 = MakeINT64(c)

INT64 numin = a64 * b64 * c64

print HEX$(numin)

PRINT HEX$(12345678901234567890q)

WAITCON

SUB MakeINT64(INT value), INT64
double a = FLT(value)
INT64 b = INT(a)
RETURN b
ENDSUB


If this works for you then you should stick to INT64 in your whole program, and when some external func gives you an INT you should cast it to INT64 right away.
Title: Re: Converting C to IWB
Post by: jalih on August 12, 2017, 12:05:49 am
Quote from: fasecero on August 11, 2017, 04:32:10 pm
It seems that INT() return an INT64 from a double, so theoretically you can use this to "attach" the q to a non literal integer.


On Andy's application, it's not probably a good idea. With double you get 52-bits of precision, not the full range of INT64.
Title: Re: Converting C to IWB
Post by: fasecero on August 12, 2017, 02:07:43 am
And you are right. A double has 64 bits but can represent an "int55" (assuming such a thing existed), so the funcion I made will not work, thank you very much for pointing this out. I was trying to avoid this suggestion, but the solution I can think of would be to make a c dll that does the casting from int to int64. Can't find another "native" way to do it.

EDIT: Now that I think about it better, I think it will work just fine. The MakeINT64() function is used to pass a number from 32 to 64 bits, a number that you already know it will be 32 bits, only then you use this function. If you have a number greater than 32 bits you just use an INT64 variable from the beginning, and forget about that function. Can you guys think of an example where something doesn't work fine?
Title: Re: Converting C to IWB
Post by: ckoehn on August 12, 2017, 08:47:22 pm
The biggest problem is getting the number into a 64 bit variable.  Using double, like fascero said is the easiest way.

Code Select
openconsole

int64 bignumber
string hex
double smallnumber = 1234567

bignumber = smallnumber * smallnumber * smallnumber

hex = makehex(bignumber)

print bignumber,hex

do
until inkey$=chr$(27)   'press ESC to exit

closeconsole

end

sub makehex(int64 bnum),string
istring num[17] = "0123456789ABCDEF\0"
istring ans[17] = "----------------\0"
int ptr=1

for i=15 to 0 step -1
ans[i] = mid$(num,(bnum % 16) + 1,1)
bnum = bnum >> 4
next i

while mid$(ans,ptr,1)="0" 'remove leading 0's
ptr++
endwhile

ans = mid$(ans,ptr)

return ans
endsub

Title: Re: Converting C to IWB
Post by: jalih on August 13, 2017, 12:08:36 am
Quote from: fasecero on August 12, 2017, 02:07:43 am
EDIT: Now that I think about it better, I think it will work just fine. The MakeINT64() function is used to pass a number from 32 to 64 bits, a number that you already know it will be 32 bits, only then you use this function. If you have a number greater than 32 bits you just use an INT64 variable from the beginning, and forget about that function. Can you guys think of an example where something doesn't work fine?


You can't use double to convert input to 64-bit INT and use the full number range. IWBasic uses VAL() for conversion and it's limited to DOUBLE precision. Easiest way is to use the C-library or you can write your own function.

With binary data there is no problem, as any 8-byte buffer for data will suffice.

Code below demonstrates limited range of DOUBLE:

Code Select

Uint64 num1, num2, num4
double num3

num1 = 9223372036854775807uq
num3 = 9223372036854775807uq
num2 = Uint64(num3)

num4 = val("9223372036854775807")

print hex64$(num1)
print hex64$(num2)
print hex64$(num4)

waitcon
end


$option "/p 1"
sub hex32$(uint num), string
    istring hexnum[9]

_asm
    lea esi, [num]
    lea edi, [hexnum]

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax

    mov [edi], ecx
    mov [edi+4], edx
    mov byte [edi+8], 0
_endasm

    return hexnum

endsub


sub hex64$(uint64 num), string
    istring hexnum[17]

_asm
    lea esi, [num+4]
    lea edi, [hexnum]

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax

    mov [edi], ecx
    mov [edi+4], edx

    sub esi, 4
    add edi, 8

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax

    mov [edi], ecx
    mov [edi+4], edx
    mov byte [edi+8], 0

_endasm

    return hexnum

endsub
$option "/p 0"
Title: Re: Converting C to IWB
Post by: ckoehn on August 13, 2017, 06:50:52 am
I agree with Jalih.  Using double to convert to large of numbers results in an inaccurate conversion.  I tried it and wondered why my routine wasn't working.  Printing out the int64 number showed that it wasn't what i expected it to be.

This routine works too.

Code Select
openconsole

uint64 bignumber
string hex
double smallnumber

smallnumber = 1234567

bignumber = smallnumber ^ 3

print "converting: ", smallnumber, "^3 = ",  bignumber,

hex = makehex(bignumber)

print "to hex: ",hex

DO
until inkey$=chr$(27)

closeconsole

end

sub makehex(uint64 bnum),string
String num = "0123456789ABCDEF"
string ans =""
int ptr=1

for i=15 to 0 step -1
ans = mid$(num,(bnum % 16) + 1,1) + ans
bnum = bnum >> 4
next i

while (mid$(ans,ptr,1)="0") and (ptr<16) 'remove leading 0's
ptr++
endwhile

ans = mid$(ans,ptr)

return ans
endsub
Title: Re: Converting C to IWB
Post by: jalih on August 13, 2017, 08:29:17 am
Quote from: ckoehn on August 13, 2017, 06:50:52 am
This routine works too.


I timed IWBasic's HEX$() and my hex64$() functions and found that my routine is over five times faster. Inline asm really makes the difference:

Code Select

DECLARE "kernel32.dll", GetTickCount(),int

int i, start, finish
UINT64 num =9223372036854775807uq
string result

print "Execution times in millisecs for 1000000 iterations:"

start = GetTickCount()
for i = 1 to 1000000
result = hex$(num)
next i
finish = GetTickCount()
print "IWBasic HEX$() command: ",  finish-start

start = GetTickCount()
for i = 1 to 1000000
result = hex64$(num)
next i
finish = GetTickCount()
print "hex64$ function written in inline asm: ", finish-start

waitcon
end


$option "/p 1"
sub hex64$(uint64 num), string
    istring hexnum[17]

_asm
    lea esi, [num+4]
    lea edi, [hexnum]

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax

    mov [edi], ecx
    mov [edi+4], edx

    sub esi, 4
    add edi, 8

    mov al, byte [esi]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov edx, eax
    shl edx, 16

    mov al, byte [esi+1]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov dx, ax

    mov al, byte [esi+2]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov ecx, eax
    shl ecx, 16

    mov al, byte[esi+3]
    aam 16

    add al, 090h
    daa
    adc al, 040h
    daa

    xchg al, ah
    add al, 090h
    daa
    adc al, 040h
    daa

    mov cx, ax

    mov [edi], ecx
    mov [edi+4], edx
    mov byte [edi+8], 0

_endasm

    return hexnum

endsub
$option "/p 0"
Title: Re: Converting C to IWB
Post by: Andy on August 13, 2017, 08:49:39 am
This is all good stuff guys,

Clint I found you routine works, but if I just say bignumber = 12345678901234567890 directly it doesn't.

Jalih, I tried to assign a number like this:
result = hex64$(9223372036854775806)

It came back with FFFFFFFFFFFFFFFE which is 18446744073709551614 decimal.

Am I missing something?

Thanks guys - please keep trying.
Title: Re: Converting C to IWB
Post by: jalih on August 13, 2017, 09:10:33 am
Quote from: Andy on August 13, 2017, 08:49:39 am
Jalih, I tried to assign a number like this:
result = hex64$(9223372036854775806)

It came back with FFFFFFFFFFFFFFFE which is 18446744073709551614 decimal.

Am I missing something?


You need to add q or uq modifier for numeric literal. It's IWBasic limitation not fault in my code.
Title: Re: Converting C to IWB
Post by: Andy on August 13, 2017, 10:17:45 am
Thanks for that, but it brings me back to the same old problem - how do you add a literal to X when you don't know before hand the value of X?

Many thanks again for trying!

Andy.
Title: Re: Converting C to IWB
Post by: fasecero on August 13, 2017, 04:55:52 pm
Well, last attempt for me lol. I put aside the double problem by using the runtime functions, as jalih suggested. For some reason, I haven't been able to use c-runtime f that uses 64-bit variables (failed with DECLARE EXTERN approach and with LoadLibrary + GetProcAddress thing ), so I made a small vs dll that encapsulates the functions it needs. C++ source code included, just in case. Create an import library, place the dll at the same directory as the code below.

Code Select


SETPRECISION 0

' integer 64
INT64 num64 = 9223372036854775807q
print num64

' integer 64 to hex string
string str_16 = HEX$(num64)
print str_16

' integer 64 to decimal string
string str_10 = STR$(num64)
print str_10

' hex string to integer 64
INT64 num16 = VAL(str_16)
print num16

' decimal string to integer 64
INT64 num10 = VAL(str_10)
print num10

PRINT
PRINT
PRINT

' THE SAME USING THE DLL

$USE "cast64.lib"
DECLARE CDECL IMPORT, VAL64(string str, int base), INT64
DECLARE CDECL IMPORT, STR64(INT64 value, string buffer)
DECLARE CDECL IMPORT, HEX64(INT64 value, string buffer)

' integer 64
INT64 _num64 = 9223372036854775807q
print _num64

' integer 64 to hex string
string _str_16
HEX64(_num64, _str_16)
print _str_16

' integer64 to decimal string
string _str10
STR64(_num64, _str10)
print _str10

' hex string to integer 64
INT64 _num16 = VAL64(_str_16, 16)
print _num16

' decimal string to integer 64
INT64 _num10 = VAL64(_str10, 10)
print _num10

waitcon
end

Title: Re: Converting C to IWB
Post by: Andy on August 14, 2017, 03:23:59 am
I've come to the same conclusion, the only way for now is to write a Routine in another language that we can use.

I'm currently looking into a vb.net solution as I can understand that better than C and C ++

Andy.
Title: Re: Converting C to IWB
Post by: ckoehn on August 14, 2017, 07:27:24 am
QuoteClint I found you routine works, but if I just say bignumber = 12345678901234567890 directly it doesn't.


Like Jahil said, you need to add a q or uq to the end of a literal value.  IWBASIC limitation.  There is no way that making these routines in another language will help, because you could never transfer a int64 literal number from IWBASIC to that routine wiithout adding a q or uq. Just liike you have to now to use jahil or my routine.
Title: Re: Converting C to IWB
Post by: Andy on August 14, 2017, 08:54:30 am
But I can send a uint64 to a dll which returns a hex string, I'm only one step away from doing that, work permitting.
Title: Re: Converting C to IWB
Post by: fasecero on August 14, 2017, 09:09:29 am
QuoteI'm currently looking into a vb.net solution as I can understand that better than C and C ++


Ok, you'll find a way.

QuoteClint I found you routine works, but if I just say bignumber = 12345678901234567890 directly it doesn't.


Yeah about this, I'm just curious on how you can get a number like 12345678901234567890 without the "q". For example if I use some random function

Code Select
UINT64 ticks = GetTickCount64()

ticks variable will have an unknown value but it will have the "q" already attached.
Title: Re: Converting C to IWB
Post by: jalih on August 14, 2017, 09:27:51 am
Quote from: Andy on August 14, 2017, 08:54:30 am
But I can send a uint64 to a dll which returns a hex string, I'm only one step away from doing that, work permitting.

You can already send uint64 to IWB HEX$() function, use my routine or some other routine.  It's not the problem, your real problem is getting user or program input as uint64. As I already said, if data is binary data then you can just read it into 8 byte buffer and pass that to HEX$() routine.

Writing a function to validate ascii input and convert it to int64 is probably not that hard to write. Simple state machine can be used to validate input string and build uint64 from ascii digits.

We could write IVAL() function for IWB to handle 64-bit integers?
Title: Re: Converting C to IWB
Post by: Andy on August 14, 2017, 10:03:46 pm
Yes, I agree about how you get a unit64, at the moment I'm focusing on registry qwords -  so the number has already been inputted.

Title: Re: Converting C to IWB
Post by: ckoehn on August 15, 2017, 05:03:42 am
What is trying to be said here, if you already have a number in uint64 format, the routines already given you will work.  You don't need an external dll.
Title: Re: Converting C to IWB
Post by: Andy on August 15, 2017, 05:10:05 am
Clint,

Unless I'm missing something I cannot get a hex value greater than 7fffffffffffffff with the routines and qwords go all the way up to 16 f's.

Don't get me wrong - I really do appreciate the work you guys are doing on this!
Title: Re: Converting C to IWB
Post by: jalih on August 15, 2017, 07:40:46 am
Quote from: Andy on August 15, 2017, 05:10:05 am
Unless I'm missing something I cannot get a hex value greater than 7fffffffffffffff with the routines and qwords go all the way up to 16 f's.

Like Clint said, just read qword into 8-byte buffer and it will just work. You can use Union to map bytes into uint64.

Code Select

union dat
uint64 value
uint dword[2]
endunion

def num as dat

num.dword[0] = 0xffffffff
num.dword[1] = 0xffffffff

print hex$(num.value)
Title: Re: Converting C to IWB
Post by: Andy on August 16, 2017, 12:09:34 am
That's fantastic guys! - think maybe my brain cells were on a "go slow" for a while.

With the code amended I can read a qword and return it's hex string value - this means I can finish off my RegExport function which exports all values of a key to a file.

Code Select

$include "C:\\Include Files\\Registry\\registrylib.inc"

openconsole
print
print
print RegGetQWValueHex("HKEY_CURRENT_USER\\Software\\Test\\One","qword")
print
print
do:until inkey$ <> ""
closeconsole
end


So for registry Qwords I now have two functions for reading them:

RegGetQWValue - returns the decimal (uint64) value
RegGetQWValueHex - returns the hex string value.

I will post the library and include file when I'm done.

Thanks again!!!
:)
Title: Re: Converting C to IWB
Post by: fasecero on August 17, 2017, 08:40:06 pm
Just a side note. My dll works for INT64, anyway it can be easily ported for UINT64. But, today I give it another try by using c-runtime & 64 bits from the interface, without using a dll, and it seems that I succeeded. This problem is already solved by the union, I share it simply for the pleasure that gave me to achieve my goal xD

Code Select

$INCLUDE "windowssdk.inc"

' string to UINT64
UINT64 value = StringToUINT64("FFFFFFFFFFFFFFFF") ' hex number
print value

' UINT64 to string
string text = UINT64ToString(value)
print text

PRINT

WAITCON

' -------------------------------------------------------------------------------------
' C-Library Data Conversion Functions
' https://msdn.microsoft.com/en-us/library/0heszx3w.aspx
' -------------------------------------------------------------------------------------

DECLARE CDECL _strtoui64Template(pointer nptr, pointer endptr, uint base), UINT64

SUB StringToUINT64(string text), UINT64
UINT64 value = 0

UINT hInst=LoadLibrary("msvcrt.dll")

IF hInst THEN
UINT proc = GetProcAddress(hInst, "_strtoui64")

IF proc THEN
value = !<_strtoui64Template>proc(text, 0, 16)
ENDIF

FreeLibrary(hInst)
ENDIF

RETURN value
ENDSUB

DECLARE CDECL _ui64toa_sTemplate(UINT64 value, pointer buffer, INT sizeInCharacters, INT radix), INT

SUB UINT64ToString(UINT64 value), string
string buffer = ""

UINT hInst=LoadLibrary("msvcrt.dll")

IF hInst THEN
UINT proc = GetProcAddress(hInst, "_ui64toa_s")

IF proc THEN
value = !<_ui64toa_sTemplate>proc(value, buffer, 200, 16)
ENDIF

FreeLibrary(hInst)
ENDIF

RETURN UCASE$(buffer)
ENDSUB

Title: Re: Converting C to IWB
Post by: Andy on August 17, 2017, 10:47:47 pm
Fasecero,

That is fantastic - great job!

A good while ago I wrote an alternative registry editor, but ran into difficulties when it came to adding / amending qwords.

I can now (when I have time) go back to the program and update it - your code will allow a user to add / amend a qword value (in hex) which can then be translated into a uint64 and saved.

Modifying this code in the StringToUINT64 sub with the line :
value = !<_strtoui64Template>proc(text, 0, 10)

also allows me to take a string decimal e.g. "12345678901234567890" and turn it into a uint64 of 12345678901234567890 which will enable a user to add / amend a qword with decimal as well. 

Thanks,
Andy.