?
Solved

16 bit access to 8 bit data non-aligned data

Posted on 2002-03-19
14
Medium Priority
?
177 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
  • 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

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…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
Suggested Courses
Course of the Month13 days, 14 hours left to enroll

807 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