I have a int64 variable with a random value. I want to modify the lower 32 bits of it to 0xf0ffffff
The variable is rdx register but i want to edit edx value
ContextRecord->Rdx = 0xf0ffffff; // Not correct
The variable is rdx register but i want to edit edx value
I assume that this means that you want to keep the most significant 32-bits intact and only change the least significant 32-bits.
Assuming that the data member ContextRecord->Rdx contains the original value and you want to write back the edited value to this data member, then you could use the following code:
auto temp = ContextRecord->Rdx;
temp &= 0xffffffff00000000; //set least significant 32-bits to 00000000
temp |= 0x00000000f0ffffff; //set least significant 32-bits to f0ffffff
ContextRecord->Rdx = temp;
Of course, these lines could be combined into a single line, like this:
ContextRecord->Rdx = ContextRecord->Rdx & 0xffffffff00000000 | 0x00000000f0ffffff;
Please note that this line only works because & has a higher operator precedence than |, otherwise additional parentheses would be required.
Read the whole value, mask out the lower bits and bitwise-OR it with the 32 bit value you want there:
#include <stdint.h>
void f(int64_t *X)
{
*X = (*X & ~(uint64_t)0xffffffff) //mask out the lower 32 bits
| 0xf0ffffff; //<value to set into the lower 32 bits
}
gcc and clang on little-endian architectures optimize it to a direct mov into the lower 32 bits, i.e., the equivalent of:
#include <string.h>
//only works on little-endian architectures
void g(int64_t *X)
{
uint32_t y = 0xf0ffffff;
memcpy(X,&y,sizeof(y));
}
https://gcc.godbolt.org/z/nkMSvw
If you were doing this in straight assembly, you could just
mov edx 0xf0ffffff
as edx is an alias to the lower 32 bits of rdx. Since it seems you want to do it in C/C++, you need to adjust Rdx directly. Something like -
CONTEXT ctx;
GetThreadContext(hYourThread,&ctx); // check return value, handle errors
DWORD64 newRdx = ctx->Rdx;
newRdx &= 0xfffffffff0ffffff;
newRdx |= 0xf0ffffff;
Need to write some unit tests as I haven't tested this for all types in all architectures but a template something like below maybe what you are looking for
#include <cassert>
#include <cstdint>
#include <iostream>
#include <limits>
#include <type_traits>
template <const int bits, class /* This is where I wish concepts were completed */ T>
constexpr T modifyBits(T highPart, T lowPart)
{
// std::numeric_limits<T>::max() will fail on bits == 0 or float types
static_assert(bits != 0);
static_assert(std::is_signed<T>::value || std::is_unsigned<T>::value);
constexpr T almostallSetMask = std::numeric_limits<T>::max();
constexpr T bitmaskRaw = almostallSetMask >> (bits - (std::is_signed<T>::value ? 1 : 0));
constexpr T bitmaskHigh = bitmaskRaw << bits;
constexpr T bitmaskLow = ~bitmaskHigh;
return (highPart & bitmaskHigh) | (lowPart & bitmaskLow);
}
int main()
{
// Example usage
constexpr int64_t value = 0xFFFFFFFF00000000LL;
constexpr int64_t updated = modifyBits<32, int64_t>(value, 0xFFFFFFFFLL);
static_assert(updated == -1LL); // has to pass
return 0;
}
As you can see I can use static assert and const_expr in a generic way like this. The motto is: Write it once use everywhere. Be warned though, without unit tests this is not complete at all. Feel free to copy this if you like, you can consider it as CC0 or public domain,
A slightly more cheaty and less recommendable way to do it would be type punning:
struct splitBytes {
__int32 lower, upper;
}
void changeLower(__int64* num) {
splitBytes* pun = (splitBytes*)*num;
pun->lower = 0xf0ffffff;
}
note: type punning is pretty risky, so you really shouldn't use unless it's unavoidable. It basically lets you treat a block of memory as if it were of a different type. Really, don't use it if you can avoid it. I'm just putting it out there.
Related
The Problem
I'm currently trying to simulate some firmware in C++11. In the firmware we have a fixed data length of 32 bits, we split this 32 bits into smaller packets e.g we have a packet which as a size of 9 bits, another of 6 which gets packed into the 32 bit word.
In C++ I want to ensure the data I type in is of those lengths. I don't care if I overflow, just that only the 9 bits are operated on or passed onto another function.
Ideally I'd like some simple typedef like:
only_18_bits some_value;
My Attempt
struct sel_vals{
int_fast32_t m_val : 18;
int_fast8_t c_val : 5;
}
But this is a little annoying as I'd have to do this whenever I want to use it:
sel_vals somevals;
somevals.m_val = 5;
Seems a little verbose to me plus I have to declare the struct first.
Also for obvious reasons, I can't just do something like:
typedef sel_vals.m_val sel_vals_m_t;
typedef std::vector<sel_vals_m_t>;
I could use std::bitset<9> but whenever I want to do some maths I have to convert it to unsigned, it just gets a little messy. I want to avoid mess.
Any ideas?
I would suggest a wrapper facade, something along these lines:
#include <cstdint>
template<int nbits> class bits {
uint64_t value;
static const uint64_t mask = (~(uint64_t)0) >> (64-nbits);
public:
bits(uint64_t initValue=0) : value(initValue & mask) {}
bits &operator=(uint64_t newValue)
{
value=newValue & mask;
}
operator uint64_t() const { return value; }
};
//
bits<19> only_19_bits_of_precision;
With a little bit of work, you can define math operator overloads that directly operate on these templates.
With a little bit of more work, you could work this template to pick a smaller internal value, uint32_t, uint16_t, or uint8_t, if the nbits template parameter is small enough.
I have a hex pattern stored in a variable, how to do I know what is the size of the hex pattern
E.g. --
#define MY_PATTERN 0xFFFF
now I want to know the size of MY_PATTERN, to use somewhere in my code.
sizeof (MY_PATTERN)
this is giving me warning -- "integer conversion resulted in truncation".
How can I fix this ? What is the way I should write it ?
The pattern can increase or decrease in size so I can't hard code it.
Don't do it.
There's no such thing in C++ as a "hex pattern". What you actually use is an integer literal. See paragraph "The type of the literal". Thus, sizeof (0xffff) is equal to sizeof(int). And the bad thing is: the exact size may vary.
From the design point of view, I can't really think of a situation where such a solution is acceptable. You're not even deriving a type from a literal value, which would be a suspicious as well, but at least, a typesafe solution. Sizes of values are mostly used in operations working with memory buffers directly, like memcpy() or fwrite(). Sizes defined in such indirect ways lead to a very brittle binary interface and maintenance difficulties. What if you compile a program on both x86 and Motorola 68000 machines and want them to interoperate via a network protocol, or want to write some files on the first machine, and read them on another? sizeof(int) is 4 for the first and 2 for the second. It will break.
Instead, explicitly use the exactly sized types, like int8_t, uint32_t, etc. They're defined in the <cstdint> header.
This will solve your problem:
#define MY_PATTERN 0xFFFF
struct TypeInfo
{
template<typename T>
static size_t SizeOfType(T) { return sizeof(T); }
};
void main()
{
size_t size_of_type = TypeInfo::SizeOfType(MY_PATTERN);
}
as pointed out by Nighthawk441 you can just do:
sizeof(MY_PATTERN);
Just make sure to use a size_t wherever you are getting a warning and that should solve your problem.
You could explicitly typedef various types to hold hex numbers with restricted sizes such that:
typedef unsigned char one_byte_hex;
typedef unsigned short two_byte_hex;
typedef unsigned int four_byte_hex;
one_byte_hex pattern = 0xFF;
two_byte_hex bigger_pattern = 0xFFFF;
four_byte_hex big_pattern = 0xFFFFFFFF;
//sizeof(pattern) == 1
//sizeof(bigger_pattern) == 2
//sizeof(biggest_pattern) == 4
four_byte_hex new_pattern = static_cast<four_byte_hex>(pattern);
//sizeof(new_pattern) == 4
It would be easier to just treat all hex numbers as unsigned ints regardless of pattern used though.
Alternatively, you could put together a function which checks how many times it can shift the bits of the pattern until it's 0.
size_t sizeof_pattern(unsigned int pattern)
{
size_t bits = 0;
size_t bytes = 0;
unsigned int tmp = pattern;
while(tmp >> 1 != 0){
bits++;
tmp = tmp >> 1;
}
bytes = (bits + 1) / 8; //add 1 to bits to shift range from 0-31 to 1-32 so we can divide properly. 8 bits per byte.
if((bits + 1) % 8 != 0){
bytes++; //requires one more byte to store value since we have remaining bits.
}
return bytes;
}
#include "stdio.h"
typedef struct CustomStruct
{
short Element1[10];
}CustomStruct;
void F2(char* Y)
{
*Y=0x00;
Y++;
*Y=0x1F;
}
void F1(CustomStruct* X)
{
F2((char *)X);
printf("s = %x\n", (*X).Element1[0]);
}
int main(void)
{
CustomStruct s;
F1(&s);
return 0;
}
The above C code prints 0x1f00 when compiled and ran on my PC.
But when I flash it to an embedded target (uController) and debugging, I find that
(*X).Element1[0] = 0x001f.
1- Why the results are different on PC and on the embedded target?
2- What can I modify in this code so that it prints 0x001f in the PC case,
without changing the core of code (by adding a compiler option or something maybe).
shorts are typically two bytes and 16 bits. When you say:
short s;
((char*)&s)[0] = 0x00;
((char*)&s)[1] = 0x1f;
This sets the first of those two bytes to 0x00 and the second of those two bytes to 0x1f. The thing is that C++ doesn't specify what setting the first or second byte does to the value of the overall short, so different platforms can do different things. In particular, some platforms say that setting the first byte affects the 'most significant' bits of the short's 16 bits and setting the second byte affects the 'least significant' bits of the short's 16 bits. Other platforms say the opposite; That setting the first byte affect the least significant bits and setting the second byte affects the most significant bits. These two platform behaviors are referred to as big-endian and little-endian respectively.
The solution to getting consistent behavior independent of these differences is to not access the bytes of the short this way. Instead you should simply manipulate the value of the short using methods that the language does define, such as with bitwise and arithmetic operators.
short s;
s = (0x1f << 8) | (0x00 << 0); // set the most significant bits to 0x1f and the least significant bits to 0x00.
The problem is that, for many reasons, I can only change the body of the function F2. I can not change its prototype. Is there a way to find the sizeof Y before it have been castled or something?
You cannot determine the original type and size using only the char*. You have to know the correct type and size through some other means. If F2 is never called except with CustomStruct then you can simply cast the char* back to CustomStruct like this:
void F2(char* Y)
{
CustomStruct *X = (CustomStruct*)Y;
X->Element[0] = 0x1F00;
}
But remember, such casts are not safe in general; you should only cast a pointer back to what it was originally cast from.
The portable way is to change the definition of F2:
void F2(short * p)
{
*p = 0x1F;
}
void F1(CustomStruct* X)
{
F2(&X.Element1[0]);
printf("s = %x\n", (*X).Element1[0]);
}
When you reinterpret an object as an array of chars, you expose the implementation details of the representation, which is inherently non-portable and... implementation-dependent.
If you need to do I/O, i.e. interface with a fixed, specified, external wire format, use functions like htons and ntohs to convert and leave the platform specifics to your library.
It appears that the PC is little endian and the target is either big-endian, or has 16-bit char.
There isn't a great way to modify the C code on the PC, unless you replace your char * references with short * references, and perhaps use macros to abstract the differences between your microcontroller and your PC.
For example, you might make a macro PACK_BYTES(hi, lo) that packs two bytes into a short the same way, regardless of machine endian. Your example becomes:
#include "stdio.h"
#define PACK_BYTES(hi,lo) (((short)((hi) & 0xFF)) << 8 | (0xFF & (lo)))
typedef struct CustomStruct
{
short Element1[10];
}CustomStruct;
void F2(short* Y)
{
*Y = PACK_BYTES(0x00, 0x1F);
}
void F1(CustomStruct* X)
{
F2(&(X->Element1[0]));
printf("s = %x\n", (*X).Element1[0]);
}
int main(void)
{
CustomStruct s;
F1(&s);
return 0;
}
I want to modify individual bits of data, (for e.g. ints or chars). I want to do this by making a pointer, say ptr. by assigning it to some int or char, and then after incrementing ptr n times, I want to access the nth bit of that data.
Something like
// If i want to change all the 8 bits in a char variable
char c="A";
T *ptr=&c; //T is the data type of pointer I want..
int index=0;
for(index;index<8;index++)
{
*ptr=1; //Something like assigning 1 to the bit pointed by ptr...
}
There no such thing as a bit pointer in C++. You need to use two things, a byte pointer and an offset to the bit. That seems to be what you are getting towards in your code. Here's how you do the individual bit operations.
// set a bit
*ptr |= 1 << index;
// clear a bit
*ptr &= ~(1 << index);
// test a bit
if (*ptr & (1 << index))
...
The smallest addressable memory unit in C and C++ is 1 byte. So You cannot have a pointer to anything less than a byte.If you want to perform bitwise operations C and C++ provide the bitwise operators for these operations.
It is impossible to have address of individual bit, but you can utilize structures with bit fields. Like in this example from Wikipedia so:
struct box_props
{
unsigned int opaque : 1;
unsigned int fill_color : 3;
unsigned int : 4; // fill to 8 bits
unsigned int show_border : 1;
unsigned int border_color : 3;
unsigned int border_style : 2;
unsigned int : 2; // fill to 16 bits
};
Then by manipulating individual fields you will change sets of bits inside unsigned int. Technically this is identical to bitwise operations, but in this case compiler will generate the code (and you have lower chances of bug).
Be advised that you have to be cautious using bit fields.
C and C++ doesn't have a "bit pointer", technically speaking, C and C++ as such, deosn't know about "bits". You could build your own type, to do this, you need two things: A pointer to some type (char, int - probably unsigned) and a bit number. You'd then use the pointer and the bit number, along with the bitwise operators, to actually access the values.
There is nothing like a pointer to a bit
If you want all bits set to 1 then c = 0xff; is what you want, if you want to set a bit under some condition:
for(index;index<8;index++)
{
if (condition) c |= 1 << index;
}
As you can see there is no need to use a pointer
You can not read a single bit from the memory, CPU always read a full cache line, which could have different sizes for different CPUs.
But from the language point of view you can use bit fields
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
http://en.wikipedia.org/wiki/Bit_field
When asking a question on how to do wrapped N bit signed subtraction I got the following answer:
template<int bits>
int
sub_wrap( int v, int s )
{
struct Bits { signed int r: bits; } tmp;
tmp.r = v - s;
return tmp.r;
}
That's neat and all, but how will a compiler implement this? From this question I gather that accessing bit fields is more or less the same as doing it by hand, but what about when combined with arithmetic as in this example? Would it be as fast as a good manual bit-twiddling approach?
An answer for "gcc" in the role of "a compiler" would be great if anyone wants to get specific. I've tried reading the generated assembly, but it is currently beyond me.
As written in the other question, unsigned wrapping math can be done as:
int tmp = (a - b) & 0xFFF; /* 12 bit mask. */
Writing to a (12bit) bitfield will do exactly that, signed or unsigned. The only difference is that you might get a warning message from the compiler.
For reading though, you need to do something a bit different.
For unsigned maths, it's enough to do this:
int result = tmp; /* whatever bit count, we know tmp contains nothing else. */
or
int result = tmp & 0xFFF; /* 12bit, again, if we have other junk in tmp. */
For signed maths, the extra magic is the sign-extend:
int result = (tmp << (32-12)) >> (32-12); /* asssuming 32bit int, and 12bit value. */
All that does is replicate the top bit of the bitfield (bit 11) across the wider int.
This is exactly what the compiler does for bitfields. Whether you code them by hand or as bitfields is up to you, but just make sure you get the magic numbers right.
(I have not read the standard, but I suspect that relying on bitfields to do the right thing on overflow might not be safe?)
The compiler has knowledge about the size and exact position of r in your example. Suppose it is like
[xxxxrrrr]
Then
tmp.r = X;
could e.g. be expanded to (the b-suffix indicating binary literals, & is bitwise and, | is bitwise or)
tmp = (tmp & 11110000b) // <-- get the remainder which is not tmp.r
| (X & 00001111b); // <-- put X into tmp.r and filter away unwanted bits
Imagine your layout is
[xxrrrrxx] // 4 bits, 2 left-shifts
the expansion could be
tmp = (tmp & 11000011b) // <-- get the remainder which is not tmp.r
| ((X<<2) & 00111100b); // <-- filter 4 relevant bits, then shift left 2
How X actually looks like, whether a complex formulation or just a literal, is actually irrelevant.
If your architecture does not support such bitwise operations, there are still multiplications and divisions by power of two to simulate shifting, and probably these can also be used to filter out unwanted bits.