Self-modifying code
mcdonald at uxe.cso.uiuc.edu
mcdonald at uxe.cso.uiuc.edu
Mon Jul 11 01:13:00 AEST 1988
> [discussion of execute-only code segments]
> > Besides, I thought that self-modifying code was (a) extremely difficult
> >to write, and (b) considered poor programming practice.
>
> Yes, it is and it is.
>
Yes, it is and yes it is, but only by those who don't need it. There
are good uses for self-modifying code: I have used it recently in
two places (one on an IBMPC and the second on a PDP-11.
The first is the use of self-modifying code in
interrupt handlers. It is necessary sometimes to change data segment
in such a handler. The only place to put the value for the data segment
is in the code segment, because when the interrupt occurs, only
the CS register is valid. You could quibble about whether this would
be self-modifying code if you put the value out-of-line and got it
through a pointer. This example was in assembler of course.
The second use is not absolutely necessary - but the results sure
are nice. This involves changing the code in graphics routines on the
fly. Absolutely nothing is more important than making write-to-screen
routines fast (well, nothing having to do with computers.) I have
an example where 4 decisions about 1 instruction each need to be
made at run time. I can do three things:
1. Use a case statement or an if to select the proper one based on
a flag.
2. Put the little area of code where these occur in a subroutine
and call the proper one through a pointer. Unfortunately there
would be maybe 10 subroutines with the various choices.
3. Set up the code at run time ,which is self-modifying code.
Possibility 1. is slow. No doubt about it. It reduces something
which should occur in the blink of an eye to a crawl. Slowness
is absolutely forbidden, so this is out.
Possibility 3. won't be slow if a big enough chunk of code is
included around the messy part. But is is memory intensive. If the
smallest fast-enough chunk is 200 bytes, this adds up to 2000 bytes.
Possibility 2 works fine and is fast enough, but requires
assembler intervention- doing it in C is possible but actually
harder (a lot harder). It also upsets certain religious net-persons.
What did I actually do? On the PC, I used 10 different subroutines.
On the PDP-11, where there is only 56K memory, I used self modifying code.
This brings up another point. A fourth alternative, possible
in Fortran but not in C, is the computed or assigned goto. The
overhead for these is less than a subroutine call, so the amount of
code you need in a clump for it to be fast enough is small.
Alternatively, if the complier were smart enough (mine wasn't) it
could convert a case statement into the equivalent of a computed goto.
Doug McDonald
More information about the Comp.lang.c
mailing list