Self Modifying Code - Part 1
TTA (Transport Triggered Architecture) and SUBLEQ can use pointer but it requires the use self modifying code. Reading data from a memory location to a variable called DATA from an address stored in (pointed to by) a variable called ADDR is an example. We can write it as:
- DATA = [ADDR]
Not to be confused with copy or move:
- DATA = ADDR
DATA = [ADDR] can be coded as:
T T ? ; T=0
PTR PTR ? ; PTR=0
ADDR T ? ; T=-ADDR
T PTR ? ; PTR=ADDR
T T ? ; T=0
PTR: T T ? ; T=-PTR (self modifying code)
DATA DATA ? ; DATA=0
T DATA ? ; DATA=[ADDR]
Although the assembler thinks the first T on the PTR: line is real and initially set with the address of "T", the code above overwrites the address with the value held in ADDR. The only problem is that code cannot reside in ROM (as it is self modifying).
A more general form would be:
- Copy [SRC] to [DST]
This would be coded as:
SRC_PTR SCR_PTR ? ; Copy SRC to SRC_PTR T T ? SRC T ? T SRC_PTR ? DST_PTR DST_PTR ? ; Copy DST to DST_PTR T T ? DST T ? T DST_PTR ? NDATA NDATA ? ; COPY [SRC] TO NDATA TO [DST] SRC_PTR: SRC_PTR NDATA ? ; SELF MODIFYING CODE NDATA DST_PTR: DST_PTR ? ; SELF MODIFYING CODE T T RTN ; RETURN
Getting code in ROM to RAM without self modifying code is tricky, but first an assembler update.
Assembler Updated
SYNTAX
A space is required between tokens.
SUBLEQ defined variables:
- Z ( Zero, if used must be cleared after use )
- T ( Temp, must be cleared before use )
SUBLEQ defined constants (value should not be changed):
- N ( Negative or -1 )
- P ( Positive or +1 )
Comments:
- ( begin in-line comment
- ) end in-line comment
- ; end of line comment
Address Labels:
- . next address
- ? next address
- label label for address reference or variable
- .label variable (location) for label (compiler sets address)
- label: address reference (goto location) for label (compiler sets address)
- @label absolute (fixed) address for label (no code generated)
Constants and Literals:
- Digits constant (example "1")
- -? constant (example "-1")
- -? literal (example "-end")
Examples of code (note: line numbers are not part of the assembler code):
- ( HELLO WORLD! )
- E OUTPUT ?
- L OUTPUT ?
- L OUTPUT ?
- O OUTPUT ?
- BLANK OUTPUT ?
- W OUTPUT ?
- O OUTPUT ?
- R OUTPUT ?
- L OUTPUT ?
- D OUTPUT ?
- BANG OUTPUT ?
- Z Z HALT ; And end program
- ( ASCII characters )
- .H 72
- .E 69
- .L 76
- .O 79
- .BLANK 32
- .W 87
- .R 82
- .D 68
- .BANG 33
- ( Predined variables and addresses )
- .Z 0
- .T 0
- .P 1
- .N -1
- .SP -17
- @OUTPUT -1 ; On my system
- @INPUT -2 ; On my system
- @HALT 0 ; Return to monitor
Example assembler output (note: line numbers are not part of the assembler output):
- 39 -1 3
- 41 -1 6
- 43 -1 9
- 43 -1 12
- 45 -1 15
- 47 -1 18
- 49 -1 21
- 45 -1 24
- 51 -1 27
- 43 -1 30
- 53 -1 33
- 55 -1 36
- 57 57 0
- 72
- 69
- 76
- 79
- 32
- 87
- 82
- 68
- 33
- 0
- 0
- 1
- -1
- -17
Note that the ".label" command exports variable values one per line while the "label:" command exports as a triplet (i.e. a SUBLEQ instruction).
Self Modifying Code - Part 2
The following code fragments sets up a pointer [ADDR1] to pointer [ADDR2] copy that returns the DATA copied:
( SET SYSTEM DEFAULTS)
@INPUT -1
@OUTPUT -2
@HALT 0
@Z -9
@T -10
@SP -11
( VARIABLES )
@A -12
@B -13
@C -14
@D -15
@E -16
@F -17
@L -18
@H -19
@I -20
@J -21
@K -22
@TOP_OF_FREE_RAM -33
( POINTER TO POINTER COPY EQUATES )
@PPC -32
@NDATA -23
@SRC -32
@DST -28
@RTN -24
( POINTER TO POINTER COPY ROUTINE LINES )
@PPC_L1 -32 ; SRC
@PPC_L2 -31 ; NDATA
@PPC_L3 -30 ; ? (=PPC_L4)
@PPC_L4 -29 ; NDATA
@PPC_L5 -28 ; DST
@PPC_L6 -27 ; ? (=PPC_L7)
@PPC_L7 -26 ; T
@PPC_L8 -25 ; T
@PPC_L9 -24 ; RTN
( COPY ROM CODE TO RAM - THE HARD WAY )
PPC_L1 PPC_L1 ? T T ? PPC_D1 T ? T PPC_L1 ?
PPC_L2 PPC_L2 ? T T ? PPC_D2 T ? T PPC_L2 ?
PPC_L3 PPC_L3 ? T T ? PPC_D3 T ? T PPC_L3 ?
PPC_L4 PPC_L4 ? T T ? PPC_D4 T ? T PPC_L4 ?
PPC_L5 PPC_L5 ? T T ? PPC_D5 T ? T PPC_L5 ?
PPC_L6 PPC_L6 ? T T ? PPC_D6 T ? T PPC_L6 ?
PPC_L7 PPC_L7 ? T T ? PPC_D7 T ? T PPC_L7 ?
PPC_L8 PPC_L8 ? T T ? PPC_D8 T ? T PPC_L8 ?
PPC_L9 PPC_L9 ? T T ? PPC_D9 T ? T PPC_L9 ?
T T JMP
( POINTER TO POINTER COPY CODE TO BE MOVED )
.PPC_D1 SRC
.PPC_D2 NDATA
.PPC_D3 PPC_L4
.PPC_D4 NDATA
.PPC_D5 DST
.PPC_D6 PPC_L7
.PPC_D7 T
.PPC_D8 T
.PPC_D9 RTN
JMP:
( CALL POINTER TO POINTER COPY WITH DATA COPY )
SRC SRC ? ; SET SOURCE ADDRESS
T T ?
ADDR1 T ? ; ADDR1 IS LOCAL
T SRC ?
DST DST ? ; SET DESTINATION ADDRESS
T T ?
ADDR2 T ? ; ADDR2 IS LOCAL
T DST ?
RTN RTN ? ; SET RETURN ADDRESS
T T ?
RETURN T ? ; RETURN IS LOCAL
T RTN ?
T T PPC ; JUMP TO POINTER TO POINTER COPY
DATA DATA RETURN: ? ; RETURN ADDRESS
NDATA DATA ? ; SAVE COPY IN LOCAL DATA
This seems to complete self modifying code as DATA=[ADDR] and [ADDR]=DATA can be generated with PPC (Pointer to Pointer Copy) and existing assembler tools (i.e. getting the address of the DATA variable).
AlanX
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.