Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!killer!ames!mailrus!iuvax!pur-ee!a.cs.uiuc.edu!uxc.cso.uiuc.edu!uxe.cso.uiuc.edu!mcdonald From: mcdonald@uxe.cso.uiuc.edu Newsgroups: comp.lang.c Subject: Re: Self-modifying code Message-ID: <225800044@uxe.cso.uiuc.edu> Date: 10 Jul 88 15:13:00 GMT References: <12330@ut-sally.UUCP> Lines: 51 Nf-ID: #R:ut-sally.UUCP:12330:uxe.cso.uiuc.edu:225800044:000:2699 Nf-From: uxe.cso.uiuc.edu!mcdonald Jul 10 10:13:00 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