Accessing high and low bytes of a unsigned short in a struct.

Discussion in 'C++' started by James Roberge, May 12, 2005.

  1. I am having a little trouble getting my union/struct to work correctly.

    I am creating a struct that will contain information about the status of
    various Z80 cpu registers in an emulator i am trying to write.

    some of the registers such as "DE" can be accessed as 16 bit data or the
    high and low bytes can be accessed separately. SO, "DE" refers to the
    16 bit data, where "D" and "E" refer to the high and low bytes respectively.

    Here is what i have so far.

    typedef union {
    struct {
    unsigned char L; //Swapped cause i am little endian
    unsigned char H;
    } B;
    unsigned short W;
    } PAIR;

    struct Registers {
    unsigned char A; // A Register, all is good here.
    PAIR DE; // use the above union to emulate.
    };

    Now, all is ok, when i access the registers like this.

    Registers regs1;
    regs1.A = 0xFF; //Works as expected
    regs1.DE.W = 0xCAFE; //Set 16 bit register

    //therefore

    regs1.DE.B.H == 0xCA
    regs1.DE.B.L == 0xFE

    The problem is i find this too ugly. and i would like for the above
    code to look more like this and still work exactly the same.

    Registers regs1;
    regs1.A = 0xFF; //Works as expected
    regs1.DE = 0xCAFE; //Set 16 bit register

    //therefore

    regs1.D == 0xCA
    regs1.E == 0xFE


    How would i go about defining this union/structure so that i can access
    them more gracefully? Does it involve anonymous unions/structures, and
    are anonymous unions and structs valid standard C++?

    Thanks

    James
     
    James Roberge, May 12, 2005
    #1
    1. Advertising

  2. James Roberge wrote:
    > I am having a little trouble getting my union/struct to work

    correctly.
    >
    > I am creating a struct that will contain information about the status

    of
    > various Z80 cpu registers in an emulator i am trying to write.
    >
    > some of the registers such as "DE" can be accessed as 16 bit data or

    the
    > high and low bytes can be accessed separately. SO, "DE" refers to

    the
    > 16 bit data, where "D" and "E" refer to the high and low bytes

    respectively.
    >
    > Here is what i have so far.
    >
    > typedef union {
    > struct {
    > unsigned char L; //Swapped cause i am little endian
    > unsigned char H;
    > } B;
    > unsigned short W;
    > } PAIR;
    >
    > struct Registers {
    > unsigned char A; // A Register, all is good here.
    > PAIR DE; // use the above union to emulate.
    > };
    >
    > Now, all is ok, when i access the registers like this.
    >
    > Registers regs1;
    > regs1.A = 0xFF; //Works as expected
    > regs1.DE.W = 0xCAFE; //Set 16 bit register
    >
    > //therefore
    >
    > regs1.DE.B.H == 0xCA
    > regs1.DE.B.L == 0xFE
    >
    > The problem is i find this too ugly. and i would like for the above
    > code to look more like this and still work exactly the same.
    >
    > Registers regs1;
    > regs1.A = 0xFF; //Works as expected
    > regs1.DE = 0xCAFE; //Set 16 bit register
    >
    > //therefore
    >
    > regs1.D == 0xCA
    > regs1.E == 0xFE
    >
    >
    > How would i go about defining this union/structure so that i can

    access
    > them more gracefully? Does it involve anonymous unions/structures,

    and
    > are anonymous unions and structs valid standard C++?
    >
    > Thanks
    >
    > James



    You could write a wrapper class containing a union and define members
    SetHi(unsigned char h) and SetLo(unsigned char l), as well as
    corresponding Get methods. An overloaded operator= could be used to
    assign unsigned shorts to the register as a whole. Of course, it's a
    matter of taste whether you think it is prettier to say
    regs1.SetLo(0xCA) than regs1.B.L = 0xCA. Of course you could write much
    more sophisticated methods that behave more like you want.

    Some people consider unions not proper C++, but this seems like a
    proper use for them. You could define a class that stores the data as
    two bytes and calculates the conversions to and from a 16 bit word on
    the fly, or do it the other way around - store as a word, and have
    member functions calculate or manipulate the byte values. I think a
    union would do nicely here though.

    regards Mark
     
    Mark Stijnman, May 12, 2005
    #2
    1. Advertising

  3. James Roberge

    Jay Nabonne Guest

    On Thu, 12 May 2005 06:41:02 +0000, James Roberge wrote:

    > I am having a little trouble getting my union/struct to work correctly.
    >
    > I am creating a struct that will contain information about the status of
    > various Z80 cpu registers in an emulator i am trying to write.
    >
    > some of the registers such as "DE" can be accessed as 16 bit data or the
    > high and low bytes can be accessed separately. SO, "DE" refers to the
    > 16 bit data, where "D" and "E" refer to the high and low bytes respectively.
    >
    > Here is what i have so far.
    >
    > typedef union {
    > struct {
    > unsigned char L; //Swapped cause i am little endian
    > unsigned char H;
    > } B;
    > unsigned short W;
    > } PAIR;
    >
    > struct Registers {
    > unsigned char A; // A Register, all is good here.
    > PAIR DE; // use the above union to emulate.
    > };
    >
    > Now, all is ok, when i access the registers like this.
    >
    > Registers regs1;
    > regs1.A = 0xFF; //Works as expected
    > regs1.DE.W = 0xCAFE; //Set 16 bit register
    >
    > //therefore
    >
    > regs1.DE.B.H == 0xCA
    > regs1.DE.B.L == 0xFE
    >
    > The problem is i find this too ugly. and i would like for the above
    > code to look more like this and still work exactly the same.
    >
    > Registers regs1;
    > regs1.A = 0xFF; //Works as expected
    > regs1.DE = 0xCAFE; //Set 16 bit register
    >
    > //therefore
    >
    > regs1.D == 0xCA
    > regs1.E == 0xFE
    >
    >
    > How would i go about defining this union/structure so that i can access
    > them more gracefully? Does it involve anonymous unions/structures, and
    > are anonymous unions and structs valid standard C++?
    >


    Seems like you could use an alias (aka "reference"):

    typedef union {
    struct {
    unsigned char L; //Swapped cause i am little endian
    unsigned char H;
    } B;
    unsigned short W;
    } PAIR;

    struct Registers
    {
    Registers() : DE(DEReg.W), D(DEReg.B.H), E(DEReg.B.L)
    {
    }

    unsigned char A;
    unsigned short& DE;
    unsigned char& D;
    unsigned char& E;

    private:
    PAIR DEReg; // Don't want direct access.
    };

    int main()
    {
    Registers r;

    r.A = 0x71;
    r.D = 0xa0;
    r.E = 0x65;
    return 0;
    }

    HTH

    - Jay
     
    Jay Nabonne, May 12, 2005
    #3
  4. James Roberge wrote:

    > Now, all is ok, when i access the registers like this.
    >
    > Registers regs1;
    > regs1.A = 0xFF; //Works as expected
    > regs1.DE.W = 0xCAFE; //Set 16 bit register
    >
    > //therefore
    >
    > regs1.DE.B.H == 0xCA
    > regs1.DE.B.L == 0xFE
    >
    > The problem is i find this too ugly. and i would like for the above
    > code to look more like this and still work exactly the same.


    there are annonymous unions:

    struct register {
    unsigned short W;
    union {
    unsigned char h;
    unsigned char l;
    };
    };

    you use it:

    int main()
    {
    register x;
    x.W = 1; // 16 bit access
    x.h = 3; // 8 bit access
    x.l = 1;
    }



    cheers,
    Michael
     
    Michael Wohlwend, May 13, 2005
    #4
  5. James Roberge wrote:
    > I am having a little trouble getting my union/struct to work correctly.
    >

    [SNIP]

    Ok, welli seem to have it working a bit more to my liking. here is what
    i have.

    typedef unsigned char BYTE;
    typedef unsigned short WORD;

    typedef union Z80RegisterPair {
    struct {
    BYTE L;
    BYTE H;
    };
    WORD W;
    } PAIR;

    struct Z80Registers {
    BYTE A, Ax;
    PAIR BC, BCx;
    PAIR DE, DEx;
    PAIR HL, HLx;
    };

    This allows me to access like this

    Z80Registers regs1;

    regs1.DE.W = 0xCAFE; //For the 16 bit value.
    //therefore
    regs1.DE.H == 0xCA;
    regs1.DE.L == 0xFE;


    Any other suggestions would be great though.

    James
     
    James Roberge, May 13, 2005
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page