[comp.lang.c] Set function address into absolute memory?

mikec@ux1.lbl.gov (Mike Chin) (07/07/89)

Is there a reasonable way to place the address of a function into
an absolute location? I need to do this to set up the vector table in
an 80186. I would have thought that something like "a pointer to a function"
set to the table address would work, but it seems I have to wrap it inside
of a structure. Here's an example that shows the structure, and in comments what
seems should be OK. This lints with Gimpel, and runs under MSC 5.1
in large model...
----------------------------------------------------
/*
instead of malloc, for an real vector table I would use
absolute addresses
*/

#include <stdio.h>
#include <malloc.h>

typedef	struct	{
	void (*oopa)();
	}functype;

void	vector();

void main()
{
	void 		(*funcpoint)();
	functype	*funcstruct;
/*
	this won't pass lint
	funcpoint=(void*) malloc (4);
	*funcpoint = vector;
	*funcpoint();
*/

	funcstruct=(functype *) malloc(4);
	funcstruct->oopa=vector;
	funcstruct->oopa();

}

void vector()
{
	printf ("this is the stuff\n");
}
----------------------------------------------------
Mike Chin
MJChin@lbl.gov

desnoyer@apple.com (Peter Desnoyers) (07/08/89)

In article <2954@helios.ee.lbl.gov> mikec@ux1.lbl.gov (Mike Chin) writes:
> Is there a reasonable way to place the address of a function into
> an absolute location? I would have thought that something like "a pointer
> to a function"
> set to the table address would work [...]

It should. See below.

> void main(){
>     void    (*funcpoint)(); 
                   ^
       i.e. (*funcpoint)() is void, and *funcpoint is a function -
       therefore the value of funcpoint is the address of the first
       instruction in that function.
>
>         funcpoint=(void*) malloc (4); 
                       ^
         Allocate memory to put the code into??? and then cast it
         to type void, instead of void (*)()? (need a typedef to do
         this cast correctly, although there's not much point to it)

[more code...]

What you want to do is allocate an array of pointers to functions
(the malloc'ed pointer will be type pointer to pointer to function),
put a pointer to a function in the space so allocated, and proceed
from there. e.g. -

  /* code fragment: */
  typedef void (*fptr)();   /* type fptr is "pointer to function" */
  fptr * tmp;               /* tmp points to an array of fptrs */
  tmp = (fptr *) malloc( sizeof( fptr));  /* allocate 1 fptr */
  tmp[0] = vector;          /* and set the value */
  (*tmp[0])();              /* now call vector() */

This lints with no errors. 

                                      Peter Desnoyers
                                      Apple ATG
                                      (408) 974-4469

flaps@jarvis.csri.toronto.edu (Alan J Rosenthal) (07/08/89)

mikec@ux1.lbl.gov (Mike Chin) writes:
...
>void	vector();
...
>	void 		(*funcpoint)();
>	functype	*funcstruct;
>/*
>	this won't pass lint
>	funcpoint=(void*) malloc (4);
>	*funcpoint = vector;
>	*funcpoint();
>*/

The declaration of funcpoint should be void (**funcpoint)();.  The function
address you are storing is a pointer to function returning void, so the pointer
to the memory it should be stored into is a pointer to pointer to function
returning void.

The cast of malloc's return value should be redundant as it should be declared
as returning void * in memory.h.

To keep your program portable (possibly only between compiler upgrades, if your
program is machine-specific anyway), rather than "malloc(4)" write
"malloc(sizeof(void (*)()))".

ajr