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.