There is a special kind of enums: bitfields. A bitfield is an enum divided into bit groups. When you define a new symbolic constant in a bitfield, you need to specify the group to which the constant will belong to. By default, IDA proposes groups containing one bit each. If a group is not defined yet, it is automatically created when the first constant in the group is defined. For example:
name CONST1
value 0x1
mask 0x1will define a constant named CONST1 with value 1 and will create a group containing only one bit. Another example. Let's consider the following definitions:
#define OOF_SIGNMASK 0x0003
#define OOFS_IFSIGN 0x0000
#define OOFS_NOSIGN 0x0001
#define OOFS_NEEDSIGN 0x0002
#define OOF_SIGNED 0x0004
#define OOF_NUMBER 0x0008
#define OOF_WIDTHMASK 0x0030
#define OOFW_IMM 0x0000
#define OOFW_16 0x0010
#define OOFW_32 0x0020
#define OOFW_8 0x0030
#define OOF_ADDR 0x0040
#define OOF_OUTER 0x0080
#define OOF_ZSTROFF 0x0100How do we describe this?
name value mask maskname
OOFS_IFSIGN 0x0000 0x0003 OOF_SIGNMASK
OOFS_NOSIGN 0x0001 0x0003 OOF_SIGNMASK
OOFS_NEEDSIGN 0x0002 0x0003 OOF_SIGNMASK
OOF_SIGNED 0x0004 0x0004
OOF_NUMBER 0x0008 0x0008
OOFW_IMM 0x0000 0x0030 OOF_WIDTHMASK
OOFW_16 0x0010 0x0030 OOF_WIDTHMASK
OOFW_32 0x0020 0x0030 OOF_WIDTHMASK
OOFW_8 0x0030 0x0030 OOF_WIDTHMASK
OOF_ADDR 0x0040 0x0040
OOF_OUTER 0x0080 0x0080
OOF_ZSTROFF 0x0100 0x0100If a mask consists of more than one bit, it can have a name and a comment. A mask name can be set when a constant with the mask is being defined. IDA will display the mask names in a different color.
In order to use a bitfield in the program, just convert an instruction operand to enum. IDA will display the operand like this:
will be replaced by
mov ax, 70h mov ax, OOFS_IFSIGN or OOFW_8 or OOF_ADDRSuppose the source text looked like this:
void out_operand(int opnum, int flags);
// 'flags' parameter is combination of the following bits:
// (don't use OOF_SIGNMASK and OOF_WIDTHMASK, they are for the kernel)
#define OOF_SIGNMASK 0x0003 // sign output:
#define OOFS_IFSIGN 0x0000 // output sign if needed
#define OOFS_NOSIGN 0x0001 // should not out sign ()
#define OOFS_NEEDSIGN 0x0002 // always out sign (+-)
#define OOF_SIGNED 0x0004 // output as signed if
// This function output the first 2 operands of instruction
void out_operands(void)
{
// the first operand is a signed value
out_operand(0, OOFS_IFSIGN|OOF_SIGNED|OOFW_IMM);
// the first operand is a unsigned 32bit address
out_operand(1, OOFS_NOSIGN|OOF_ADDR|OOFW_32);
}We have a disassembly like this:
Let’s improve it by using bitfields. We first define a bitfield type by opening an enumeration window (menu View|Enumerations) where we press Ins to create a new object and make it a bitfield. The name given to the bitfield does not matter much. We press Ctrl-N to define the bitfield values.
The first bitfield mask is 3 (or 2 bits). The name of the mask is not used by IDA, it is intended as a memory helper. Out of the 4 values this field can take, we only define the first value, zero, and assign a name to it : OOFS_IFSIGN. If we want to define other values, within the fields limits, we just repeat the process. With some comments, the definition becomes
We switch to the disassembly window (or close the enumeration window with Alt-F3). Through the Edit|Operand types|Enum member menu we select the enum type we just defined and get this result…
That’s all folks !



