I have to write a program that takes bits 3,4,5 and puts them into the place of bits 24,25,26 and then it takes bits 24,25,26 (from the original number) and puts them in the place of bits 3,4,5. The code that I wrote succesfuly transfers 3,4,5 to 24,25,26 but I can't understand why it's not working the other way around.. I also want to ask if there is an easier way to do this..
static void Main()
{
Console.Write("Please input your number: ");
int num = Convert.ToInt32(Console.ReadLine());
int mask = 0;
int bit = 0;
int p = 0;
int numP = 0;
//take bit 3,4,5 and put them in the place of 24,25,26
for (int i = 0; i < 3; i++)
{
p = 3 + i;
numP = num >> p;
bit = numP & 1;
if (bit == 1)
{
mask = 1 << 24 + i;
num = num | mask;
}
else
{
mask = ~(1 << 24 + i);
num = num & mask;
}
}
//take bit 24,25,26 and put them in the place of 3,4,5
for (int i = 0; i < 3; i++)
{
p = 24 + i;
numP = num >> p;
bit = numP & 1;
if (bit == 1)
{
mask = 1 << 3 + i;
num = num | mask;
}
else
{
mask = ~(1 << 3 + i);
num = num & mask;
}
}
Console.WriteLine("Your new number is: {0}", num);
}
To switch the bits you need to store away the original bits before you copy the new bits in.
As you want to switch three bits that are next to each other with three other bits that are next to each other, it can be done quite easily:
int lo = num & 0x00000038; // get bits 3-5
int hi = num & 0x07000000; // get bits 24-26
num &= ~0x07000038; // clear bits 3-5 and 24-26
num |= lo << 21; // put bits 3-5 in 24-26
num |= hi >> 21; // put bits 24-26 in 3-5
Edit:
Doing the same one bit at a time in a loop; instead of having two loops and copying bits, you can do it with one loop where you swap bits, which solves the problem of the first loop overwriting the bits that you need in the second loop:
int numP, bit1, bit2, mask1, mask2;
//swap bits 3,4,5 with bits 24,25,26
for (int i = 0; i < 3; i++) {
// get bit 3 (,4,5)
numP = num >> (3 + i);
bit1 = numP & 1;
// get bit 24 (,25,26)
numP = num >> (24 + i);
bit2 = numP & 1;
// shift bit 3 (,4,5) to positon 24 (,25,26)
bit1 = bit1 << (24 + i);
// shift bit 24 (,25,26) to position 3 (,4,5)
bit2 = bit2 << (3 + i);
// set bit 3 (,4,5) to zero
mask1 = 1 << (3 + i);
num = num & ~mask1;
// set bit 24 (,25,26) to zero
mask2 = 1 << (24 + i);
num = num & ~mask2;
// put bit 3 (,4,5) in bit 24 (,25,26)
num = num | bit1;
// put bit 24 (,25,26) in bit 3 (,4,5)
num = num | bi2;
}
Assuming you are numbering bits from least- to most-significant (the proper way):
3322 2222 2222 1111 1111 11
1098 7654 3210 9876 5432 1098 7654 3210
xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
Your masks are
0x00000038 (binary: 0000 0000 0000 0000 0000 0000 0011 1000) will extract bits 3-5
0x07000000 (binary: 0000 0111 0000 0000 0000 0000 0000 0000) will extract bits 24-26
The code is easy. This is one way to do it:
public uint exchange_bits( uint a )
{
uint swapped = ( a & ~( 0x07000038 ) ) // clear bits 3-5 and 24-26
| ( ( a & 0x00000038 ) << 21 ) // OR in bits 3-5, shifted left 21 bits
| ( ( a & 0x07000000 ) >> 21 ) // OR in bits 24-26, shifted right 21 bits
;
return swapped ;
}
It is always my opinion that code should be readable by a human, and only incidentally executable. If you are not running this in a tight loop, you could do the following:
private static int SwapBits(int ind)
{
BitVector32 bv = new BitVector32(ind);
BitVector32 bcopy = bv;
bcopy[1 << 24] = bv[1 << 3];
bcopy[1 << 25] = bv[1 << 4];
bcopy[1 << 26] = bv[1 << 5];
bcopy[1 << 3] = bv[1 << 24];
bcopy[1 << 4] = bv[1 << 25];
bcopy[1 << 5] = bv[1 << 26];
return bcopy.Data;
}
Produces:
old 0x02000028 00000010000000000000000000101000
new 0x05000010 00000101000000000000000000010000
If you are in a tight loop, I would do the following:
private static int SwapBitsInt(int ind)
{
// mask out the ones we swap
int outd = ind & ~0x07000038;
// set the top 3 and bottom 3. The sections are 21 bits away.
outd |= (ind & 0x00000038) << 21;
outd |= (ind & 0x07000000) >> 21;
return outd;
}
The constants 0x00000038 and 0x07000000 are the results of 1 << 3 | 1 << 4 | 1 << 5 and 1 << 24 | 1 << 25 | 1 << 26. An easy way to find them is to use the "Programmer" mode in Windows Calculator, and click the bits you want.
Related
I am a beginner at C# and would like some advice on how to solve the following problem:
My code read 3 byte from ADC true FTDI ic and calculating value. Problem is that sometimes I get values under zero (less than 0000 0000 0000 0000 0000 0000) and my calculating value jump to a big number. I need to implement two's complement but I and I don't know how.
byte[] readData1 = new byte[3];
ftStatus = myFtdiDevice.Read(readData1, numBytesAvailable, ref numBytesRead); //read data from FTDI
int vrednost1 = (readData1[2] << 16) | (readData1[1] << 8) | (readData1[0]); //convert LSB MSB
int v = ((((4.096 / 16777216) * vrednost1) / 4) * 250); //calculate
Convert the data left-justified, so that your sign-bit lands in the spot your PC processor treats as a sign bit. Then right-shift back, which will automatically perform sign-extension.
int left_justified = (readData[2] << 24) | (readData[1] << 16) | (readData[0] << 8);
int result = left_justified >> 8;
Equivalently, one can mark the byte containing a sign bit as signed, so the processor will perform sign extension:
int result = (unchecked((sbyte)readData[2]) << 16) | (readData[1] << 8) | readData[0];
The second approach with a cast only works if the sign bit is already aligned left within any one of the bytes. The left-justification approach can work for arbitrary sizes, such as 18-bit two's complement readings. In this situation the cast to sbyte wouldn't do the job.
int left_justified18 = (readData[2] << 30) | (readData[1] << 22) | (readData[0] << 14);
int result18 = left_justified >> 14;
Well, the only obscure moment here is endianness (big or little). Assuming that byte[0] stands for the least significant byte you can put
private static int FromInt24(byte[] data) {
int result = (data[2] << 16) | (data[1] << 8) | data[0];
return data[2] < 128
? result // positive number
: -((~result & 0xFFFFFF) + 1); // negative number, its abs value is 2-complement
}
Demo:
byte[][] tests = new byte[][] {
new byte[] { 255, 255, 255},
new byte[] { 44, 1, 0},
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"[{string.Join(", ", test.Select(x => $"0x{x:X2}"))}] == {FromInt24(test)}"));
Console.Write(report);
Outcome:
[0xFF, 0xFF, 0xFF] == -1
[0x2C, 0x01, 0x00] == 300
If you have big endianness (e.g. 300 == {0, 1, 44}) you have to swap bytes:
private static int FromInt24(byte[] data) {
int result = (data[0] << 16) | (data[1] << 8) | data[2];
return data[0] < 128
? result
: -((~result & 0xFFFFFF) + 1);
}
Some game that I currently reverse engineer store two values in 3 bytes.
first value size is 1 bit and second value size is 23 bits.
[0][000 0001 0001 0111 1001 0000] 0 stone, 71568 att
[1][000 0000 0010 1001 0000 0111] 1 stone, 10511 att
I found a way to read them like this:
public byte AddedStonesCount
{
get
{
byte[] att_plus_stones_count_as_bytes = new byte[4];
Buffer.BlockCopy(this.Data, 21, att_plus_stones_count_as_bytes, 0, 3);
uint att_plus_stones_count = BitConverter.ToUInt32(att_plus_stones_count_as_bytes, 0);
return (byte)(att_plus_stones_count >> 23);
}
set
{
}
}
public uint Attack
{
get
{
byte[] att_plus_stones_count_as_bytes = new byte[4];
Buffer.BlockCopy(this.Data, 21, att_plus_stones_count_as_bytes, 0, 3);
uint att_plus_stones_count = BitConverter.ToUInt32(att_plus_stones_count_as_bytes, 0);
return att_plus_stones_count << 9 >> 9;
}
set
{
}
}
But I also need a way to change them. That's where something always goes wrong for me.
I tried doing att & 0x800000 to get 1 0000 0000 0000 0000 0000 added with attack, but strangely it give me 0 instead of the value I expect.
I doing some tests here:
uint test = 0x80290F; //8399119 - here we store 1 stone added and 10511 attack power
uint test_composition = 10511 & (0x800000); //this does not give me 8399119 :/
BitArray ba = new BitArray(BitConverter.GetBytes(test));
string test_original = string.Empty;
for (int i = 0; i < ba.Length; i++)
test_original += ba.Get(i) ? 1 : 0;
uint att = test << 9 >> 9;
BitArray ba_att = new BitArray(BitConverter.GetBytes(att));
string test_att = string.Empty;
for (int i = 0; i < ba_att.Length; i++)
test_att += ba_att.Get(i) ? 1 : 0;
uint stones = test >> 23;
Help...
For example, when pet has attack = 10511 and amount of stones added = 1, then end value should be 8399119.
To set bit#23 according to stones (0 or 1) and the bits#0...22 according to attack, use the bitwise OR operator:
(stones << 23) | attack
I have a short value X:
short X=1; //Result in binary: 0000000000000001
I need to split them into an array and set the bits (say bit 6 and 10) //Result in binary: 0000001000100001
I need to convert it back to short X value.
How can I do it painlessly?
Could you please help?
1. Manual solution
Setting bit 6 and 10:
myValue |= (1 << 6)|(1 << 10);
Clearing bit 6 and 10:
myValue &= ~((1 << 6)|(1 << 10));
2. Use BitArray
var bits = new BitArray(16); // 16 bits
bits[5] = true;
bits[10] = true;
Convert back to short:
var raw = new byte[2];
bits.CopyTo(raw, 0);
var asShort = BitConverter.ToInt16(raw, 0);
If what you are referring to is a very basic encryption, then perhaps using the XOR (^) operator would be better suited for your needs.
short FlipBytes(short original, params int[] bytesToSet)
{
int key = 0;
foreach (int b in bytesToSet)
{
if (b >= 0 && b < 16)
{
key |= 1 << b;
}
}
return (short)(original ^ key);
}
This method will both set and reset the bytes that you desire. For example:
short X = 1;
short XEncrypt = FlipBytes(X, 6, 10);
short XDecrypt = FlipBytes(XEncrypt, 6, 10);
// X = 1 , Binary = 0000000000000001
// XEncrypt = 1089 , Binary = 0000010001000001
// XDecrypt = 1 , Binary = 0000000000000001
If you have a int value "intValue" and you want to set a specific bit at position "bitPosition", do something like:
intValue = intValue | (1 << bitPosition);
or shorter:
intValue |= 1 << bitPosition;
If you want to reset a bit (i.e, set it to zero), you can do this:
intValue &= ~(1 << bitPosition);
(The operator ~ reverses each bit in a value, thus ~(1 << bitPosition) will result in an int where every bit is 1 except the bit at the given bitPosition.)
Linq solution, terser, but probably, less readable than foreach loop:
using System.Linq;
...
short X = 1;
var bitsToSet = new[] { 5, 9 };
var result = X | bitsToSet.Aggregate((s, a) => s |= 1 << a);
If you insist on short add cast:
short result = (short) (X | bitsToSet.Aggregate((s, a) => s |= 1 << a));
I have two numbers (going from 0-9) and I want to combine them into 1 byte.
Number 1 would take bit 0-3 and Number 2 has bit 4-7.
Example : I have number 3 and 4.
3 = 0011 and 4 is 0100.
Result should be 0011 0100.
How can I make a byte with these binary values?
This is what I currently have :
public Byte CombinePinDigit(int DigitA, int DigitB)
{
BitArray Digit1 = new BitArray(Convert.ToByte(DigitA));
BitArray Digit2 = new BitArray(Convert.ToByte(DigitB));
BitArray Combined = new BitArray(8);
Combined[0] = Digit1[0];
Combined[1] = Digit1[1];
Combined[2] = Digit1[2];
Combined[3] = Digit1[3];
Combined[4] = Digit2[0];
Combined[5] = Digit2[1];
Combined[6] = Digit2[2];
Combined[7] = Digit2[3];
}
With this code I have ArgumentOutOfBoundsExceptions
Forget all that bitarray stuff.
Just do this:
byte result = (byte)(number1 | (number2 << 4));
And to get them back:
int number1 = result & 0xF;
int number2 = (result >> 4) & 0xF;
This works by using the << and >> bit-shift operators.
When creating the byte, we are shifting number2 left by 4 bits (which fills the lowest 4 bits of the results with 0) and then we use | to or those bits with the unshifted bits of number1.
When restoring the original numbers, we reverse the process. We shift the byte right by 4 bits which puts the original number2 back into its original position and then we use & 0xF to mask off any other bits.
This bits for number1 will already be in the right position (since we never shifted them) so we just need to mask off the other bits, again with & 0xF.
You should verify that the numbers are in the range 0..9 before doing that, or (if you don't care if they're out of range) you can constrain them to 0..15 by anding with 0xF:
byte result = (byte)((number1 & 0xF) | ((number2 & 0xF) << 4));
this should basically work:
byte Pack(int a, int b)
{
return (byte)(a << 4 | b & 0xF);
}
void Unpack(byte val, out int a, out int b)
{
a = val >> 4;
b = val & 0xF;
}
Could someone please explain what the following code does.
private int ReadInt32(byte[] _il, ref int position)
{
return (((il[position++] | (il[position++] << 8)) | (il[position++] << 0x10)) | (il[position++] << 0x18));
}
I'm not sure I understand how the bitwise operators in this method work, could some please break it down for me?
The integer is given as a byte array.
Then each byte is shifted left 0/8/16/24 places and these values are summed to get the integer value.
This is an Int32 in hexadecimal format:
0x10203040
It is represented as following byte array (little endian architecture, so bytes are in reverse order):
[0x40, 0x30, 0x20, 0x10]
In order to build the integer back from the array, each element is shifted i.e. following logic is performed:
a = 0x40 = 0x00000040
b = 0x30 << 8 = 0x00003000
c = 0x20 << 16 = 0x00200000
d = 0x10 << 24 = 0x10000000
then these values are OR'ed together:
int result = a | b | c | d;
this gives:
0x00000040 |
0x00003000 |
0x00200000 |
0x10000000 |
------------------
0x10203040
Think of it like this:
var i1 = il[position];
var i2 = il[position + 1] << 8; (<< 8 is equivalent to * 256)
var i3 = il[position + 2] << 16;
var i4 = il[position + 3] << 24;
position = position + 4;
return i1 | i2 | i3 | i4;