A simple example: say you have a program containing a variable foo which is only ever used by two instructions, one of which loads it into a register, the other of which increments it (we'll assume the architecture has an inc instruction which can be applied to a memory location):
start: load r1, foo ; ; other stuff... ; inc foo jmp start
start: load r1, 42 ; ; other stuff... ; inc (start+1) jmp start
This, of course, is a very weak example. Much more interesting things happen when you start modifying the actual opcodes, so that completely different instructions will be executed on each pass through the loop.
code
This was brought to you by the Save Our Archaic Technical Terms Society.
A couple of high-level languages offer the (usually evil) choice to change your code in run time.
The best example is most likely COBOL. The ALTER statement works in the following way :
. . (some thousands of lines snipped) . PERFORM READ-DATA UNTIL MY-SUM IS GREATER THAN 700. . . (some more lines snipped) . READ-DATA SECTION. HERE-IT-GOES. GO TO INITIAL-ITERATION. INITIAL-ITERATION. MOVE 0 TO MY-SUM. ALTER HERE-IT-GOES TO PROCEED TO MORE-ITERATIONS. GO TO READ-FROM-FILE. MORE-ITERATIONS. ADD INPUT-SUM TO MY-SUM ROUNDED. READ-FROM-FILE. READ INFILE. READ-DATA-EXIT. EXIT.
What it does is simple: Read records from an input file until the sum of values in a certain field of the input field is greater than 700.
The ALTER statement changes the statement
GO TO INITIAL-ITERATION.
GO TO MORE-ITERATIONS.
during run-time.
Most people who wrote COBOL compilers apart from IBM decided not to implement ALTER.
Some lesser-known languages like NODAL and POCAL also offered self-modifying code features, easier to implement because both were interpreted languages.
A sample in POCAL :
10.10 SET I=0 10.20 SET POCLIN(10.10)="SET I=" I+1 10.30 DO 20!30 10.40 TYPE "Program used " I " times" ! 10.50 END 20.10 SAVE "(SOMEDISK:SOMEUSER)STUPID:POCL" 30.10 TYPE "Saving failed - tough luck !"
The conclusion might be that languages which allow for self-modifying code are also self-obfuscating.
(function-lambda-expression #'foo)
If you define a function:
(lambda (x) (foo x))
Then you change the definition of foo, then the above function will call the new version of foo. This still works if the function is compiled.
All behaviour tested under Corman Lisp version 1.42
The standard for Common Lisp allows function-lambda-expression to return nil whenever it wants.
printable version chaos
Everything2 Help