views:

748

answers:

5

I realize that far is compiler specific, but my expectation is that the placement of the far specifier should make sense to those who really understand pointers.

So, I have two applications that share the processor's entire memory space.

App A needs to call function foo that exists in app B.

I know the memory location of function foo.

So this should work, in app A:

typedef int (* __far MYFP)(int input);

void somefunc(void)
{
   int returnvalue;
   MYFP foo;

   foo = (MYFP) 0xFFFFFA;

   returnvalue = foo(39);
}
  • Is the __far in the right spot in the typedef?
  • Do I need to add __far to the (MYFP) cast?
  • Some information suggests that the call to foo doesn't need to be dereferenced, what is your experience?
  • What else about this looks incorrect, or might I try to accomplish this?

  • Is there a better way to do this?

Edit:

This is on an embedded device (Freescale S12XEQ device) using Code Warrior. It's a 16 bit device with 24 bit memory space, so yes, it is segmented/banked.

+8  A: 

The __far keyword, at least in the MS world, was used when creating binaries that used segmented memory. You need to understand 8086 memory system to understand this. The 8086 divided the memory into segments, each segment was 64K long, so each address in a segment needed 16bits. Addresses came in two forms: near and far. A near address was 16bits and was an offset into the current segment, one of CS,DS,ES,SS depending on the instruction, a far was 32bits and consisted of a segment and an offset. In the 8086, the absolute address was 16 * segment + offset, giving an addressable range of 1Mb.

If you're not using a segmented memory system, and it looks like you are not, then all addresses have the same number of bits so the near/far distinction is not necessary which means the keyword is probably ignored by the compiler.

Skizz

Skizz
Yes, it did mean there was 4096 ways to address the same byte of memory.
Skizz
__far existed not only on x86 family with segmented addressing. M68k, PowerPC and some other had also this qualifier. I think in the embedded it is still used. To make answer the original question we need therefor more information (like plattform, compiler, ...)
flolo
I understand this, and yes, my memory is segmented.
Adam Davis
+1  A: 

This is a snippet of code that works from a project I am working on. It's Paradigm C++, so it uses some version of Borland. The CPU it uses is an 8086 clone, so segmented 20-bit memory.

void softSerial0SR(unsigned16);
void (__far *softHandler)(unsigned16);

I initialize softHandler to 0 without complaint.

Then,

softHandler = softSerial0SR;

in setup code.

To call it, just call softHandler like a regular function.

Note that this code is slightly tweaked for you from the actual code I have.

Paul Nathan
+6  A: 

Is the __far in the right spot in the typedef?

[Edit, in response to ChrisN's comment -- thanks]

This is a compiler-dependent feature, since it is not part of ANSI C. According to the compiler manual <http://www.freescale.com/files/soft_dev_tools/doc/ref_manual/CW_Compiler_HC12_RM.pdf&gt;, chapter 8, you have it placed correctly. In other compilers, you may need to reverse the order. This should be pretty easy to figure out, though, since exactly one of the two options will compile with any given compiler.

Do I need to add __far to the (MYFP) cast?

Nope, it's part of the type.

Some information suggests that the call to foo doesn't need to be dereferenced, what is your experience?

Function pointers can be optionally dereferenced in C. The following lines are both valid do the exact same thing:

foo = (MYFP)0xFFFFFA;
returnvalue = foo(39);  // 1
returnvalue = (*foo)(39);  // 2

What else about this looks incorrect, or might I try to accomplish this?

You've done it exactly correctly.

Adam Rosenfield
Good answer, except that the documentation for the compiler he's using states that the function pointer syntax should be typedef int (* __far MYFP)(int). See http://www.freescale.com/files/soft_dev_tools/doc/ref_manual/CW_Compiler_HC12_RM.pdf
ChrisN
A: 

the both programs were built by the same compiler/options, so they use the same OBI?

n-alexander
A: 

Agree the code looks fine - in this case, I would get a disassembly of the code generated, and figure out if it came out right. There should only be 10 instructions at the most - and then you will know for sure if it worked.

Jeff