Translating a bitwise operation from C++

J

John Dann

I'm trying to generate a 4-byte unsigned integer in VB2005 that
encodes a number of bit-level variables. What I need to do is to be
able to compute a value for the uint that is based on specific values
for the constituent variables; the unit can then be passed to an
external DLL, which requires a function parameter in this form.

Unfortunately the only documentation I have for the external DLL is in
(I think) C++, which I'm struggling to understand. The C++ code for
the procedure to create a value for the number is:

MakeNumber(CV, DU, DT, ST, SID)

( ((CV) & 0x1F) | (((DU) & 0x1F)<<5) | (((DT) & 0x1F)<<10) |

(((ST) & 0xFF)<<16) | (((SID) & 0xFF)<<24) )

(The 3 lines above are all on a single line in the original code.)

So, the procedure is encoding values for the 5 variables CV, DU, DT,
ST, SID) in assembling the final uint.

Now I can see the gist of what's being done here and can spot the
bitwise operators but I've got 2 questions about how to translate this
procedure into VB2005:

1. Is there some equivalent assembly procedure that I can use in
VB2005 and if so what would the exact syntax be? For example is there
any equivalent of what seems to be the | operator?

2. What data type should I use for the values held in CV, DU etc?
UShort maybe?

Many thanks for any help.
 
M

Michael M.

The data 0xff is the same as 11111111 in binrary and would be a single byte
so the data type is byte or Char or short I think, the operators convert
something like this:

| = OR
& = AND
<< = Shift bit left (probably a function for this in VB.net)

In C++ a single operator means a bitwise action to do on a value and a
double operator is used in logical comparsions the following below would be
used in if statements to compare things:

||
==
&&

Regards,

Mike.
 
M

Michael C

John Dann said:
MakeNumber(CV, DU, DT, ST, SID)

( ((CV) & 0x1F) | (((DU) & 0x1F)<<5) | (((DT) & 0x1F)<<10) |

(((ST) & 0xFF)<<16) | (((SID) & 0xFF)<<24) )

(CV And &h1f) or ((DU and &h1f) * 32) or ((DT And &h1f) * 1024) or ((ST And
&hff) * 65536) or ((SID And &hff) * 16777216)

You might have issues with the last bracketed section because I presume this
will default to signed int. You might need to convert them to unsigned int
and then back.
2. What data type should I use for the values held in CV, DU etc?
UShort maybe?

It is a macro so not specified. Most likely they used 32 bit int.

Michael
 
J

John Dann

(CV And &h1f) or ((DU and &h1f) * 32) or ((DT And &h1f) * 1024) or ((ST And
&hff) * 65536) or ((SID And &hff) * 16777216)

You might have issues with the last bracketed section because I presume this
will default to signed int. You might need to convert them to unsigned int
and then back.


It is a macro so not specified. Most likely they used 32 bit int.

Thanks for the response. Actually, I do have a bit more info on the
data types in the original - just didn't include it in the original
question in the interests of brevity (and also because I didn't fully
understand it!). The relevant details are below. (These details define
the memory structure that the number I'm trying to generate needs to
access, so the bit structures of the two integers must presumably
mirror one another.)

struct VarA // the same size as a UINT
{
unsigned int CV: 5;
unsigned int DU: 5;
unsigned int DT: 5;
unsigned int reserved : 1;

unsigned int ST : 8;
unsigned int SID: 8;

bool IsCurrentVariable(); // is the ID valid for current data?
bool IsHiLowVariable(); // is ID valid for Hi/Low data?

};

union ID
{
DWORD id;
VarA fields;
};

I've been able to make some progress in getting this working in that
the code for creating the 4-byte uint compiles and the resulting
number does return a value when passed in the function call, but
unfortuantely it's not the right value! So I still have work to do and
any further ideas would be very helpful.

The structure of my code at present is:

Dim result as ULong
Dim CV, DU, DT, ST, SID as UShort

result = _
(CV And &h1f) or ((DU and &h1f) * 32) or ((DT And &h1f) * 1024) or _
((ST And &hff) * 65536) or ((SID And &hff) * 16777216)

(I've also tried declaring CV etc as UInteger but no change - result
is identical and still wrong.)


I wasn't sure exactly what was meant by:
You might have issues with the last bracketed section because I presume this
will default to signed int. You might need to convert them to unsigned int
and then back.

Could someone spell out just what might need converting please, ie the
whole result value or the last bracketed part?
 
M

Michael C

John Dann said:
Thanks for the response. Actually, I do have a bit more info on the
data types in the original - just didn't include it in the original
question in the interests of brevity (and also because I didn't fully
understand it!). The relevant details are below. (These details define
the memory structure that the number I'm trying to generate needs to
access, so the bit structures of the two integers must presumably
mirror one another.)

That makes sense although I'm not sure you could duplicate this in vb.net.
You could try using the FieldOffset attribute.
I've been able to make some progress in getting this working in that
the code for creating the 4-byte uint compiles and the resulting
number does return a value when passed in the function call, but
unfortuantely it's not the right value! So I still have work to do and
any further ideas would be very helpful.

The structure of my code at present is:

Dim result as ULong
Dim CV, DU, DT, ST, SID as UShort

result = _
(CV And &h1f) or ((DU and &h1f) * 32) or ((DT And &h1f) * 1024) or _
((ST And &hff) * 65536) or ((SID And &hff) * 16777216)

(I've also tried declaring CV etc as UInteger but no change - result
is identical and still wrong.)

Everything should be uinteger I believe (int is 32bit in VB I presume). To
find the problem try giving CV a non-zero value and everything else a zero
value. Do you get the expected result? If so then try the same thing for DU
and then DT etc.
I wasn't sure exactly what was meant by:


Could someone spell out just what might need converting please, ie the
whole result value or the last bracketed part?

With vb it will default to signed integer in most cases. This can cause
problems when doing math like this because the most significant bit is the
sign. To avoid errors you need to define everything as unsigned int. Eg:
&hffff * &h10000 should give &hffff0000 but will give an error if unsigned
is not used.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top