Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Change only lower 32 bits of an __int64 variable

Tags:

c++

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
like image 348
Shahriyar Avatar asked Sep 14 '25 16:09

Shahriyar


2 Answers

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.

like image 126
Andreas Wenzel Avatar answered Sep 16 '25 06:09

Andreas Wenzel


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

like image 30
PSkocik Avatar answered Sep 16 '25 07:09

PSkocik