Need help to find a bit wise operation to fit my case study - bit-manipulation

I want to do bit operation between operand A and operand B so that result has the following bits.
Note: 1 = set , 0 = clear so
A = 1010
B = 0011
Result= 0011
That is, I want to inverse A bit if A and B are different, keep A bit if A and B are the same.
Some more examples:
Original=Set |Clear|Set|Clear
Latest =Clear|Clear|Set|Set
Result =Clear|Clear|Set|Set
A=0001
B=1000
Result=1000

You are looking to retain B in all cases. As your truth table shows. You go through all possibilities, and for all of them you get B back....

Related

What does 0b1 mean in C++?

I came across a part of code that I cannot understand.
for (unsigned int i = (x & 0b1); i < x; i+= 2)
{
// body
}
Here, x is from 0 to 5.
What is meant by 0b1? and what would be the answers for eg: (0 & 0b1), (4 & 0b1) etc?
0b... is a binary number, just like 0x... is hex and 0... is octal.
Thus 0b1 is same as 1.
1b0 is illegal, the first digit in those must always be 0.
As previous answers said, it is the binary representation of the integer number 1, but they don't seem to have fully answered your question. This has a lot of layers so I'll briefly explain each.
In this context, the ampersand is working as a bitwise AND operator. i & 0b1 is (sometimes) a faster way of checking if an integer is even as opposed to i % 2 == 0.
Say you have int x = 5 and you'd like to check if it's even using bitwise AND.
In binary, 5 would be represented as 0101. That final 1 actually represents the number 1, and in binary integers it's only present in odd numbers. Let's apply the bitwise AND operator to 5 and 1;
0101
0001
&----
0001
The operator is checking each column, and if both rows are 1, that column of the result will be 1 – otherwise, it will be 0. So, the result (converted back to base10) is 1. Now let's try with an even number. 4 = 0100.
0100
0001
&----
0000
The result is now equal to 0. These rules apply to every single integer no matter its size.
The higher-level layer here is that in C, there is no boolean datatype, so booleans are represented as integers of either 0 (false) or any other value (true). This allows for some tricky shorthand, so the conditional if(x & 0b1) will only run if x is odd, because odd & 0b1 will always equal 1 (true), but even & 0b1 will always equal 0 (false).

do bitwise and operation with a given value which results in a desired output [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I want to determine the value of X in the below mentioned operations:
X & 0x08 = 8
How to find out x in this scenario?
The problem is that there are many numbers that combined with given number would give you the same result. Bitwise operations are not really reversible like arithmetic operations.
You can however find a set of possible numbers X that would produce the correct result. The algorithm for that would be quite simple (and language agnostic).
Let's say we want X & b == c, where b is 12 and c is 8. You need to get binary representations of both the known number and the result
b == 12 == 00001100
c == 8 == 00001000
The rules that X must meet are the following:
For every bit equal to 1 in c, corresponding bits in b and X must be equal to 1
For bit equal to 0 in c, if corresponding bit in b is 1 then corresponding bit in X must be 0.
For bit equal to 0 in c, if corresponding bit in b is 0 then value of corresponding bit in X is unknown.
By these rules, we can determine that in our example
b == 12 == 00001100
c == 8 == 00001000
X == ????10??
Under every ? you can substitute either 1 or 0 and you will get a correct result. For example, both 00001000 (8) and 11111011 (251) will be a valid solution.
If you're asking this, then there can be several things you don't understand.
X & 0x08 = 8
Let's start with the easiest part: 0x08. This is just the hexadecimal representation, which is how computer programmers think when they want to know what the individual bytes hold. (If you don't know what a byte is, do a Google for computer memory byte. This is a VERY important concept.)
In this case, 0x08 is just a normal 8. In binary, that means 0000 1000. Exactly one bit is set.
Now let's do the & sign. In this case, it stands for bitwise-AND. (If you don't know what a bit is, continue reading about bits and bytes. A bit is a single binary digit in a byte. A 0 or 1.)
There are a few basic bit operations.
& -- AND -- the corresponding bit in both numbers is set
| -- OR -- if either is set
^ -- XOR -- exclusive or -- one or the other is set
So if we have two numbers, A and B as follows:
A 0101 0101
B 0000 1111
Then:
A & B == 0000 0101
A | B == 0101 1111
A ^ B == 0101 1010
So... in the case of X & 0x08, that 0x08 == 0000 1000. You should be able to figure it out from here.

how does CF(Carry flag) get set according to the computation t = a-b where a and b are unsigned integers

I'm new to x64-64, just a question on how does CF get set? I was reading a textbook which says:
CF: Carry flag is used when most recent operation generated a carry out of the most significant bit. Used to detect overflow for unsigned operations.
I have two questions:
Q1-suppose we used one of the add instructions to perform the equivalent of the C assignment t = a+b, where variables a, b, and t are integers (only 3 bits for simplicity), so for 011(a) + 101(b) = 1000 = 000, since we have a carry out bit 1 in the fourth digit, so CF flag will be set to 1, is my understanding correct?
Q2-if my understanding in Q1 is true, and suppose we used one of the sub instructions to perform the equivalent of the C assignment t = a-b, where a, b, and t are unsigned integers, since a, b are unsigned, we can't actually do a+(-b), and I don't get how we can make 011(a) - 101(b) carry out of the most significant bit?
The carry flag is often called "borrow" when performing a subtraction. After a subtraction, it set if a 1 had to be borrowed from the next bit (or would have been borrowed if you used the grade-school subtraction method). The borrow flag is like a -1 in that bit position:
011 -1 211
- 101 -> - 101
----- -----
B 110
You can get the same result by adding a zero to the arguments, and then the carry or borrow will be the high bit of the result:
0011 - 0101 = 0011 + (-0101) = 0011 + 1011 = 1110

How to choose the correct left shift in bit wise operations?

I am learning bare metal programming in c++ and it often involves setting a portion of a 32 bit hardware register address to some combination.
For example for an IO pin, I can set the 15th to 17th bit in a 32 bit address to 001 to mark the pin as an output pin.
I have seen code that does this and I half understand it based on an explanation of another SO question.
# here ra is a physical address
# the 15th to 17th bits are being
# cleared by AND-ing it with a value that is one everywhere
# except in the 15th to 17th bits
ra&=~(7<<12);
Another example is:
# this clears the 21st to 23rd bits of another address
ra&=~(7<<21);
How do I choose the 7 and how do I choose the number of bits to shift left?
I tried this out in python to see if I can figure it out
bin((7<<21)).lstrip('-0b').zfill(32)
'00000000111000000000000000000000'
# this has 8, 9 and 10 as the bits which is wrong
The 7 (base 10) is chosen as its binary representation is 111 (7 in base 2).
As for why it's bits 8, 9 and 10 set it's because you're reading from the wrong direction. Binary, just as normal base 10, counts right to left.
(I'd left this as a comment but reputation isn't high enough.)
If you want to isolate and change some bits in a register but not all you need to understand the bitwise operations like and and or and xor and not operate on a single bit column, bit 3 of each operand is used to determine bit 3 of the result, no other bits are involved. So I have some bits in binary represented by letters since they can each either be a 1 or zero
jklmnopq
The and operation truth table you can look up, anything anded with zero is a zero anything anded with one is itself
jklmnopq
& 01110001
============
0klm000q
anything orred with one is a one anything orred with zero is itself.
jklmnopq
| 01110001
============
j111nop1
so if you want to isolate and change two bits in this variable/register say bits 5 and 6 and change them to be a 0b10 (a 2 in decimal), the common method is to and them with zero then or them with the desired value
76543210
jklmnopq
& 10011111
============
j00mnopq
jklmnopq
| 01000000
============
j10mnopq
you could have orred bit 6 with a 1 and anded bit 5 with a zero, but that is specific to the value you wanted to change them to, generically we think I want to change those bits to a 2, so to use that value 2 you want to zero the bits then force the 2 onto those bits, and them to make them zero then orr the 2 onto the bits. generic.
In c
x = read_register(blah);
x = (x&(~(3<<5)))|(2<<5);
write_register(blah,x);
lets dig into this (3 << 5)
00000011
00000110 1
00001100 2
00011000 3
00110000 4
01100000 5
76543210
that puts two ones on top of the bits we are interested in but anding with that value isolates the bits and messes up the others so to zero those and not mess with the other bits in the register we need to invert those bits
using x = ~x inverts those bits a logical not operation.
01100000
10011111
Now we have the mask we want to and with our register as shown way above, zeroing the bits in question while leaving the others alone j00mnopq
Now we need to prep the bits to or (2<<5)
00000010
00000100 1
00001000 2
00010000 3
00100000 4
01000000 5
Giving the bit pattern we want to orr in giving j10mnopq which we write back to the register. Again the j, m, n, ... bits are bits they are either a one or a zero and we dont want to change them so we do this extra masking and shifting work. You may/will sometimes see examples that simply write_register(blah,2<<5); either because they know the state of the other bits, know they are not using those other bits and zero is okay/desired or dont know what they are doing.
x read_register(blah); //bits are jklmnopq
x = (x&(~(3<<5)))|(2<<5);
z = 3
z = z << 5
z = ~z
x = x & z
z = 2
z = z << 5
x = x | z
z = 3
z = 00000011
z = z << 5
z = 01100000
z = ~z
z = 10011111
x = x & z
x = j00mnopq
z = 2
z = 00000010
z = z << 5
z = 01000000
x = x | z
x = j10mnopq
if you have a 3 bit field then the binary is 0b111 which in decimal is the number 7 or hex 0x7. a 4 bit field 0b1111 which is decimal 15 or hex 0xF, as you get past 7 it is easier to use hex IMO. 6 bit field 0x3F, 7 bit field 0x7F and so on.
You can take this further in a way to try to be more generic. If there is a register that controls some function for gpio pins 0 through say 15. starting with bit 0. If you wanted to change the properties for gpio pin 5 then that would be bits 10 and 11, 5*2 = 10 there are two pins so 10 and the next one 11. But generically you could:
x = (x&(~(0x3<<(pin*2)))) | (value<<(pin*2));
since 2 is a power of 2
x = (x&(~(0x3<<(pin<<1)))) | (value<<(pin<<1));
an optimization the compiler might do for if pin cannot be reduced to a specific value at compile time.
but if it were 3 bits per field and the fields start aligned with bit zero
x = (x&(~(0x7<<(pin*3)))) | (value<<(pin*3));
which the compiler might do a multiply by 3 but maybe instead just
pinshift = (pinshift<<1)|pinshift;
to get the multiply by three. depends on the compiler and instruction set.
overall this is called a read modify write as you read something, modify some of it, then write back (if you were modifying all of it you wouldnt need to bother with a read and a modify you would write the whole new value). And folks will say masking and shifting to generically cover isolating bits in a variable either for modification purposes or if you wanted to read/see what those two bits above were you would
x = read_register(blah);
x = x >> 5;
x = x & 0x3;
or mask first then shift
x = x & (0x3<<5);
x = x >> 5;
six of one half a dozen of another, both are equal in general, some instruction sets one might be more efficient than another (or might be equal and then shift, or shift then and). One might make more sense visually to some folks rather than the other.
Although technically this is an endian thing as some processors bit 0 is the most significant bit. In C AFAIK bit 0 is the least significant bit. If/when a manual shows the bits laid out left to right you want your right and left shifts to match that, so as above I showed 76543210 to indicate the documented bits and associated that with jklmnopq and that was the left to right information that mattered to continue the conversation about modifying bits 5 and 6. some documents will use verilog or vhdl style notation 6:5 (meaning bits 6 to 5 inclusive, makes more sense with say 4:2 meaning bits 4,3,2) or [6 downto 5], more likely to just see a visual picture with boxes or lines to show you what bits are what field.
How do I choose the 7
You want to clear three adjacent bits. Three adjacent bits at the bottom of a word is 1+2+4=7.
and how do I choose the number of bits to shift left
You want to clear bits 21-23, not bits 1-3, so you shift left another 20.
Both your examples are wrong. To clear 15-17 you need to shift left 14, and to clear 21-23 you need to shift left 20.
this has 8, 9,and 10 ...
No it doesn't. You're counting from the wrong end.

is VAR |= 1 << 2; reverisble?

First I am not sure what is going on in this bitwise operation.
I get code written and supply to other parties as code snippets.
Now if VAR is unsigned 8bit integer (unsigned char) and r is either 0 or 1 or 2 or 4.
Can following be reversed if the value of r is known and resulting value is there.
VAR |= 1 << r; //that is 200 where VAR was 192 and r was 3
For example initial value of VAR is 192 and value of r is 3 *result is 200*.
Now if I have this 200, and I know the value of r that was 3, can I reverse it back to 192 ?
I hope it is most easy one, but I don't know these bitwise operations, so forgive me.
Thanks
The answer is no. This is because the | (OR) operator is not a one-to-one function.
In other words, there are multiple values of VAR that can produce the same result.
For example:
r = 3;
var0 = 8;
var1 = 0;
var0 |= 1 << r; // produces 8
var1 |= 1 << r; // produces 8
If you tried to invert it, you wouldn't be able to tell whether the original value is 0 or 8.
A similar situation applies to the & AND operator.
From an information-theory perspective:
The operators | and & incur a loss of information and do not preserve the entropy of the data.
On the other hand, operators such as ^ (XOR), +, and - are one-to-one and thus preserve entropy and are invertible.
No, OR is not reversable. I believe only XOR is.
For example, if variable a contains 1001 1100 or 1001 1000, and you set the third bit (from the right) to 1 regardless of what the initial value is, then both 1001 1100 and 1001 1000 as source operands would result in the same value (1001 1100).
Firstly, 1<<2 is just another way of writing "4" or 100 in binary.
The |= operator is another way of writing x = x | y;
The end result is setting bit 2 in x. If bit 2 in x was zero then reversing it would be to clear bit 2. If bit 2 was 1, then it's a no-op.
The problem with your question is that you don't know ahead of time what the initial state of bit 2 was.
If your goal was to clear bit 2 you can do this:
x &= ~(1<<2);
Given an expression result |= 1 << shiftAmount, corresponding to VAR and r in your original example, you can use the following to do the exact opposite:
result &= ~(1 << shiftAmount)
Note that this is not a pure inverse, because bitwise-or is not a one-to-one function. Bitwise-or sets one or more bits to 1, whether or not they were already 0 or 1. The expression I have shown above will always set the associated bits to 0, so if the bit was 1 originally it will not go back to its original state.
No, you can't reverse an OR operation.
In your example, with r=3, both the starting values VAR=192 and VAR=200 will result in 200.
Since there are two input values that will give the same result, you won't know which one to go back to.