Getting the value at memory address X - c++

I have a question: how can I see what is the value of the number at memory address X in c++.
I want to make something like the:
mov bx, 1024d
mov ax, [bx]
from assembly, where ax will be my result.
Thanks for the support.
P.S. I just started working with pointers and memory addresses

In C++, the value at that address is *reinterpret_cast<uint16_t*>(1024).

in c/c++ address is stored as pointer, so BX in your code in c++ will be
unsigned short* _mybx = (unsigned short*)1024U; // note casting to unsigned short*
to get value which is stored on address you need to use:
unsigned short _myax = *_mybx; // note asterix here
instead of c kind of cast, you can use reinterpret_cast
unsigned short* _bx = reinterpret_cast<unsigned short*>(1024);
which is more c++ way

Related

C/C++ What does casting do in the low level?

Somebody told me that type-casting C conversions does only change how the system interprets the information (for example, casting the char 'A' into int does return 65 when using cout to print it since in
memory it stays as 01000001).
However, I noticed that, when casting floating point numbers into same width integers, the value is conserved and not changed, as it would be if only the interpretation was changed.
For example, let X be a double precision floating point number:
double X = 3.14159;
As far as I now, when inspecting &X we will find (converted by decimal to binary converter):
01000000 00001001 00100001 11111001 11110000 00011011 10000110 01101110
But, as some of you would already know, when doing:
long long Y = (long long)X;
Y will be 3, the truncated version of X, instead of 4614256650576692846, the value it would get when looking at the binary values at &X if looking for a long long.
So, I think it is clear that they were wrong but, then, how does casting work in low level? Is there any detection of whether the value would be changed or not? How would you code it to get Y = 4614256650576692846 instead of Y = 3?
Casting will try to preserve the values as precise as possible.
You can use memcpy() to copy bit patterns.
#include <iostream>
#include <cstring>
int main() {
double X = 3.14159;
long long Y;
memcpy(&Y, &X, sizeof(Y));
std::cout << Y << '\n';
return 0;
}
Casting lets the compiler decide how to change the data in order for it to be as useful as possible yet respecting the requested datatype.
The int to char conversion just changes the interpretation from, let us say, 65 to 'A'.
However, when we have a value we may want to conserve, the compiler will use special instructions for its conversion.
For example, when casting from double to long long, the processor will use the CVTTSD2SI instruction, which loads and truncates a FP register's value into a general purpose one:
double a = 3.14159;
long long b = (long long)a;
will have a disassembly of (I got rid of the stack pointers for ease of understanding):
movsd xmm0, QWORD PTR [a]
cvttsd2si rax, xmm0
mov QWORD PTR [b], rax
So, the ways to use the original value would be as mentioned in the selected answer: dereferencing the pointer to the double and place it into the long long variable or, as other stated, using memcpy().
If you want to get Y = 4614256650576692846, you can use:
double X = 3.14159;
long long Y = *( (long long*)(&X) );
This will cast a double pointer to a long long pointer, and then the compiler thinks that (long long*)(&X) is somewhere a long long stores.
But I don't advise you to do so because the result is based on how double is stored on your machine, and the result is not guaranteed to be 4614256650576692846.

Obtaining an int from a void pointer which points to a short

I have a return value from a library which is a void pointer. I know that it points to a short int; I try to obtain the int value in the following way (replacing the function call with a simple assignment to a void *):
short n = 1;
void* s = &n;
int k = *(int*)s;
I try to cast a void pointer that points to an address in which there is a short and I try to cast the pointer to point to an int and when I do so the output becomes a rubbish value. While I understand why it's behaving like that I don't know if there's a solution to this.
If the problem you are dealing with truly deals with short and int, you can simply avoid the pointer and use:
short n = 1;
int k = n;
If the object types you are dealing with are different, then the solution will depend on what those types are.
Update, in response to OP's comment
In a comment, you said,
I have a function that returns a void pointer and I would need to cast the value accordingly.
If you know that the function returns a void* that truly points to a short object, then, your best bet is:
void* ptr = function_returning_ptr();
short* sptr = reinterpret_cast<short*>(ptr);
int k = *sptr;
The last line work since *sptr evaluates to a short and the conversion of a short to an int is a valid operation. On the other hand,
int k = *(int*)sptr;
does not work since conversion of short* to an int* is not a valid operation.
Your code is subject to undefined behavior, as it violates the so-called strict aliasing rules. Without going into too much detail and simplifying a bit, the rule states that you can not access an object of type X though a pointer to type Z unless types X and Z are related. There is a special exception for char pointer, but it doesn't apply here.
In your example, short and int are not related types, and as such, accessing one through pointer to another is not allowed.
The size of a short is only 16 bits the size of a int is 32 bits ( in most cases not always) this means that you are tricking the computer into thinking that your pointer to a short is actually pointing to an integer. This causes it to read more memory that it should and is reading garbage memory. If you cast s to a pointer to a short then deference it it will work.
short n = 1;
void* s = &n;
int k = *(short*)s;
Assuming you have 2 byte shorts and 4 byte ints, There's 3 problems with casting pointers in your method.
First off, the 4 byte int will necessarily pick up some garbage memory when using the short's pointer. If you're lucky the 2 bytes after short n will be 0.
Second, the 4 byte int may not be properly aligned. Basically, the memory address of a 4 byte int has to be a multiple of 4, or else you risk bus errors. Your 2 byte short is not guaranteed to be properly aligned.
Finally, you have a big-endian/little-endian dependency. You can't turn a big-endian short into a little-endian int by just tacking on some 0's at the end.
In the very fortunate circumstance that the bytes following the short are 0, AND the short is integer aligned, AND the system uses little-endian representation, then such a cast will probably work. It would be terrible, but it would (probably) work.
The proper solution is to use the original type and let the compiler cast. Instead of int k = *(int*)s;, you need to use int k = *(short *)s;

memset pointer + offset

For example, I have:
DWORD pointer = 0x123456;
DWORD offset = 0xABC;
I want to add offset to pointer and set the value at the address pointed by that pointer to 1.0f. How do I give memset() a pointer and an offset as first argument?
DWORDs are the same as uint32_t's. Just add them together as you would with any other integer.
Also, while setting a float (I am assuming you're setting a float due to the 'f' after the '1.0'), I wouldn't use memset. Just cast the pointer to a float, and de-reference it like so:
DWORD pointer = 0x123456;
DWORD offset = 0xABC;
pointer += offset;
float* float_pointer = reinterpret_cast<float*>(pointer);
*float_pointer = 1.0f;
This can be straightforward pointer arithmetic, but we've got a few preliminary issues to take care of first.
Why is your pointer variable declared as a DWORD? We'll need a proper pointer type eventually.
Why are you asking about memset, if you're trying to set a floating-point value? memset sets plain bit patterns; it's not much good for floating-point.
I assume your offset is supposed to be measured in bytes, not sizeof(float).
Anyway, computing the pointer you want could go something like this:
float *fp = (float *)(pointer + offset);
[Notice that I perform the addition inside the parens, before the cast, so as to get a byte offset. If I instead wrote (float *)pointer + offset, it'd offset by `sizeof(float).]
Once we've got that float pointer, we can set the location it points to to 1.0 in the usual way:
*fp = 1.0f;
Or we could set it to 0 using memset:
memset(fp, 0, sizeof(float));

Dereferencing pointer in Code Composer Studio

I have a value I receive in an unsigned byte array that I would like to dereference as a float. Take ptr as a uint8_t* pointing at a byte array of four values 0,0,0xCD,0x42 (this is a little endian system).
float val = *(float*)ptr;
is return -1.34e8
When I type:
*(float*)ptr;
In the expressions window after hitting a break point in that section of code, it gives me 102.5 as expected. Further, when I type:
*(float*)(ptr - 1);
I get the incorrect -1.34e8, as if the compiler used ptr - 1 instead of what I typed.
I'm confused - am I missing something here?
Basically the deref is correct.
If you printf("%p", ptr); do you get an address that is maybe not 4-byte aligned (or at least 2-byte aligned)? This may be necessary on some platforms.
For test, just pass the value of a real float in the uint8_t*, e.g.
float f= 102.5;
yourfunct((uint8_t*)&f);
and see if that works.
*(float*)(ptr - 1);
is the same as this
ptr--; //move the pointer to point to charackter in front of the previous one
*(float*)ptr;
Is this your intention ?
Or do you just want to subtract 1 from the value that is being pointed to be ptr.

64 bit addresses

I compile the application for 64 bit Windows operating system.
The application should save 64 bit addresses, I have to decide about variable type, to save them. I thought to save them in long. But sizeof(long) == 4.Where and how can I save the addresses
You should store memory addresses in pointers:
void *myaddr = 0x0123456789ABCDEF; // memory address
int *myaddr2 = 0x0123456789ABCDEF; // pointer to int in memory, dereferencable
You can get the address of a variable like this:
int myvar;
int *addrofmyvar = &myvar;
printf("%p", addrofmyvar); // use %p to print pointers
Note: there are some differences between C and C++ regarding pointers (esp. void pointers). See the C and C++ standards. There is no such thing as "C/C++".
If you intend to store a pointer as a number, use uintptr_t or intptr_t. They are guaranteed to match the size and the representation of a pointer.
Otherwise you are not writing portable code.
You should use actual pointers (to whatever type is in the address) to store addresses.
I did'nt try it but maybe with long long will work.
Please check this link: http://msdn.microsoft.com/en-us/library/s3f49ktz%28v=vs.80%29.aspx
unsigned long long, 8 bytes,equivalent to unsigned __int64
range: from 0 to 18,446,744,073,709,551,615
Do not use LONG or LONG LONG when writing cross-platform code. LONG does not have the same size on different platforms/different compilers.