Lab 03: LC-3 Introduction

Due 11:59pm Wednesday September 21, 2011

Introduction

In this lab, you will begin to write programs on the LC-3. We will explore the LC-3's instruction set: the complete set of the operations supported by the LC-3. Appendix A (section A.3, p.523) in the text book contains a complete description of the LC-3 instruction set.

The handin33 program will only submit files found in the cs33/lab/03 directory. You will create one file, lab03.txt, which will hold all of your responses.

You are encouraged to work with a partner; however, you may work alone if you choose to do so.

  1. How many unique instructions are in the LC-3 instruction set? Contrast this with the nearly 400 unique instructions supported by the Intel IA64 instruction set, the instruction set used by most new Intel desktop processors, including the Pentium 4, Core 2, Xeon, and Core i3, i5, and i7 processors. Do not print out the 1,643 page instruction set manual! But, while you're thinking about not printing 1,643 pages, mentally note how much more complex that instruction set must be compared to the LC-3's.
  2. Referring again the IA64 instruction set (you know, the one you didn't print), find the reference for the ADD operation (page 107, numbered as 3-35) and read the first two paragraphs of the "Description" on the following page. Then, read the description of the ADC operation (go back to page 103) and read the first three paragraphs of the "Description". Compare and contrast these two instructions with the ADD instruction you supported in your ALU from Lab 2.
  3. A common operation performed in programming is setting a value to zero. The IA64 instruction set includes a MOV instruction that, amongst other things, allows you to move an immediate value into a register. Using MOV, you can initialize a register to the value 0 simply by moving an immediate value of 0 into it.

    The LC-3 does not contain a MOV instruction. Show two ways to perform the assignment R0 = 0. The first way should take 1 instruction; the second way should take 3 or less instructions. For the second way, you may use one register as temporary storage if necessary. Your answer should work regardless of the initial value of R0.

    Your answer should not be LC-3 instructions written in binary, but rather something like R2 = R0 ADD R1, or R3 = NOT R4. You may only use the ALU (arithmetic logic unit) operations AND, ADD, and NOT

  4. The LC-3 and IA64 instruction sets both contain the operations AND, ADD, and NOT. One important instruction from the IA64 instruction set that is excluded from the LC-3 is SAL. The SAL instruction performs a left shift on a register. Read the "Description" of SAL, SAR, SHL and SHR (page 1188, numbered as 4-356). Compare and contrast these four operations to the three shift operations you supported in your ALU implementation from Lab 2.
  5. How would you compute R2 = SAL(R1, 1) on the LC-3? This operation is meant to store the result of shifting R1 one time to the left and storing the result in R2. Do not modify R1. (Again, same format as question 3 using only the ALU operations.)
  6. The LC-3 implements two versions of the ADD instruction. The first adds two 16-bit registers (the first row in Figure A.2 on page 525) and the second adds one 16-bit register to an immediate 5-bit value (the second row).
    1. What is the largest value that can be stored in the 5-bit immediate position? (Remember that this is a 2s complement integer.)
    2. If the 2s complement representation of the number 915 is stored in register R0 and you wish to compute R2 = R1 ADD 915, it is easy to do since we can use the first version of ADD: R2 = R1 ADD R0. But, what if 915 is not stored in a register (or in memory)? Provide a sequence of instructions that compute R2 = R1 ADD 915. You may use other registers as temporary storage, but R1 must not be modified. You may only use ALU operations and your answer should be in the same format as question 3.

      HINT: It may help you if you set R3 to zero.

      CHALLENGE: Including setting R3 to 0, can you complete this in 11 operations or less?

  7. Another instruction supported by the IA64 instruction set but not supported by the LC-3 instruction set is SUB, which performs subtraction. Assuming that the registers R0 and R1 each contain 2s complement integers, how would you compute R2 = R0 SUB R1? Do not modify R0 or R1. (Again, same format as question 3 using only the ALU operations.)
    1. Assume that R0 contains a positive 2s complement integer. Write a sequence of LC-3 statements (same format/only ALU operations) that sets R1 = 1 if R0 is odd, otherwise it sets R1 = 0. You may only use ALU operations.
    2. What if R0 contained a negative 2s complement integer?
  8. Yet another IA64 instruction excluded from the LC-3 is the ROL instruction which performs a left rotate. Left rotating is similar to left shifting (SAL), except that instead of throwing away the leftmost bit and forcing the rightmost bit to 0 (which we do in shifting), we make the rightmost bit equal to the previous leftmost bit. For example, if R0 = 1001 0100 0010 0000, then the after executing R1 = ROL(R0, 1), R1 would store the value 0010 1000 0100 0001.
    1. Convert +23 and -50 to 16-bit 2s complement values and then perform a single left rotate on each of these values. What is the result?
    2. Assume that the LC-3 supported a fictional instruction called SIGN(DR, SR) which did the following:
          if SR >= 0 then
             DR = 0
          else
             DR = 1
      Write a sequence of LC-3 instructions (using the ALU instructions + the SIGN instruction) which performs R1 = ROL(R0).
    3. Write a sequence of statements which stores in R1 the number of 1's in the 4 leftmost bits of R0 (using the ALU instructions + the SIGN instruction).
  9. Sometimes data only requires 8 bits of storage space. Generally, characters (such as the letter 'A') are stored using only 8 bits (1 byte). However, the LC-3 has a word size of 16-bits (2 bytes), which means that if we store a character in a memory location, we end up wasting 1 byte of the memory space per character. On a modern 64-bit processor, we would be wasting 56 bits (7 bytes) for each 1 byte character. That's a lot of waste! To get around this problem, multiple characters can be stored in a single memory location using what is known as packing. Here's how this could work on the 16-bit LC-3: we use the first 8 bits (bits [15:8]) of the 16-bit word to store one character, and we use the second 8 bits (bits [7:0]) to store the next character.
    1. Assuming that R0 contains the ASCII encoding of the letter 'A' and R1 contains the ASCII encoding of the letter 'B', write a sequence of LC-3 statements (using the ALU operations + the SIGN instruction) that packs the contents of R0 and R1 into R2 (with R0 occupying [15:8] and R1 occupying [7:0]).
    2. Assuming that R2 contains two packed bytes (such as the result of performing part a. above), write a sequence of LC-3 statements (using the ALU operations + the SIGN instruction) that unpacks the contents of R2 into R0 and R1 such that bits [15:8] of R2 end up as bits [7:0] in R0 (with bits [15:8] of R0 set to all zeros) and bits [7:0] of R2 end up as bits [7:0] of R1 (again, with bits [15:8] of R1 set to all zeros).