nop
nop

Reputation: 6311

The opposite of bitwise AND

I don't like so many nested ifs, which is why I want the opposite of that condition if (section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE). What would it be? I tried with if (section_header[i].Characteristics & ~IMAGE_SCN_MEM_WRITE) continue, but it's not the correct one.

for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i)
{
    if (functions[i] >= section_header[i].VirtualAddress && functions[i] < section_header[i].VirtualAddress + section_header[i].Misc.VirtualSize)
    {
        if (section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
        {
            ... next
        }
    }
}

Upvotes: 1

Views: 924

Answers (3)

Nate Eldredge
Nate Eldredge

Reputation: 57972

If you are certain that your mask will only have one bit set, then you can test whether that bit is cleared (i.e. not set) in value by doing

if (~value & MASK)
    // bit is clear

However, I do not recommend this. While logically correct, it is a lot less idiomatic than the other suggested options if (!(value & MASK)) or if ((value & MASK) == 0). People reading your code are much more likely to misunderstand, possibly leading them to create new bugs by "fixing" it.

Also, if MASK should have more than one bit set, the expression ~value & MASK expression will be true if if any of those bits is cleared in value, and so it is no longer the logical negation of value & MASK. For instance if MASK == 0x3 and value == 0x2, then value & MASK is true and ~value & MASK is also true. By contrast !(value & MASK) is true iff all of those bits are cleared.

Upvotes: 4

Nasser GHOSEIRI
Nasser GHOSEIRI

Reputation: 100

First you need to determine the type of the 'Characteristics' item. Is it uint32_t? This is important, as the AND operation may get confused if you try to fuse incompatible types.

Here is how I would have done it:

...
auto typed_flag = (uint32_t)IMAGE_SCN_MEM_WRITE;
if (((section_header[i].Characteristics bitand typed_flag) == typed_flag) 
{
    continue;
}
...

NOTE: 'bitand' is more C++ish than ampersand (although both do exactly the same).

Upvotes: 0

Casey
Casey

Reputation: 10936

Flipping your conditionals is a common practice to reduce "arrow code" (heavily indented code):

for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) {
    if(!(section_header[i].VirtualAddress < functions[i] && functions[i] < section_header[i].VirtualAddress + section_header[i].Misc.VirtualSize)) {
        continue;
    }
    if((section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE) == 0) {
        continue;
    }
    // From this point
    // It's now guaranteed that selected function is in range and
    // the selected section_header contains the IMAGE_SCN_MEM_WRITE bit
}

Upvotes: 4

Related Questions