Self-modifying Code Puzzle, SOLN

First thing to notice is that to alter an instruction requires at 
least 3 instructions for each instruction altered: one to fetch 
the instruction to a data register, another to change it, and a 
third to write it back to memory. Because we will not be using
loops, we will only be able to alter at most 1/3 of our program's
instructions. 

To get started, we need to get the first two instructions into 
data registers, and we need to get the data A and B into data 
registers. Before we can do that, we need to record our program's 
memory location so we can refer to it to do those reads and writes. 
Recall that, when we are writing the code, we do not know 
where the program will be in memory when it is executing.

Next, the data in A is not appropriately layed out so that we can
add it to an instruction and have only the opcode bits affected.
The number in A is a 4-bit number with its lowest-order
bit in A[0]. We need to shift those bits to the left so they 
line-up with the location of an instruction's opcode. So, we 
need to shift them to the left so that they move,

 A[3] to A[15], 
 A[2] to A[14], 
 A[1] to A[13], 
 A[0] to A[12].

To left-shift, we can use this trick,

    ADD R1, R1, R1

Adding a binary number to itself is equivalent to multiplication
by 2, which shifts all the digits to the left, just as
multiplication by 10 will shift all the base-10 digits of a
number to the left one position. (Try it by hand.)
So, we need to add 12 times to shift 12 places to the left.
Of course, the above applies to B as well.

Let's get P's address first. Instruction instr_0 is,

    LEA R1, -1

That puts the memory address, PC-1, into register R1. When it is 
executed, that would be the address of the LEA instruction, i.e.,
the address of instr_0. We now know where we live. 

Next, let's get data A into a register:

    LD R2, -4

The offset is -4 because back -1 from PC gets us to the LD 
instruction, -2 gets us to  LEA instruction, -3 gets us to B, -4 
to A. We could also do this instead:

    LDR, R2, R1, -2

since R1 has the LEA instruction's address. Ok, we are ready to 
load the LEA instruction.

    LDR R3, R1, 0

Ok, so far so good. At this point we have A in R2 and instr_0 in
R3.

Now, we want to do arithmetic on only the opcode field. But I 
suppose A is just a number; so, we need to get A added to only 
the opcode part of the instruction. That requires a bit of 
arithmetic trickery, and we don't really know the LC3's 
instruction set that well at this point, but here's a hint: if
A is simply a number to be added to an opcode, it can't be more than 
four bits (with zeroes in the upper 12 bits). So, we just need to 
shift those four bits leftward until they line up with the opcode 
field (with zeroes in the lower 12 bits). It happens that if you 
add a binary number to itself, the result is that all the bits shift 
left one position (the lowest bit is 0). So, to shift A left 12 
positions, we should add it to itself 12 times. A is in R2. The 
next instructions are,

    ADD R2, R2, R2
    ADD R2, R2, R2
    ADD R2, R2, R2
    ...

The ADD being repeated 12 times. The next task is to add this to 
instr_0.

    ADD R4, R3, R2

We now have the altered instruction in R4. R1 has the memory address
of instr_0. So, we simply move the result into memory using that
address.

    STR R4, R1, 0


We have completed the task for instr_0. Repeat the same code with
minor modifications to alter instr_1.