|
-
Nov 5th, 2007, 10:14 AM
#1
Thread Starter
New Member
[RESOLVED] Understanding the CopyMemory method
This may sound like a silly question, but I've been having trouble reading an 8-byte REG_BINARY value from the registry and converting it to a Double. After extensive trial and error, I've discovered that the CopyMemory API is capable of doing that coversion. I've implemented it in the following way:
Code:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
' Irrelevant code...
Dim KeyHandle&, DataType&, BufferSize&, st$, lng&, bn() As Byte, dbl#
' Irrelevant code...
Case REG_BINARY
ReDim bn(0 To BufferSize - 1) As Byte
Call RegQueryValueEx(KeyHandle, Name, 0&, 0&, bn(0), BufferSize)
CopyMemory dbl, bn(0), CLng(UBound(bn) + 1)
RegistryRead = dbl
That way, a REG_BINARY value of hex:1c,0e,9a,bf,fe,3f,73,40 reads as 307.999694444444.
What I wanted to know is how exactly it is done. If I wanted, for instance, to manually convert (calc.exe?) the hexadecimal values above to the decimal result, how would I do that?
-
Nov 5th, 2007, 11:11 AM
#2
Re: Understanding the CopyMemory method
I understood everything until I got to this:
 Originally Posted by DonKeyDoo
What I wanted to know is how exactly it is done. If I wanted, for instance, to manually convert (calc.exe?) the hexadecimal values above to the decimal result, how would I do that?
I don't know what you are asking there....
You don't have to use CopyMemory, you can also use the LSet, for example, here I wrote code to test your result:
Code:
Option Explicit
Private Type t_Double
D As Double
End Type
Private Type t_B8
B(0 To 7) As Byte
End Type
Private Sub Form_Load()
Dim Dbl As t_Double
Dim DblB As t_B8
Dim K As Long
Dbl.D = 307.999694444444
LSet DblB = Dbl
For K = 0 To 7
Debug.Print Right("0" & Hex(DblB.B(K)), 2) & ",";
Next K
Debug.Print
End Sub
Using LSet is safer because it does some checks before it copies the memory, so it won't crash you application in case you copy more memory than the buffer can hold (in that case CopyMemory will crash your application, but LSet won't)
The only negative thing I don't like about LSet is that you have to define the Type structures and use those instead of variables... and it's kinda anoying... but it beats CopyMemory on safety...
By the way, I got this result when testing with the code: "14,0E,9A,BF,FE,3F,73,40"
-
Nov 5th, 2007, 03:38 PM
#3
Re: Understanding the CopyMemory method
I like that LSet method 
 Originally Posted by CVMichael
By the way, I got this result when testing with the code: "14,0E,9A,BF,FE,3F,73,40"
The number will still display as 307.999694444444 if the first byte is within the range &h0C to &h1C.... In other words it would appear ~ 4 bits of a double cannot be displayed or entered.
-
Nov 5th, 2007, 03:54 PM
#4
Re: Understanding the CopyMemory method
 Originally Posted by DonKeyDoo
<snip>...value of hex:1c,0e,9a,bf,fe,3f,73,40 reads as 307.999694444444.
What I wanted to know is how exactly it is done. If I wanted, for instance, to manually convert the hexadecimal values above to the decimal result, how would I do that?
Not so easily as the structure in memory does not align to bytes, you would have to extract and combine the appropriate bits from the bytes to get the Exponent and Mantissa.
-
Nov 6th, 2007, 03:26 AM
#5
Thread Starter
New Member
Re: Understanding the CopyMemory method
Thanks for your replies and assistance. I will definitely use the LSet method instead of CopyMemory. However, I'm still having difficulties understanding the logic behind the conversion. Viewing the structure of double in the memory helped, but mathematics is my soft spot, so there's still a gap. I've been trying to find a code that uses mathematical function for the conversion, rather than using the memory calls... but to no avail. Anyway, thanks again!
-
Nov 6th, 2007, 04:02 AM
#6
Thread Starter
New Member
Re: Understanding the CopyMemory method
 Originally Posted by CVMichael
You don't have to use CopyMemory, you can also use the LSet, for example, here I wrote code to test your result:
Can I use the LSet method the other way around? In your example you've shown how to convert double to to an 8-byte array, but how can I use LSet to convert the array to a double? I seem to be getting a type-mismatch error when I try to run it the other way around...
-
Nov 6th, 2007, 06:02 AM
#7
Re: Understanding the CopyMemory method
 Originally Posted by DonKeyDoo
I'm still having difficulties understanding the logic behind the conversion. [...] I've been trying to find a code that uses mathematical function for the conversion, rather than using the memory calls...
There is no mathematical way to do the conversion you ask for. The reason for that is that it depends on how you interpret the numbers. If you look at a binary number like 101, you might know that this equals 5 in the decimal system. However that is only true if 101 should be interpreted as an integer number. A stream of bits can be interpreted in many different ways depending on the data type you're using. A single or a double doesn't interpret a stream of bits as an integer number. A string wouldn't intepret it as that either, it would convert the bits into characters.
The binary value you read from the registry happens to be 8 byte long, or 64 bits long. Depending on how you want to interpret the information it could represent a 8-byte floating point value (a Double) or maybe as a 8 or 4 character string (depending on the format used). Or maybe it represent two 32-bit integer values (Long) or four 16 bit integer values (Integer).
When you use CopyMemory you simply copy the bit-stream from one memory location to another and depending on the data type used as the target you would get different interpretations of the data.
In fact, the binary number 101, could just as well mean "bread and milk", in a shopping list application that interprets the numbers that way.
-
Nov 6th, 2007, 08:36 AM
#8
Re: Understanding the CopyMemory method
 Originally Posted by DonKeyDoo
Can I use the LSet method the other way around? In your example you've shown how to convert double to to an 8-byte array, but how can I use LSet to convert the array to a double? I seem to be getting a type-mismatch error when I try to run it the other way around... 
The opposite is like this:
Code:
Option Explicit
Private Type t_Double
D As Double
End Type
Private Type t_B8
B(0 To 7) As Byte
End Type
Private Sub Form_Load()
Dim Dbl As t_Double
Dim DblB As t_B8
' Set the binary data
DblB.B(0) = &H1C
DblB.B(1) = &HE
DblB.B(2) = &H9A
DblB.B(3) = &HBF
DblB.B(4) = &HFE
DblB.B(5) = &H3F
DblB.B(6) = &H73
DblB.B(7) = &H40
' Copy from byte array to a double
LSet Dbl = DblB
Debug.Print Dbl.D
End Sub
-
Nov 7th, 2007, 10:27 AM
#9
Thread Starter
New Member
Re: Understanding the CopyMemory method
Hey everybody. Thanks again for your replies. You've been a great help.
After reading about the double precision structure in memory, I've decided to write a covnersion function in spite of the LSet and CopyMemory methods... Here's a test example:
vb Code:
Public Sub Test()
Dim str$, x&, exponent&, mantissa As Double
mantissa = 1
divider = 1
str = "0100000001110011001111111111111010111111100110100000111000011100"
sign = CLng(Mid(str, 1, 1))
' assuming 64-bit
For x = 12 To 2 Step -1
If CLng(Mid(str, x, 1)) = 1 Then exponent = exponent + (2 ^ (Abs(x - 12)))
Next x
For x = 13 To 64
If CLng(Mid(str, x, 1)) = 1 Then mantissa = mantissa + (1 / (2 ^ (x - 12)))
Next x
Debug.Print ((-1) ^ sign) * (2 ^ (exponent - 1023)) * mantissa 'exponent bias is 0x3ff = 1023
End Sub
It works!
Thanks again!
-
Nov 7th, 2007, 10:30 AM
#10
Thread Starter
New Member
Re: [RESOLVED] Understanding the CopyMemory method
hmm.. disregard "divider = 1" I don't know how it got there :P
-
Nov 7th, 2007, 12:06 PM
#11
Re: [RESOLVED] Understanding the CopyMemory method
Just FYI... you can edit your post and make the changes, instead of making a new post stating the mistake....
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|