Solved

16 bit access to 8 bit data non-aligned data

Posted on 2002-03-19
14
170 Views
Last Modified: 2010-04-15
Given the code at the end of this question, is it possible to replace the two macros: getWord() and setWord() with a single program element that can appear on either side of an assigment operator?

i.e.

where I now have:
  i = getWord(a)
  i++;
  setWord(a,i);

I want to be able to have something like:
  word(a) = word(a)+1;

Or even better
  word(a)++;

Is it possible to reduce the two macros to one program element?
- I don't have the luxury of using C++ :(
- It doesn't have to be a macro.
- Be as creative as you like
- The important conditions to remember are:
  1. The dataArea array must be an array of unsigned char with no specific WORD alignement.
  2. The appliation must be able to function transparently on processors that use different byte ordering. i.e. Little endian or big endian.
- If you're feeling mighty clever, I also require the same functionality for DWORDS (4 byte unsigned longs). Although that should be a natural extension of the solution for WORD (2 byte unsigned shorts).

Thanks for your time
Paul

#include <stdio.h>

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long  ADDR;

#define getWord(a)   (WORD)((*(dataArea+a)<<8)|*(dataArea+a+1))
#define setWord(a,v) (*(dataArea+a)=((v)>>8)&0xff,*(dataArea+a+1)=(v)&0xff)

BYTE dataArea[] = {
  0x01,0x23,0x45,0x67,0x89,0xAB
};

int
main(int argc, char *argv[])
{
  ADDR     addr=1;
  WORD     i;

  i = getWord(addr);
  printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);
  setWord(addr,1234);
  i = getWord(addr);
  printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);

  return 0;
}
 
0
Comment
Question by:zebada
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 2
  • +1
14 Comments
 
LVL 6

Author Comment

by:zebada
ID: 6881744
I just re-read the question - gee it sounds a lot like a homework assignment.

So before anyone gets upset I'll explain why I need this:

I am upgrading the string handling on a virtual machine. Currently the strings have a limit of 127 characters. That limit can easily be stored in a single byte so getting and setting the string length is as simple as setting up a macro that computes the char * of the string length.

The string handling is being upgraded to handle strings longer than 256 characters. The length obviously needs to use more than 1 byte. So my problem is:

How do I easily upgrade the virtual machine which has hundreds of functions with thousands of references to the string length as a macro. The macro is found wherever a char * can be found - including on the left of an assignment operator.

sombody put me out of my misery :(
Paul
0
 
LVL 86

Expert Comment

by:jkr
ID: 6882597
You're probably gonna hate me for that, but... well, lets see what you think of

#include <stdio.h>

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long  ADDR;

#define WORDREF(a)   ((WORD*)(dataArea+a))

BYTE dataArea[] = {
 0x01,0x23,0x45,0x67,0x89,0xAB
};

int
main(int argc, char *argv[])
{
 ADDR     addr=1;
 WORD     i;

 i = *WORDREF(addr);
 printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);
 *WORDREF(addr)=1234;
 i = *WORDREF(addr);
 printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);

 return 0;
}
0
 
LVL 6

Author Comment

by:zebada
ID: 6883546
If only it were that simple.

It's the little endian/big endian thing that will cause that approach to fail.
I've added to the printf() to display the actual data bytes in the dataArea array like so:

printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd) DataArea=[0x%02x,0x%02x]\n",addr,i,i,dataArea[1],dataArea[2]);

The output of my sample program is:
Value of WORD at Address 0x00000001 is 0x2345 (9029) DataArea=[0x23,0x45]
Value of WORD at Address 0x00000001 is 0x04d2 (1234) DataArea=[0x04,0xd2]

The output of your sample program is:
Value of WORD at Address 0x00000001 is 0x4523 (17699) DataArea=[0x23,0x45]
Value of WORD at Address 0x00000001 is 0x04d2 (1234) DataArea=[0xd2,0x04]

This is really the root of the problem.

It is also a completely acceptable for the solution to use #ifdef's because I will always have a different executable file for different cpu architectures.

Paul
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:BlackDiamond
ID: 6883666
how about changing it to

#define WORDREF(a) ntohl(((WORD*)(dataArea+a)))



0
 
LVL 86

Expert Comment

by:jkr
ID: 6883690
>>#define WORDREF(a) ntohl(((WORD*)(dataArea+a)))

a) would have to read

#define WORDREF(a) ntohs(*((WORD*)(dataArea+a)))

b) doesn't make sense, as these functions work based on the architecture the app is running on not on the architecture the app is emulating

c) is pretty equivalent to what he already has, as it can't serve as a lvalue...
0
 
LVL 86

Expert Comment

by:jkr
ID: 6883777
But, however, BlackDiamond, you gor me in gear :o)

What about

#include <stdio.h>

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long  ADDR;

#define WORDREF(a)   ((WORD*)(dataArea+a))

BYTE dataArea[] = {
0x01,0x23,0x45,0x67,0x89,0xAB
};

#ifdef __LITTLE_ENDIAN__
#define __WORD ( x) ( (x >> 8) | ((x & 0x00FF) << 8 )
#else
#define __WORD ( x) ( x)
#endif

int
main(int argc, char *argv[])
{
ADDR     addr=1;
WORD     i;

i = __WORD( *WORDREF(addr));
printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);
*WORDREF(addr)=__WORD(1234);
i = __WORD( *WORDREF(addr));
printf("Value of WORD at Address 0x%08lx is 0x%04hx (%hd)\n",addr,i,i);

return 0;
}
0
 
LVL 6

Author Comment

by:zebada
ID: 6883811
Neat idea, but it doesn't get me any closer to than I already am.

I still can't use the same macro on both sides of the assignment operator.

That means I need to go through the code and edit ALL instances of the exiting single (char *) macro that currently CAN and DOES appear on both sides of an assignment operator.

Because (char *) is ALWAYS the same no matter what the cpu architecture it can be used as both l-value and r-value.

Maybe it's not possible with multibye integers.

0
 
LVL 86

Expert Comment

by:jkr
ID: 6883831
>>Maybe it's not possible with multibye integers.

Afford the luxory to use C++ and it's a matter of minutes to find a soultion :o)
0
 
LVL 6

Author Comment

by:zebada
ID: 6883849
Oh, how I've dreamed of being able to write this VM in C++. :-(

Don't forget I am at liberty to change the format of the dataArea[] array. That's essentially the object code format.
However it must be the same for both architecture types to provide 100% cross-platform portability.
0
 
LVL 6

Author Comment

by:zebada
ID: 7315170
Just in case you're interested - I solved the problem by dynamically modifying the "object code" when it is loaded into the virtual machine. The object code is changed so that anywhere 2, 4 or 8 byte integers are used they are converted to the endian of the current processor.

I am going to delete this question.
0
 
LVL 1

Expert Comment

by:Computer101
ID: 7315477
A request for deletion has been made.  If no objection, I will place this in PAQ

Computer101
E-E Admin
0
 
LVL 86

Expert Comment

by:jkr
ID: 7317540
I'd say, there are some nice tricks shown in here, why not PAQ (even @0)?
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
ID: 7317548
Points refunded and placed in PAQ

Computer101
E-E Admin
0
 
LVL 86

Expert Comment

by:jkr
ID: 7317550
Hey, at 0 points, you could have given me the "answer" :o)
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

729 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question