AutoHotkey Community

It is currently May 26th, 2012, 5:44 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Question about NumGet
PostPosted: March 8th, 2009, 11:35 pm 
Offline

Joined: March 8th, 2009, 11:33 pm
Posts: 6
Hello,

At first I'd like to say I'm impressed by the evolution AutoHotKey, it's now more than powerful !
BTW, I have a little question regarding the NumGet function, seems kinda 'trouble'...

I've downloaded the Sean's COM wrapper and I can see a nice function called VTable that is using the NumGet function this way :

Code:
VTable(ppv, idx)
{
   Return   NumGet(NumGet(1*ppv)+4*idx)
}


So what?
Can we imagine that ppv value would be '10000' and that 'idx' value is 2, can you explain me how Numget will retrieve or 'decode' the '10000' value into xxx value please?

Thanks in advance and keep up the good work!
Yours,

Gérôme GUILLEMIN


Report this post
Top
 Profile  
Reply with quote  
PostPosted: March 9th, 2009, 10:37 am 
Offline

Joined: March 8th, 2009, 11:33 pm
Posts: 6
Hello,

To be more precise I'd like to know how autoHotKey compute NumGet onto values 1, 2, 3 and 4 and why these results please ?

Code:
p := 1
r := NumGet(p)
msgbox %p%, %r%  ; ==> 1, 49

p := 2
r := NumGet(p)
msgbox %p%, %r%  ; ==> 2, 50

p := 3
r := NumGet(p)
msgbox %p%, %r%  ; ==> 3, 51

p := 4
r := NumGet(p)
msgbox %p%, %r%  ; ==> 4, 52


Does anyone know how this NumGet function works please?
Why and how can NumGet(1) return 49, NumGet(2) return 50,... ?
Thanks


Report this post
Top
 Profile  
Reply with quote  
PostPosted: March 9th, 2009, 10:56 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Gerome wrote:
I'd like to know how autoHotKey compute NumGet onto values 1, 2, 3 and 4 and why these results please ?


49 is ASCII value of 1 .. and so on!
Code:
MsgBox, % Asc(1)


Quote:
Does anyone know how this NumGet function works please?


Many of us know.. but things have to be explained from basics.. such as bits and bytes :roll:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 11:06 am 
He might have misinterpreted the Asc()-function, eg so Asc(3) means to tripple the standard level of [this]. :wink:


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 11:11 am 
Offline

Joined: March 8th, 2009, 11:33 pm
Posts: 6
BoBo³ wrote:
He might have misinterpreted the Asc()-function, eg so Asc(3) means to tripple the standard level of [this]. :wink:


Ok guys, so why this script when I know tell P to have the value of 1000 give me a big number ?

Code:
p := 1000
r := NumGet(p)
msgbox %p%, %r%  ; ==> 1000, 808464433

p := 2
r := NumGet(p)
msgbox %p%, %r%  ; ==> 2, 808452146

p := 3
r := NumGet(p)
msgbox %p%, %r%  ; ==> 3, 808452147

p := 4
r := NumGet(p)
msgbox %p%, %r%  ; ==> 4, 808452148


It does not seem to be Asc() thistime or may be I've lost something?
Thanks


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 11:32 am 
why don´t you check the help for that?
It´s much faster than guessing and experimenting:
help wrote:
NumGet(VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Returns the binary number stored at the specified address+offset. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types.

NumPut(Number, VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Stores Number in binary format at the specified address+offset and returns the address to the right of the item just written. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings) (UInt64 is supported in v1.0.48+); for details see DllCall Types. If an integer is too large to fit in the specified Type, its most significant bytes are ignored; e.g. NumPut(257, var, 0, "Char") would store the number 1.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 11:36 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Gerome wrote:
It does not seem to be Asc() thistime or may be I've lost something?


Try these:

Code:
Numput( 1312901971, Var := "   " )
MsgBox, % Var


Code:
Var := Chr(83) Chr(75) Chr(65) Chr(78)
MsgBox, % Var


You need to understand bits and bytes before you can understand NumGet() / NumPut()


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 12:01 pm 
Gerome wrote:
Ok guys, so why this script when I know tell P to have the value of 1000 give me a big number ?

Code:
; create var (so its address will be set) by either of the following 2 ways
VarSetCapacity(var,4) ; set size of var large enough for number
;var = 0  ; <-- any value will do
; if you don't do either of the above, then you must use "&var" in numput and numget

p := 1000        ; this stores 1000 as an ASCII STRING in p
Numput(p, var)   ; this stores 1000 (p) as a BINARY number in var
r := NumGet(var) ; this converts BINARY number in var to ASCII STRING
msgbox %p%, %r%  ; ==> 1000, 1000


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 12:05 pm 
Offline

Joined: March 8th, 2009, 11:33 pm
Posts: 6
Z_Gecko wrote:
why don´t you check the help for that?
It´s much faster than guessing and experimenting:
help wrote:
NumGet(VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Returns the binary number stored at the specified address+offset. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types.

NumPut(Number, VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Stores Number in binary format at the specified address+offset and returns the address to the right of the item just written. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings) (UInt64 is supported in v1.0.48+); for details see DllCall Types. If an integer is too large to fit in the specified Type, its most significant bytes are ignored; e.g. NumPut(257, var, 0, "Char") would store the number 1.


Yes I've read this, but it is still fuzzy for me :/
I still don't understand why when using :
p := 1000
r := NumGet(p)
msgbox %p%, %r% ; ==> 1, 808464433

I have a value of 808464433, unless this 808464433 value represents the pointer value of p ?
I'm a bit lost... because this NumGet is used into the VTable function that Sean developped, and I was wondering how he can retrieve the very adress of the COM adress value by using two consecutive call the NumGet...
Please help.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 12:23 pm 
Gerome wrote:
I still don't understand why when using :
p := 1000
r := NumGet(p)
msgbox %p%, %r% ; ==> 1, 808464433

I have a value of 808464433, unless this 808464433 value represents the pointer value of p ?


No it is not a pointer - you are putting an ASCII STRING in p, and try to retrieve the content of p as though it were a BINARY NUNBER.

The reason numput exists at all, is because AHK stores all of its variables as STRINGS - not as BINARY NUMBERS.

Examine my previous post - the comments should tell you what you are misunderstanding.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 1:33 pm 
See if this makes clear what is going on with STRINGS and BINARY numbers.

Code:
VarSetCapacity(var,4) ; set size of var large enough for number

p := 1000        ; this stores 1000 as an ASCII STRING in p
Numput(p, var)   ; this stores 1000 (p) as a BINARY number in var
r := NumGet(var)
msgbox %p%, %r%  ; ==> 1000, 1000



Code:
hex dump of p (a normal AHK variable, stored as an ASCII STRING)
0000: 31 30 30 30 | 00 00 00 00 |  - 1000....
     0x31 = 1 0x30 = 0 0x30 = 0 0x30 = 0

hex dump of var (1000 stored as a BINARY value by the use of numput)
0000: E8 03 00 00 | 00 00 00 00 |  - è.......
      0x03E8 = 1000

hex dump of r (a normal AHK variable, stored as an ASCII STRING by use of numget)
0000: 31 30 30 30 | 00 00 00 00 |  - 1000....
     0x31 = 1 0x30 = 0 0x30 = 0 0x30 = 0


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 5:56 pm 
Offline

Joined: March 8th, 2009, 11:33 pm
Posts: 6
Dear JimD,
jimD wrote:
See if this makes clear what is going on with STRINGS and BINARY numbers.

Code:
VarSetCapacity(var,4) ; set size of var large enough for number

p := 1000        ; this stores 1000 as an ASCII STRING in p
Numput(p, var)   ; this stores 1000 (p) as a BINARY number in var
r := NumGet(var)
msgbox %p%, %r%  ; ==> 1000, 1000



Code:
hex dump of p (a normal AHK variable, stored as an ASCII STRING)
0000: 31 30 30 30 | 00 00 00 00 |  - 1000....
     0x31 = 1 0x30 = 0 0x30 = 0 0x30 = 0

hex dump of var (1000 stored as a BINARY value by the use of numput)
0000: E8 03 00 00 | 00 00 00 00 |  - è.......
      0x03E8 = 1000

hex dump of r (a normal AHK variable, stored as an ASCII STRING by use of numget)
0000: 31 30 30 30 | 00 00 00 00 |  - 1000....
     0x31 = 1 0x30 = 0 0x30 = 0 0x30 = 0


Thanks for these clarifications :)
So, if I follow those rules then this code :
Code:
VTable(ppv, idx)
{
   Return   NumGet(NumGet(1*ppv)+4*idx)
}


by emitting the postulate that 'ppv' contains the value '1000' and 'idx' value '12', then
NumGet(NumGet(1*ppv)+4*idx) seems totally strange to call twice NumGet, because if ppv contains 1000 then the computation would be :

(1*1000)+4*12) == 1048 ?
If the result is 1048, I really still don't understand why calling twice NumGet... ? :/


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 9th, 2009, 6:07 pm 
It seems you still don´t get, that NumGet is retrieving a Number stored at some address. It´s not a methematical function, so you cant know it´s result without knowing the number stored at that address.


Quote:
NumGet(VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Returns the binary number stored at the specified address+offset. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself.


So the two NumGets in Seans Code are not strange at all.
The inner NumGet retrieves the Address for the outer NumGet, thats all.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 10th, 2009, 10:14 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
This is what I replied in PM, and one more.

They are analogous to the dereference operator in C/C++.
Code:
val:=NumGet(1*ptr)
NumPut(val, 1*ptr)
Code:
val = *ptr
*ptr = val

Moreover, the following two are equivalent but the first is faster.
Code:
val:=NumGet(var)
NumPut(val, var)
Code:
val:=NumGet(&var)
NumPut(val, &var)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 25th, 2009, 4:57 pm 
Offline

Joined: December 25th, 2008, 3:50 pm
Posts: 23
Location: 50° lat.
Gerome wrote:
Code:
p := 1000
r := NumGet(p)
msgbox %p%, %r%  ; ==> 1000, 808464433


and
jimD wrote:
Code:
hex dump of p (a normal AHK variable, stored as an ASCII STRING)
0000: 31 30 30 30 | 00 00 00 00 |  - 1000....
     0x31 = 1 0x30 = 0 0x30 = 0 0x30 = 0

hex dump of var (1000 stored as a BINARY value by the use of numput)
0000: E8 03 00 00 | 00 00 00 00 |  - è.......
      0x03E8 = 1000


Bienvenue, Gérôme. I am absolutely positive, that you will buy into a statement that it took me nearly two months to go figure out the answer. De toute façon you can tell that the other gentlemen don't have a handle on this topic either. They have come to learn what works just like you will.

First and foremost, the Intel processor architecture is little-endian. Meaning that in a memory block it is the leftmost number that is multiplied with 2 raised to the power of zero.

Now, jimD used a memory scanner and posted an output fragment in abbreviated form. Taking his hint that AHK variables are of type str, one searches for those 4 =strlen(p) adjacent bytes in memory. A p-ointer stores the memory address at which this data is to be found at its own memory address. This is the PointertoaPointerVariable argument in VTable().

Here comes the crux. You casted what is meant to be a str as an int by calling numGet(). Thereby you have the computer calculate 30 30 30 31 as a decimal. He does it by summing 16^(8-pos) *(# @the pos), i.e.
    3 x 16^7 +
    0 x 16^6 +
    3 x 16^5 +
    0 x 16^4 +
    3 x 16^3 +
    0 x 16^2 +
    3 x 16^1 +
    1 x 16^0.
Do the math or enter 30303031 in the hexadecimal field here. You could have instructed numGet to fetch a short: numGet(p, 0, "short") and it would have taken the first two bytes from the left and casted them as a decimal. The result is? Going down this path the solution offers itself as
Code:
loop % strlen(p)
    Msgbox % str.=a_space char := chr(numGet(p, a_index-1, "char"))


Had you tried p = 10009, why would the outcome of a call to numGet() have been no different from 808,464,433? Because an int ends after 32 bits.

Gentlemen, drop the secrecy, take to empowering those people.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Apollo, batto, BrandonHotkey, G. Sperotto, Google [Bot], Miguel, notsoobvious, rbrtryn and 72 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group