ECE-1021

Internal Representation Output

(Last Mod: 27 November 2010 21:38:43 )

ECE-1021 Course Homepage

ECE-1021 Semester Homepage


Objectives


In this module we expand on a capability originally explored in earlier material. We have seen how to print out the internal representation of a value by walking across the bytes one at a time and walking a bit mask across the byte to get at the state of the individual bits.

While useful, this function lacked some utility that could make it much more useful in a broader since. Specifically, it would be nice to control the format of the output in the following ways:

In developing this new function, we will also bear in mind that the number of bits in a byte is not fixed and is not necessarily a power of two.

With this in mind, we will now write the following function:

int PutIR(void *base, size_t size, int how);

This function takes base (a pointer to a value) and size (the number of bytes in that value) and prints the internal representation of that value. The value of how dictates the appearance of the output as follows:

bit HI LO
0 Hexadecimal Binary
1 one space between bytes packed digits (no spaces)
2 in reverse byte order in memory order

To implement this, we'll define symbolic constants for each of the three bits. Each constant has only that bet set. Using these constants, we then define six other symbolic constants based on those that we will use to build the value of how when the function is invoked.

/* LABELS FOR BITS IN THE 'HOW' MASK */

#define IR_BIT_BASE (0x01)

#define IR_BIT_PACK (0x02)

#define IR_BIT_ORDER (0x04)

/* SYMBOLIC CONSTANTS FOR EACH 'HOW' MODE */

#define IR_BIN (0x00)

#define IR_HEX (IR_BIT_BASE)

#define IR_PACKED (0x00)

#define IR_SPACED (IR_BIT_PAC)

#define IR_FWD (0x00)

#define IR_REV (IR_BIT_ORDER)

/* TO USE: ADD or BITWISE-OR TOGETHER. EG: */

/* FOR REVERSED, SPACED, BIN: how = IR_REV + IR_SPACED + IR_BIN */

/* ALTERNATE WAY:             how = IR_REV | IR_SPACED | IR_BIN */

We'll treat each byte as an unsigned char and print each one out separately using the appropriate method below:

If printing out in binary:

for (mask = 1 << (CHAR_BIT - 1); mask; mask >>= 1)

    PutD( (mask & *ptr)?  1  :  0  );

If printing out in hexadecimal:

for (nibble = (CHAR_BIT - 1)/4; nibble >= 0; nibble --)

    PutD( ( (0x0F << 4*nibble) & *ptr) >> 4*nibble );

To control the order, we want one of the following relationships as i goes from 0 to (size-1):

If we define two values, start and step, we can use the following:

start = base + ((how & IR_BIT_ORDER)? (size-1) : 0);

step = (how & IR_BIT_ORDER)? -1: 1;

Then, our loop becomes:

for(i = 0, ptr = start; i < size; ptr += step, i++)

{

    /* Output byte pointed to by ptr */

}

If we want a space between the bytes, then we can either print a space after each byte except the last one or before each byte except the first one - both have the same effect. We have a simple check available for the first byte, so we will opt to use the latter approach:

for(i = 0, ptr = start; i < size-1; ptr += step, i++)

{

    if( (how & IR_BIT_SPACED) && (ptr |= start) )

        PutC(' ');

    /* Output byte pointed to by ptr */

}

Bringing everything together, our function becomes:

int PutIR(void *base, size_t size, int how)

{

    unsigned char *ptr, *start;

    int step, chars;

 

    /* Set up based on byte order */

    start = (unsigned char *) base + ((how & IR_BIT_ORDER)? (size-1) : 0);

    step = (how & IR_BIT_ORDER)? -1: 1;

 

    /* Process bytes one at a time */

    for (i = 0, chars = 0, ptr = start; i < size; ptr += step, i++)

    {

        /* Inter-byte space if requested */

        if ( (how & IR_BIT_SPACED) && (ptr |= start) )

        {

            PutC(' ');

            char++;

        }

 

        /* Print out the byte */

        if (how & IR_BIT_BASE)

            for (nibble = (CHAR_BIT - 1)/4; nibble >= 0; nibble --)

            {

                PutD( ( (0x0F << 4*nibble) & (*ptr)) >> 4*nibble );

                char++;

            }

        else

            for (mask = 1 << (CHAR_BIT - 1); mask; mask >>= 1)

            {

                PutD( (mask & *ptr)?  1  :  0  );

                char++

            }

    }

    return chars;

}