Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to tie variables in c++

Well my problem is as follows: I'm trying to translate an x86 assembly source code to c++ source code.

Explanation as to what registers are.
    skip this if you know what they are and how they work.    
As you may or may not know, assembly language makes use of "general purpose registers".
    In x86 assembly these registers are, and can be considered as "4 bytes" in length variables ( int var in c++ ), their names are: eax, ebx, ecx and edx.
    Now, these registers are each respectively broken down into ax, bx, cx and dx that represent the 2 bytes less significant value of each register.
    ax, bx, cx and dx are also broken down into ah, bx, ch and dh ( most significant byte ) and al, bl, cl and dl ( less significant byte ).
    So, for example:
    If I set eax:
    EAX = 0xAB12CDEF
    that would automatically change ax, al and ah
    AX would become 0xCDEF
    AH would become 0xCD
    AL would become 0xEF

My question is: How do I make that possible in C++ ?

int eax, ax, ah, al;
eax = 0xAB12CDEF

How can I make, ax, ah and al, change at the same time? Or is it possible to make them pointers to different portions eax, if so, how? Thanks! P.S. Also how could i use to make another variable be a char ? How could I make variable new variable "char chAL" point to al which points to eax. So that when i make a change to chAL, the changes would automatically reverberate to eax, ah and al.

like image 298
Fresco Avatar asked Jan 18 '26 02:01

Fresco


2 Answers

If your goal is to emulate X86 assembly code, then indeed you need to support the behaviour of X86 registers.

Here's a simple implementation using a union:

#include <iostream>
#include <cstdint>

using namespace std;

union reg_t {
    uint64_t rx;
    uint32_t ex;
    uint16_t x;
    struct {
        uint8_t l;
        uint8_t h;
    };
};

int main(){
    reg_t a;

    a.rx = 0xdeadbeefcafebabe;

    cout << "rax = " << hex << a.rx << endl;
    cout << "eax = " << hex << a.ex << endl;
    cout << "ax  = " << hex << a.x << endl;
    cout << "al  = " << hex << (uint16_t)a.l << endl;
    cout << "ah  = " << hex << (uint16_t)a.h << endl;

    cout << "ax & 0xFF      = " << hex << (a.x & 0xFF) << endl;
    cout << "(ah << 8) + al = " << hex << (a.h << 8) + a.l << endl;

}

output:

rax = deadbeefcafebabe
eax = cafebabe
ax  = babe
al  = be
ah  = ba
ax & 0xFF      = be
(ah << 8) + al = babe

You'll get the correct result on the right platform (little-endian). You'll have to swap bytes, and/or add padding for other platforms.

That's the basic, down to earth solution, which will certainly work on many x86 platforms (at least X86/linux/g++ works fine), but the behaviour this very approach relies on seems undefined in C++.

Here's another approach using a byte array to store register content:

class x86register {

  uint8_t bytes[8]; 

public:

  x86register &operator =(const uint64_t &v){
    for (int i = 0; i < 8; i++)
      bytes[i] = (v >> (i * 8)) & 0xff;
    return *this;
  }

  x86register &operator =(const uint32_t &v){
    for (int i = 0; i < 4; i++)
      bytes[i] = (v >> (i * 8)) & 0xff;
    return *this;
  }

  x86register &operator =(const uint16_t &v){
    for (int i = 0; i < 2; i++)
      bytes[i] = (v >> (i * 8)) & 0xff;
    return *this;
  }

  x86register &operator =(const uint8_t &v){
    bytes[0] = v;
    return *this;
  }

  operator uint64_t(){
    uint64_t res = 0;
    for (int i = 7; i >= 0; i--)
      res = (res << 8) + bytes[i];
    return res;
  }

  operator uint32_t(){
    uint32_t res = 0;
    for (int i = 4; i >= 0; i--)
      res = (res << 8) + bytes[i];
    return res;
  }

  operator uint16_t(){
    uint16_t res = 0;
    for (int i = 2; i >= 0; i--)
      res = (res << 8) + bytes[i];
    return res;
  }

  operator uint8_t(){
    return bytes[0];
  }

};

This simple class should work regardless of endianness on the running platform. Also, you probably want to add a few other accessors/mutators to handle the HSB (AH, BH, etc) of word registers.

like image 183
didierc Avatar answered Jan 19 '26 17:01

didierc


You can extract parts of eax using bitwise operations, like this:

void main()
{
    int eax, ax, ah, al;
    eax = 0xAB12CDEF;
    ax = eax & 0x0000FFFF;
    ah = (eax & 0x0000FF00) >> 8;
    al = eax & 0x000000FF;
    printf("ax = eax & 0x0000FFFF           = 0x%X\n", ax);
    printf("ah = (eax & 0x0000FF00) >> 8    = 0x%X\n", ah);
    printf("al = eax & 0x000000FF           = 0x%X\n", al);
}

Output

ax = eax & 0x0000FFFF           = 0xCDEF
ah = (eax & 0x0000FF00) >> 8    = 0xCD
al = eax & 0x000000FF           = 0xEF

You could also define macro like that:

#define AX(dw) ((dw) & 0x0000FFFF)
#define AH(dw) ((dw) & 0x0000FF00) >> 8)
#define AL(dw) ((dw) & 0x000000FF)

void main()
{
    int eax = 0xAB12CDEF;
    cout << "ax = " << hex << AX(eax) << endl; // prints ax = 0xCDEF
}
like image 25
regmagik Avatar answered Jan 19 '26 16:01

regmagik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!