I have the following bitfield struct:
struct DescriptorByte
{
unsigned short IsImmedCalc : 1;
unsigned short IsPrefix : 1;
unsigned short NoMemOp : 1;
unsigned short Size : 5;
};
I want to create an table for holding many DescriptorByte struct, so i created this:
struct OpcodeList
{
DescriptorByte ADD_8_MO;
DescriptorByte ADD_32_MO;
DescriptorByte ADD_8_OM;
DescriptorByte ADD_32_OM;
DescriptorByte ADD_8_OI = { TRUE, FALSE, TRUE, 1 + 1 };
DescriptorByte ADD_32_OI = { TRUE, FALSE, TRUE, 1 + 4 };
DescriptorByte PUSH_ES = { TRUE, FALSE, TRUE, 1 };
};
So is this the same as having an struct with each member beign 1 byte long?. Also i want to be able to reference the initializator member like this:
DescriptorByte ADD_8_OI = { IsImmedCalc = true, Size = 1 };
but visual studio is not letting me. The idea behind all of this is having a table of DescriptorByte, is this the best approach? also what is the best initialization method? thanks.
"is this the same as having a struct with each member being 1 byte long?"
Your compiler might add padding if you do not use #pragma pack or something similar.
But there isn't any padding required in this specific case, so essentially the answer is yes.
Just change the unsigned short to unsigned char and each member will be 1 byte long.
Add '.' on the left side of each field:
DescriptorByte ADD_8_OI = { .IsImmedCalc = true, .Size = 1 };
Alternatively, just write the actual values in the correct order (missing ones will be set to 0):
DescriptorByte ADD_8_OI = { true, 1 };
EDIT: Posted this thinking it was a C# question, sorry! Leaving it here for others.
C# does not support bit-fields. However, you can still 'emulate' that behavior using a single member variable of the appropriate size along with various getter properties.
In your example, you want to use an unsigned 8-bit integer value (byte) and encapsulate those bitfields. Have no fear, you can still use a struct to do all this to make marshaling and interop easier.
So let's take your DescriptorByte and recreate what you are looking to do:
struct DescriptorByte
{
static readonly byte IsImmedCalcFlag = 0x80; // 1000 0000
static readonly byte IsPrefixFlag = 0x40; // 0100 0000
static readonly byte NoMemOpFlag = 0x20; // 0010 0000
static readonly byte FlagsBitMask = 0xE0; // 1110 0000
static readonly byte SizeBitMask = 0x1F; // 0001 1111
byte field;
public bool IsImmedCalc
{
get { return (field & IsImmedCalcFlag) > 0; }
set
{
if (value)
field = (byte)(field | IsImmedCalcFlag); // Set the bit
else
field = (byte)(field & ~IsImmedCalcFlag); // Clear the bit
}
}
public bool IsPrefix
{
get { return (field & IsPrefixFlag) > 0; }
set
{
if (value)
field = (byte)(field | IsPrefixFlag); // Set the bit
else
field = (byte)(field & ~IsPrefixFlag); // Clear the bit
}
}
public bool NoMemOp
{
get { return (field & NoMemOpFlag) > 0; }
set
{
if (value)
field = (byte)(field | NoMemOpFlag); // Set the bit
else
field = (byte)(field & ~NoMemOpFlag); // Clear the bit
}
}
public byte Size
{
get { return (byte)(field & SizeBitMask); }
set { field = (byte)((field & FlagsBitMask) | (value & SizeBitMask)); }
}
}
Related
I'm a Rust beginner which comes from C/C++. To start off I tried to create a simple "Hello-World" like program for Microsoft Windows using user32.MessageBox where I stumbled upon a problem related to bitfields. Disclaimer: All code snippets were written in the SO editor and might contain errors.
MessageBox "Hello-World" in C
The consolidated C declarations needed to call the UTF-16LE version of the function are:
enum MessageBoxResult {
IDFAILED,
IDOK,
IDCANCEL,
IDABORT,
IDRETRY,
IDIGNORE,
IDYES,
IDNO,
IDTRYAGAIN = 10,
IDCONTINUE
};
enum MessageBoxType {
// Normal enumeration values.
MB_OK,
MB_OKCANCEL,
MB_ABORTRETRYIGNORE,
MB_YESNOCANCEL,
MB_YESNO,
MB_RETRYCANCEL,
MB_CANCELTRYCONTINUE,
MB_ICONERROR = 0x10UL,
MB_ICONQUESTION = 0x20UL,
MB_ICONEXCLAMATION = 0x30UL,
MB_ICONINFORMATION = 0x40UL,
MB_DEFBUTTON1 = 0x000UL,
MB_DEFBUTTON2 = 0x100UL,
MB_DEFBUTTON3 = 0x200UL,
MB_DEFBUTTON4 = 0x300UL,
MB_APPLMODAL = 0x0000UL,
MB_SYSTEMMODAL = 0x1000UL,
MB_TASKMODAL = 0x2000UL,
// Flag values.
MB_HELP = 1UL << 14,
MB_SETFOREGROUND = 1UL << 16,
MB_DEFAULT_DESKTOP_ONLY = 1UL << 17,
MB_TOPMOST = 1UL << 18,
MB_RIGHT = 1UL << 19,
MB_RTLREADING = 1UL << 20,
MB_SERVICE_NOTIFICATION = 1UL << 21
};
MessageBoxResult __stdcall MessageBoxW(
HWND hWnd,
const wchar_t * lpText,
const wchar_t * lpCaption,
MessageBoxType uType
);
Usage:
MessageBoxType mbType = MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON3 | MB_TOPMOST;
if ((mbType & 0x0F /* All bits for buttons */ == MB_YESNO) && (mbType & 0xF0 /* All bits for icons */ == MB_ICONEXCLAMATION) && (mbType & 0xF00 /* All bits for default buttons */ == MB_DEFBUTTON3) && (mbType & MB_TOPMOST != 0)) {
MessageBoxW(NULL, L"Text", L"Title", mbType);
}
The MessageBoxType enumeration contains enumeration values and flag values. The problem with that is that MB_DEFBUTTON2 and MB_DEFBUTTON3 can be used together and "unexpectedly" result in MB_DEFBUTTON4. Also the access is quite error prone and ugly, I have to |, & and shift everything manually when checking for flags in the value.
MessageBox "Hello-World" in C++
In C++ the same enumeration can be cleverly put into a structure, which has the same size as the enumeration and makes the access way easier, safer and prettier. It makes use of bitfields - the layout of bitfields not defined by the C standard, but since I only want to use it for x86-Windows it is always the same, so I can rely on it.
enum class MessageBoxResult : std::uint32_t {
Failed,
Ok,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
TryAgain = 10,
Continue
};
enum class MessageBoxButton : std::uint32_t {
Ok,
OkCancel,
AbortRetryIgnore,
YesNoCancel,
YesNo,
RetryCancel,
CancelTryContinue
};
enum class MessageBoxDefaultButton : std::uint32_t {
One,
Two,
Three,
Four
};
// Union so one can access all flags as a value and all boolean values separately.
union MessageBoxFlags {
enum class Flags : std::uint32_t {
None,
Help = 1UL << 0,
SetForeground = 1UL << 2,
DefaultDesktopOnly = 1UL << 3,
TopMost = 1UL << 4,
Right = 1UL << 5,
RtlReading = 1UL << 6,
ServiceNotification = 1UL << 7
};
// Flags::operator|, Flags::operator&, etc. omitted here.
Flags flags;
struct {
bool help : 1;
char _padding0 : 1;
bool setForeground : 1;
bool defaultDesktopOnly : 1;
bool topMost : 1;
bool right : 1;
bool rtlReading : 1;
bool serviceNotification : 1;
char _padding1 : 8;
char _padding2 : 8;
char _padding3 : 8;
};
constexpr MessageBoxFlags(const Flags flags = Flags::None)
: flags(flags) {}
};
enum class MessageBoxIcon : std::uint32_t {
None,
Stop,
Question,
Exclamation,
Information
};
enum class MessageBoxModality : std::uint32_t {
Application,
System,
Task
};
union MessageBoxType {
std::uint32_t value;
struct { // Used bits Minimum (Base 2) Maximum (Base 2) Min (Base 16) Max (Base 16)
MessageBoxButton button : 4; // 0000.0000.0000.0000|0000.0000.0000.XXXX 0000.0000.0000.0000|0000.0000.0000.0000 - 0000.0000.0000.0000|0000.0000.0000.0110 : 0x0000.0000 - 0x0000.0006
MessageBoxIcon icon : 4; // 0000.0000.0000.0000|0000.0000.XXXX.0000 0000.0000.0000.0000|0000.0000.0001.0000 - 0000.0000.0000.0000|0000.0000.0100.0000 : 0x0000.0010 - 0x0000.0040
MessageBoxDefaultButton defaultButton : 4; // 0000.0000.0000.0000|0000.XXXX.0000.0000 0000.0000.0000.0000|0000.0001.0000.0000 - 0000.0000.0000.0000|0000.0011.0000.0000 : 0x0000.0100 - 0x0000.0300
MessageBoxModality modality : 2; // 0000.0000.0000.0000|00XX.0000.0000.0000 0000.0000.0000.0000|0001.0000.0000.0000 - 0000.0000.0000.0000|0010.0000.0000.0000 : 0x0000.1000 - 0x0000.2000
MessageBoxFlags::Flags flags : 8; // 0000.0000.00XX.XXXX|XX00.0000.0000.0000 0000.0000.0000.0000|0100.0000.0000.0000 - 0000.0000.0010.0000|0000.0000.0000.0000 : 0x0000.4000 - 0x0020.0000
std::uint32_t _padding0 : 10; // XXXX.XXXX.XX00.0000|0000.0000.0000.0000
};
MessageBoxType(
const MessageBoxButton button,
const MessageBoxIcon icon = MessageBoxIcon::None,
const MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton::One,
const MessageBoxModality modality = MessageBoxModality::Application,
const MessageBoxFlags::Flags flags = MessageBoxFlags::Flags::None
) : button(button), icon(icon), defaultButton(defaultButton), modality(modality), flags(flags), _padding0(0) {}
MessageBoxType() : value(0) {}
};
MessageBoxResult __stdcall MessageBoxW(
HWND parentWindow,
const wchar_t * text,
const wchar_t * caption,
MessageBoxType type
);
Usage:
auto mbType = MessageBoxType(MessageBoxButton::YesNo, MessageBoxIcon::Exclamation, MessageBoxDefaultButton::Three, MessageBoxModality::Application, MessageBoxFlags::Flags::TopMost);
if (mbType.button == MessageBoxButton::YesNo && mbType.icon == MessageBoxIcon::Exclamation && mbType.defaultButton == MessageBoxDefaultButton::Three && mbType.flags.topMost) {
MessageBoxW(nullptr, L"Text", L"Title", mbType);
}
With this C++ version I can access flags as boolean values and have enumeration classes for the other types, all while it still being a simple std::uint32_t in memory. Now I struggled to implement this in Rust.
MessageBox "Hello-World" in Rust
#[repr(u32)]
enum MessageBoxResult {
Failed,
Ok,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
TryAgain = 10,
Continue
}
#[repr(u32)]
enum MessageBoxButton {
Ok,
OkCancel,
AbortRetryIgnore,
YesNoCancel,
YesNo,
RetryCancel,
CancelTryContinue
}
#[repr(u32)]
enum MessageBoxDefaultButton {
One,
Two,
Three,
Four
}
#[repr(u32)]
enum MessageBoxIcon {
None,
Stop,
Question,
Exclamation,
Information
}
#[repr(u32)]
enum MessageBoxModality {
Application,
System,
Task
}
// MessageBoxFlags and MessageBoxType ?
I know about the WinApi crate which to my understanding is generated automatically from VC++-header files which doesn't help, because I will have the same problems as in C. I also saw the bitflags macro but it seems to me it doesn't handle this kind of "complexity".
How would I implement MessageBoxFlags and MessageBoxType in Rust, so I can access it in a nice (not necessarily the same) way as in my C++ implementation?
The bitfield crate #Boiethios mentioned is kind of what I wanted. I created my own first macro crate bitfield which allows me to write the following:
#[bitfield::bitfield(32)]
struct Styles {
#[field(size = 4)] button: Button,
#[field(size = 4)] icon: Icon,
#[field(size = 4)] default_button: DefaultButton,
#[field(size = 2)] modality: Modality,
style: Style
}
#[derive(Copy, Clone, bitfield::Flags)]
#[repr(u8)]
enum Style {
Help = 14,
Foreground = 16,
DefaultDesktopOnly,
TopMost,
Right,
RightToLeftReading,
ServiceNotification
}
#[derive(Clone, Copy, bitfield::Field)]
#[repr(u8)]
enum Button {
Ok,
OkCancel,
AbortRetryIgnore,
YesNoCancel,
YesNo,
RetryCancel,
CancelTryContinue
}
#[derive(Clone, Copy, bitfield::Field)]
#[repr(u8)]
enum DefaultButton {
One,
Two,
Three,
Four
}
#[derive(Clone, Copy, bitfield::Field)]
#[repr(u8)]
enum Icon {
None,
Stop,
Question,
Exclamation,
Information
}
#[derive(Clone, Copy, bitfield::Field)]
#[repr(u8)]
enum Modality {
Application,
System,
Task
}
I can then use the code like this:
// Verbose:
let styles = Styles::new()
.set_button(Button::CancelTryContinue)
.set_icon(Icon::Exclamation)
.set_style(Style::Foreground, true)
.set_style(Style::TopMost, true);
// Alternatively:
let styles = Styles::new() +
Button::CancelTryContinue +
Icon::Exclamation +
Style::Foreground +
Style::TopMost;
let result = user32::MessageBoxW(/* ... */, styles);
I am really new to using DWORD in C++ in place of boolean. Hence, please excuse my question.
I have an enum:
enum foo
{
foo1 = 0x0;
foo2 = 0x1
//....
}
DWORD foo;
I am using this enum to check for multiple conditions:
if(somethinghappenstothisvariable)
{
foo|= foo1;
}
if(somethinghappenstosecondvariable)
{
foo|=foo2;
}
Now in another file I have to check for individual variables condition
if(foo &foo1)
{
//do something;
}
if(foo & foo2)
{
//do something;
}
I figured that |= adds up the value to the DWORD if both conditions are true which leads to foo & foo2 only to be true while foo & foo1 will not be as the value of DWORD will be 1. Hence, I was wondering if there is anyway I can check this for individual DWORD value.
The issue: 1 = bit 0, 0 is invalid.
To the check each "condition" should represent a separate bit (bit 0 = 1, bit 1 = 2, etc.)
So - a simple change: foo1 = 0x01; foo2 = 0x02; should fix it.
NOTE: any additional checks should represent bit values, NOT ordinal.
In other words, foo3 = 0x04; (not 0x03;)
You can make it correct easier by creating these constants with shifts:
enum foo
{
foo1 = 1 << 0;
foo2 = 1 << 1;
foo3 = 1 << 2;
//....
}
This way you can be sure that each mask has a single bit set.
I have a bitfield struct called DescriptorByte aligned to 1 byte and a struct for holding lots of DescriptorByte like this:
struct DescriptorByte
{
unsigned char IsImmedCalc : 1;
unsigned char IsPrefix : 1;
unsigned char NoMemOp : 1;
unsigned char Size : 5;
};
struct OpcodeList
{
DescriptorByte ADD_EB_GB;
DescriptorByte ADD_EV_GV;
DescriptorByte ADD_GB_EB;
DescriptorByte ADD_GV_EV;
DescriptorByte ADD_8_OI = { TRUE, FALSE, TRUE, OPBASE + IMMED_8 };
DescriptorByte ADD_32_OI = { TRUE, FALSE, TRUE, OPBASE + IMMED_32 };
DescriptorByte PUSH_ES = { TRUE, FALSE, TRUE, OPBASE };
DescriptorByte POP_ES = { TRUE, FALSE, TRUE, OPBASE };
DescriptorByte OR_EB_GB;
//ETC
};
What i want to do is based on a number (byte) iterating through the struct like this:
OpcodeList opcodelist;
BYTE count = 5;
DescriptorByte = opcodelist + count;
Since the bitfield struct is aligned to 1 byte i should get the 5th element of the OpcodeList table, but i dont know how to make this on C++ i only know how to make it in ASM :/
LEA EAX, OPCODELIST
MOV ECX, COUNT
MOV EAX, DWORD PTR [EAX+ECX];
AND EAX, 0FF;
Thanks.
You are trying to access this "list" multiple ways: By name (like ADD_EB_GB), and by index. You can't do this with a struct.
I would suggest using a std::vector<DescriptorByte> (or std::array). This way you can access by index. And if you still need to access by name, make your names constant indices into this vector.
A bit like this:
typedef std::array<DescriptorByte, 9> OpcodeList;
enum OpcodeIndex
{
ADD_EB_GB = 0,
ADD_EV_GV,
ADD_GB_EB,
ADD_GV_EV,
ADD_8_OI,
ADD_32_OI,
PUSH_ES,
POP_ES,
OR_EB_GB
}
...
// instantiate & initialize an opcode list.
OpcodeList opcodeList =
{
{ ... },// ADD_EB_GB,
{ ... },// ADD_EV_GV,
{ ... },// ADD_GB_EB,
{ ... },// ADD_GV_EV,
{ TRUE, FALSE, TRUE, OPBASE + IMMED_8 },// ADD_8_OI,
{ TRUE, FALSE, TRUE, OPBASE + IMMED_32 },// ADD_32_OI,
{ TRUE, FALSE, TRUE, OPBASE },// PUSH_ES,
{ TRUE, FALSE, TRUE, OPBASE },// POP_ES,
{ ... }// OR_EB_GB
};
// to access by symbol:
DescriptorByte someOpcode = opcodeList[ADD_GV_EV];
// to access by symbol + offset:
DescriptorByte anotherOpcode = opcodeList[ADD_GV_EV + 5];
Note about performance. At the machine code level, a struct and a statically sized array will perform exactly the same. They are ptr+offset fields. This is exactly what std::array will compile into. std::vector will have more overhead because it supports varying sizes, so only use it if you will have OpcodeList objects that have different sizes.
Regarding initialization, it's true this is more verbose / uglier than what you have, but it's a worthy effort to keep things manageable.
You can also do this using your struct:
OpcodeList opcodelist;
BYTE count = 5;
void* p1 = &opcodelist;
DescriptorByte* p2 = (DescriptorByte*)p1;
DescriptorByte = *(p2 + count);
enum AccessSource
{
AccessSourceNull = 0x00000001,
AccessSourceSec = 0x00000002,
AccessSourceIpo = 0x00000004,
AccessSourceSSA = 0x00000008,
AccessSourceUpgrade = 0x00000010,
AccessSourceDelta = 0x00000020,
AccessSourcePhoneM = 0x00000040,
AccessSourceSoft = 0x00000080,
AccessSourceCR = 0x00000100,
AccessSourceA = 0x00000200,
AccessSourceE = 0x00000400,
AccessSourceAll = 0xFFFFFFFF
};
What is the value of AccessSourceAll ?? is it -1? or is it maximum value?
I have a parameter ULONG x , whose default value is AccessSourceAll(that means access to all). How do i remove the access right of AccessSourceE only?
How to add the access right of AccessSourceE again?
If i have a particular value in x, then how do i know whether AccessSourceE is set or not?
The value of AccessSourceAll is (int)0xFFFFFFFF since enum is of type int in C.
The unset just AccessSourceE use:
x & ~AccessSourceE // to assign: x &= ~AccessSourceE;
To add, use
x | AccessSourceE // to assign: x |= AccessSourceE;
To test,
if (x & AccessSourceE) { ... }
I'm not sure it'll actually matter since it is a mask which will clearly have a bit set for each of the other values.
If you are assigning it to a ULONG, it will be an unsigned type. To set/remove values use bitwise logic:
x |= AccessSourceE; /* set SourceE */
x &= ~AccessSourceE; /* unset SourceE */
if(x & AccessSourceE) /* test SourceE */
You can use the ^ operator for this.
For Example :
unsigned long l_unValue = AccessSource::AccessSourceAll;
l_unValue = l_unValue ^ AccessSource::AccessSourceE;
The above statement will remove "AccessSourceE" from "AccessSourceAll".
How could I make a function with flags like how Windows' CreateWindow(...style | style,...), for example, a createnum function:
int CreateNum(flag flags) //???
{
int num = 0;
if(flags == GREATER_THAN_TEN)
num = 11;
if(flags == EVEN && ((num % 2) == 1)
num++;
else if(flags == ODD && ((num % 2) == 0)
num++;
return num;
}
//called like this
int Number = CreateNum(GREATER_THAN_TEN | EVEN);
Is this possible, and if so, how?
You can define an enum specifying "single bit" values (note that the enclosing struct is acting here only as a naming context, so that you can write e.g. MyFlags::EVEN):
struct MyFlags{
enum Value{
EVEN = 0x01,
ODD = 0x02,
ANOTHER_FLAG = 0x04,
YET_ANOTHER_FLAG = 0x08,
SOMETHING_ELSE = 0x10,
SOMETHING_COMPLETELY_DIFFERENT = 0x20
};
};
and then use it like this:
int CreateNum(MyFlags::Value flags){
if (flags & MyFlags::EVEN){
// do something...
}
}
void main(){
CreateNum((MyFlags::Value)(MyFlags::EVEN | MyFlags::ODD));
}
or simply like this:
int CreateNum(int flags){
if (flags & MyFlags::EVEN){
// do something...
}
}
void main(){
CreateNum(MyFlags::EVEN | MyFlags::ODD);
}
You could also simply declare integer constants, but the enum is clearer in my opinion.
Note: I updated the post to take some comments into account, thanks!
I upvoted orsogufo's answer, but I always liked doing the following for defining the values:
enum Value{
EVEN = (1<<0),
ODD = (1<<2),
ANOTHER_FLAG = (1<<3),
YET_ANOTHER_FLAG = (1<<4),
SOMETHING_ELSE = (1<<5),
SOMETHING_COMPLETELY_DIFFERENT = (1<<6),
ANOTHER_EVEN = EVEN|ANOTHER_FLAG
};
<< is the shift operator. Incrementing the right side lets you generate sequential bit masks by moving the 1 over, one bit at a time. This has the same values for the bare flags, but reads easier to my eyes and makes it obvious if you skip or duplicate a value.
I also like combining some common flag combinations when appropriate.
You can use const int like this:
const int FLAG1 = 0x0001;
const int FLAG2 = 0x0010;
const int FLAG3 = 0x0100;
// ...
And when you use it:
int CreateNum(int flags)
{
if( flags & FLAG1 )
// FLAG1 is present
if( flags & FLAG2 )
// FLAG2 is present
// ...
}
Of course you can put one or more flag in your flags using the | operator.
Use powers of two as the individual constants, like
enum Flags { EVEN = 0x1, ODD = 0x2, GREATER_TEN = 0x4 };
and you use the logical and operator '&' for testing, like
if( flags & GREATER_THAN_TEN)
num = 11;
if( (flags & EVEN) && (num % 2) == 1 )
num++;
else if ( (flags & ODD) && (num % 2) == 0 )
num++;
return num;
You've got your tests wrong. What you want is something like (flags & EVEN), where EVEN is an integer with a single bit set (1, 2, 4, 8, 16 - some power of 2). (The integer can be an int or an enum. You could have a macro, but that's generally not a good idea.)
You can use the notation you listed, by overloading flags::operator==(flagvalue f), but it's a bad idea.
enum flags {
EVEN = 0x0100,
ODD = 0x0200,
BELOW_TEN = 0x0400,
ABOVETEN = 0x0800,
HUNDRED = 0x1000,
MASK = 0xff00
};
void some_func(int id_and_flags)
{
int the_id = id_and_flags & ~MASK;
int flags = id_and_flags & MASK;
if ((flags & EVEN) && (the_id % 2) == 1)
++the_id;
if ((flags & ODD) && (the_id % 2) == 0)
++the_id;
// etc
}
Illustrates masking of bit fields too which can be useful when you just need to bolt on a simplistic bit of extra functionality without adding any extra data structure.