How can I clear half a byte from a number - c

I know I can clear a single bit by using the bitwise operator &
number &= ~(1 << x);
But how would I be able to clear either the upper or lower half of a byte?
For example, number = 99
99 = 0110 0011 and clearing the upper half we get 0000 0011

Just AND the byte with the mask you need: to clear the upper four bits, use n & 0x0F, to clear the lower four bits, use n & 0xF0.

You could say number &= 15;. 15 is represented as 0000 1111 in binary which means the leading/upper 4 bits would be cleared away.
Likewise, to clear the trailing/lower 4 bits, you could then say number &= 240 because 240 is represented as 1111 0000 in binary.
For example, let's say number = 170 and we want to clear away the leading/upper four bits. 170 is represented as 1010 1010 in binary. So, if we do number &= 15, we get:
1010 1010
& 0000 1111
-------------
0000 1010
(0000 1010 is 10 in binary)
Supposing, again, number = 170 and we want to clear the trailing/lower four bits, we can say: number &= 240. When we do this, we get:
1010 1010
& 1111 0000
-------------
1010 0000
(1010 0000 is 160 in binary)

You want to do an and with the bit-pattern showing what you want to keep.
So for your case:
number &= 0xf;
As 0xf is 0000 1111.
This is sometimes referred to as a "mask".

Clear lower half:
number &= ~0xF;
Higher half:
number &= ~0xF0;
The above works work int types. For larger types, you need to extend mask accordingly, for example:
number &= ~UINT64_C(0xF0);

Related

C rotate bitfield (explanation needed)

I want to rotate a byte 1 bit to the left. I was looking at several examples from this site and came across this code. Though it works, I'd appreciate any step by step into how does it works.
unsigned int _rotl(const unsigned int value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
First of all, what does the first part does? And for the last part wouldn't shifting by that much you'd pretty much be erasing some of the bits?
For example:
Say
value= 0x50 //01010000
shift = 4
I'll have
for
value << shift
01010000 << 4 => 00000000
And for
value >> (sizeof(value)*8 - shift)
01010000>> (4*8 - 4) => 00000000
So doing the OR operation for both would give me 0. My understanding is wrong obviously, but I'd appreciate anyone 'dumbing' it down for a begginer like me. Thanks.
Let's take it step by step:
unsigned int _rotl(const unsigned int value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
First line:
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
This statement is an optimization and a check rolled into one line. It returns TRUE if one of two conditions is met:
Shift is zero (i.e. don't rotate any bits)
The number of rotations specified by shift would have no effect
That statement returns FALSE otherwise, but also calculates the minimum number of rotations necessary to achieve the desired result, and stores that value in shift. In other words, it calculates shift = shift % size_of_integer_data_type.
For example, if you have a 32-bit integer, then rotating it by 32 bits does nothing. If you rotate it by 64, 96, or any other multiple of 32, that also accomplishes nothing. If the effect of our rotation does nothing then we save ourselves a lot of time and just quit early.
However, we might also specify a lot more work than is necessary. If you have a 32-bit integer, then rotating it by one bit has the same effect as rotating it by 33 bits, or by 65 bits, or 97 bits, etc. This code recognizes this fact, so if you specify shift as 97, it reassigns shift=1 and cuts out the extraneous rotations.
The statement sizeof(value)*8 - 1 returns one less than the number of bits in the representation of value. For example, if sizeof(value) evaluates to 4 (which it will on a system with 32-bit integers), then 4*8 - 1 = 31.
The &= operator is a bitwise-AND with assignment. This means we're doing a bitwise-AND between shift and sizeof(value)*8 - 1 and assigning that result to shift. As before, the right hand side of that expression is equal to the number of bits in value minus one. Thus, this has the effect of masking out all bits of shift that are greater than the size of the representation of value, which in turn has the effect of computing shift = shift % size_of_integer_data_type.
To be concrete, reconsider the 32-bit case. As before, sizeof(value)*8-1 evaluates to 31. Bitwise, this value is 0000 0000 0000 0000 0000 0000 0001 1111. That value is bitwise-ANDed with shift. Any bits in shift's 6th to 32nd positions are set to zero, while the bits in the 1st to 5th positions are unchanged. If you were to specify 97 rotations the result would be one.
0000 0000 0000 0000 0000 0000 0110 0001 (97)
& 0000 0000 0000 0000 0000 0000 0001 1111 (31)
=========================================
0000 0000 0000 0000 0000 0000 0000 0001 (1)
The last thing to do here is to recall that, in C, the return value of an assignment statement is the value that was assigned. Thus, if the new value of shift is zero, then we return immediately, otherwise we continue.
Second line:
return (value << shift) | (value >> (sizeof(value)*8 - shift));
Since C doesn't have a rotation operator (it only has left and right shifts) we have to compute the low-order bits and the high-order bits separately, and then combine them with a bitwise-OR. This line is a simple matter of calculating each side separately.
The statement value << shift calculates the high order bits. It shifts the bit pattern to the left by shift places. The other statement calculates the low order bits by shifting the bit pattern to the right by size_of_integer_type - shift bits. This is easy to see in an example.
Suppose that value has the decimal value 65535 and that shift has the value 26. Then the starting value is:
0000 0000 0000 0000 1111 1111 1111 1111 (65535)
The left shift gives us:
1111 1100 0000 0000 0000 0000 0000 0000 (65535 << 26)
The right shift gives us:
0000 0000 0000 0000 0000 0011 1111 1111 (65535 >> 6)
Then the bitwise-OR combines these results:
1111 1100 0000 0000 0000 0000 0000 0000 (65535 << 26)
| 0000 0000 0000 0000 0000 0011 1111 1111 (65535 >> 6)
=========================================
1111 1100 0000 0000 0000 0011 1111 1111 (65535 rot 26)
You could re-write this code and achieve the same correct result:
unsigned int _rotl(const unsigned int value, int shift)
{
//Assume 8 bits in a byte
unsigned bits_in_integer_type = sizeof(value)*8;
shift = shift % bits_in_integer_type;
if( shift == 0 ) return value; //rotation does nothing
unsigned high_bits = value << shift;
unsigned low_bits = value >> (bits_in_integer_type - shift);
return high_bits | low_bits;
}
unsigned int _rotl(const unsigned int value, int shift)
{
// If all bits in value are zero, do nothing and return
int bitmaskOfAllOnes = sizeof(value)*8 - 1;
if ((shift &= bitmaskOfAllOnes) == 0) //What does this do?
return value;
// Shift value to the left
(value << shift)
// shifting right to handle the wrap around
| (value >> (sizeof(value)*8 - shift));
}
e.g. using 16-bit ints
value = 0x1001
shift = 4
sizeof(value) => 2
//sizeof(value)*8 - 1 => 0xffff
sizeof(value)*8 - 1 => 15 Decimal
shift &= bitmaskOfAllOnes => 0x1001 (i.e. not zero)
value << shift => 0x0010
sizeof(value)*8 - shift => 12
value >> (sizeof(value)*8 - shift) => 0x001
0x0010 | 0x001 => 0x0011

Logic of a bit masking XOR code

I have a code that changes two sets of hex numbers and then stores them into a new unsigned char. The code looks like the following:
unsigned char OldSw = 0x1D;
unsigned char NewSw = 0xF0;
unsgined char ChangedSw;
ChangedSw = (OldSw ^ ~NewSw) & ~OldSw;
So what I know is:
0x1D = 0001 1101
0xF0 = 1111 0000
Im confused on what the changedSw line is doing. I know it will give the output 0x02 but I can not figure out how its doing it.
ChangedSw = (OldSw ^ ~NewSw) & ~OldSw;
It means "zero one part of OldSw and inverse other part". NewSw indicates what bits of OldSw to zero and what bits to inverse. Namely, 1's in NewSw indicate bits to be zeroed, 0's indicate bits to be inverted.
This operation implemented in two steps.
Step 1. Invert bits.
(OldSw ^ ~NewSw):
0001 1101
^ 0000 1111
---------
0001 0010
See, we inverted bits which were 0's in original NewSw.
Step 2. Zero bits which were not inverted in previous step.
& ~OldSw:
0001 0010
& 1110 0010
---------
0000 0010
See, it doesn't change inverted bits, but zero all the rest.
the first part would be 1F ie. 0001 1111.So when ended with ~oldsw(1110 0010)
the operation will be something like this:
0001 1111
1110 0010
----------
0000 0010
So the output will be 2. The tilde operator is 1's complement.

Flags in C/ set-clear-toggle

I am confused as to what the following code does, I understand Line 1 sets a flag, line 2 clears a flag and line 3 toggles a flag;
#include <stdio.h>
#define SCC_150_A 0x01
#define SCC_150_B 0x02
#define SCC_150_C 0x04
unsigned int flags = 0;
main () {
flags |= SCC_150_A; // Line 1
flags &= ~SCC_150_B; // Line 2
flags ^= SCC_150_C; // Line 3
printf("Result: %d\n",flags); // Line 4
}
What I don't understand is what the output of Line 4 would be? What is the effect of setting/clearing/toggling the flags on 0x01 0x02 and 0x04?
The macros define constants that each require a single bit to be represented:
macro hex binary
======================
SCC_150_A 0x01 001
SCC_150_B 0x02 010
SCC_150_C 0x04 100
Initially flags is 0.
Then it has:
Bit 0 set by the bitwise OR.
Bit 1 cleared by the bitwise AND with the inverse of SCC_150_B.
Bit 2 toggled (turning it from 0 to 1).
The final result is thus 1012, or 5 in decimal.
First of all, I'm going to use binary numbers, cause it's easier to explain with them. In the end it's the same with hexadecimal numbers. Also note that I shortened the variable to unsigned char to have a shorter value to write down (8 bits vs. 32 bits). The end result is similar, just without leading digits.
Let's start with the values:
0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100
So after replacing the constant/macro, the first line would essentially be this:
flags |= 0000 0001
This performs a bitwise or operation, a bit in the result is 1, if any of the input values is 1 at that position. Due to the initial value of flags being 0, this will work just like an assignment or addition (which it won't in general, keep that in mind).
flags: 0000 0000
op: 0000 0001
----------------
or: 0000 0001
The result is flags being set to 0000 0001.
flags &= ~0000 0010
Here we've got two operations, first there's ~, the bitwise complement operator. What this essentially does is flipping all bits of the value. Therefore 0000 0010 becomes 1111 1101 (0xfd in hex). Then you're using the bitwise and operator, where a result bit is only set to 1 if both input values are 1 at the specific position as well. As you can see, this will essentially cause the second bit from the right to be set to 0 without touching any other bit.
flags: 0000 0001
op: 1111 1101
----------------
and: 0000 0001
Due to this, the result of this operation is 0000 0001 (0x01 in hex).
flags ^= 0000 0100
The last operation is the bitwise exclusive or (xor), which will set a bit to 1 only if the input bits don't match (i.e. they're different). This leads to the simple behavior of toggling the bits set in the operands.
flags: 0000 0001
op: 0000 0100
----------------
xor: 0000 0101
In this case the result will be 0000 0101 (0x05 in hex).
For clarification on the last operation, because I think xor might be the hardest to understand here, let's toggle it back:
flags: 0000 0101
op: 0000 0100
----------------
xor: 0000 0001
As you can see, the third bit from the right is equal in both inputs, so the result will be 0 rather than 1.

Sign-extend a number in C

I am having trouble trying to sign-extend a number by extracting part of a bit-string. This has trouble when it is a negative number, it wraps the number around to the positive side.
Here is my code:
// printf("add1 \n");
unsigned short r1 = (instruction>>6)&7;
signed short amount = (instruction& 31); //right here! i am trying to get the last 5 bits and store it in a register but i can't figure out how to make it negative if it is negative
// printf("\namount is %d \n", amount);
unsigned short dest = (instruction>>9)&7;
state->regs[dest] = state->regs[r1]+amount;
setCC(state,state->regs[r1]+amount);
For bit patterns, it's often easier to use hex constants instead of decimal.
signed short amount = (instruction & 0x1F);
Then to sign-extend the number, check the sign-bit (assuming the sign-bit here is the left-most of the 5 extracted bits). If it's set, do a binary inversion and add 1. Take the 2's-complement of the 5-bit value (invert and add one), then take the 2's-complement of the full-width result (invert and add 1).
if (amount & 0x10)
amount = ~(amount^0x1F + 1) + 1;
Eg.
5-bit "bitfield"
X XXXX
0000 0000 0001 1111
0000 0000 0000 0000 invert x ^ 0x1F (= 1 1111)
0000 0000 0000 0001 add 1
1111 1111 1111 1110 invert ~
1111 1111 1111 1111 add 1
0000 0000 0001 0000
0000 0000 0000 1111 invert x ^ 0x1F (= 1 1111)
0000 0000 0001 0000 add 1
1111 1111 1110 1111 invert ~
1111 1111 1111 0000 add 1
Ooops. Even simpler:
-(x^0x1F + 1) Assuming the machine operates with 2's-complement
0000 0000 0001 0110
0000 0000 0000 1001 invert
0000 0000 0000 1010 add 1 (yielding the full-width absolute value)
1111 1111 1111 0110 negate
use bitfields:
union {
int a;
struct {
int a:5;
int b:3;
unsigned int c:20;
} b;
} u = 0xdeadbeef;
int b = u.b.b; // should sign extend the 3-bit bitfield starting from bit 5
Here is how you can sign extend a 5-bit two's complement value portably without tests:
int amount = (instruction & 31) - ((instruction & 16) << 1);
More generally, it the field width is n, non zero and less than the number of bits in an int, you can write:
int amount = (instruction & ~(~1U << (n - 1) << 1)) -
((instruction & (1U << (n - 1)) << 1);
From Hacker's Delight 2-6. Assuming 5 bits of data that must be sign extended (sign bit has value 16).
Best case: If the upper bits are all zeros:
(i ^ 16) - 16
Next best case (as with OP's instruction): If the upper bits contain data that must be discarded:
(i & 15) - (i & 16)
You can check the sign-bit and fix-up the result accordingly:
int width_of_field = 5;
signed short amount = (instruction& 31);
if (amount & (1 << width_of_field >> 1)) // look at the sign bit
{
amount -= 1 << width_of_field; // fix the result
}
Alternatively, use a left-shift followed by a right shift:
width_of_field = 5;
signed short amount = (instruction& 31);
// It is possible to omit the "& 31", because of the left shift below
amount <<= 16 - width_of_field;
amount >>= 16 - width_of_field;
Note: must use two statements to avoid effects of promotion to int (which presumably has 32 bits).

How to change a 32bit registers specific bits without changing other bits?

I want to manipulate some bits of a register directly using its physical address. However I couldn't find a way to make this. I saw some posts about setting bit masks but I find them too confusing.
My registers physical address is: 0x4A10005C
I want to manipulate its bit which was between 18-16 bits. I want to set 0x3 inside those bits.
I will be really glad if you guys can provide an answer or a way to do it. Thanks.
You can just define a pointer to the register and then use normal C bitwise operations to manipulate the individual bits:
volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;
// set up a pointer to the register
uint32_t val = *my_register; // read register
val &= ~(0x7 << 16); // clear bits 16..18
val |= (0x3 << 16); // set bits 16..18 to 0x03 (i.e. set bits 16 and 17)
*my_register = val; // write register
(The above assumes that you are talking about three bits within the register, bits 16, 17 and 18, and that you want to set bit 18 to zero and bits 16 and 17 to 1.)
bit masks are pretty easy to understand so let’s run through that first:
Let say your 32bit register contains some value right now I'll arbitrarily pick 0xF48C621916
I assume you know how to convert hex to binary, if not... let's just say use a calculator or google (rather than go into the nitty gritty of that too). So our hex value can be represented in binary as:
+-- bit 31 +-- bit 0
| |
v v
1111 0100 1000 1100 0110 0010 0001 1001
^ ^
| |
+-+-- bits you want to set, 16-18
Boolean logic tells us that:
1) anything OR'd (|) with 1 gives you a value of 1. Or "sets" the bit.
2) anything AND'd (&) with 0 gives you a value of 0. Or "clears" the bit.
So if we wanted to clear bits 16-18 you can AND it with a mask like:
base number: 1111 0100 1000 1100 0110 0010 0001 10012 == 0xF48C621916
mask number: 1111 1111 1111 1000 1111 1111 1111 11112 == 0xFFF8FFF16
1111 0100 1000 1100 0110 0010 0001 1001
& 1111 1111 1111 1000 1111 1111 1111 1111
------------------------------------------
1111 0100 1000 1000 0110 0010 0001 1001
Now you can OR it with whatever you want to set there:
new mask number: 0000 0000 0000 0011 0000 0000 0000 00002 == 0x0003000016
1111 0100 1000 1000 0110 0010 0001 1001
| 0000 0000 0000 0011 0000 0000 0000 0000
-----------------------------------------
1111 0100 1000 1011 0110 0010 0001 1001
So in the code:
#define CLEAR_MASK 0x70000 //70000 is shorter to write, so just do this and flip it
#define SET_3_MASK 0x30000
volatile uint32_t * const reg = (uint32_t *) 0x4A10005C;//set a pointer to the register
*reg &= ~CLEAR_MASK; //~ filps the bits
*reg |= SET_3_MASK;
You can do tricks with shifting bits and so forth, but this is the basics of bit masks and how they work. Hope it helps.
structure r32 {
unsigned int bit0 :1;
unsigned int bit1 :1;
unsigned int bit2 :1;
unsigned int bit3 :1;
unsigned int bit4 :1;
unsigned int bit5 :1;
.
.
.
unsigned int bit31 :1;
}
in your main
structure r32 *p;
volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;
p = (structure r32 *) my_register;
and then to access to bit 5 for example
p->bit4 = 0;

Resources