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.
- 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.
- 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.
- 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
- 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.
- 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.)
- 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).
- What is the largest value that can be stored in the
5-bit immediate position? (Remember that this is a
2s complement integer.)
- 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?
- 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.)
- 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.
- What if R0 contained a negative 2s
complement integer?
- 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.
- 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?
- 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).
- 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).
- 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.
- 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]).
- 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).