Instruction Execution - some older exams (e.g. Spring 19) are not case-insensitive.
If you find errors in the past exams or in this review guide, please email me at prl83@msstate.edu.
The table below examines the last sixteen Exam 1s:
Some takeaways:
NSC, Timing, Instruction Execution, and Programming have been on every exam surveyed. Clock Signal only appeared once, in Fall 19.
Assembly programming problems are worth the majority of the points, though they have declined over time. Since Fall 20, they have been an average of 49% of the points. Summer 20 and before, they were 63% of the points. But even in the semester when programming problems were worth the least (43% in Fall 20), they were still more than double the next highest problem category, which has always been Instruction Execution.
Since Summer 2020, there have always been 4 or 5 programming problems. Before that, sometimes there were 6 or 7.
Hopefully you are familiar with the basic operation of the NSC (OUT: print a number; JC: jump conditionally (if LOC = 1); JMP: jump unconditionally). If not, review Lecture Slides 2. The NSC we use in lab (before we modify it) operates like this:
Let's take a look at the NSC question from the Spring 2024 exam:
It begins with a familiar schematic. However, as you can see by the text beneath the diagram, the control logic has been changed. In the schematic above, "control" is a single component, but in Quartus, we used a bunch of logic gates. The effect of these modifications is that the NSC won't work the same way. For example, in the lab, opcode 01 was JC, but on this exam question it will perform JMP.
All of the last sixteen Exam 1s contained an NSC question. They used the following control logic:
* Fall 23, Spring 23, Fall 22, and Spring 19 used the same control logic as Fall 24; the rest were different.
** Summer 18 didn't modify the control logic of the original NSC, it just made the opcode the last two bits of the instruction.
Some observations:
None of the exams required you to know anything about Quartus or Verilog, memorize the schematic of the NSC, or explain how to make modifications to it.
PC_INC is always equal to ~PC_LD. This makes sense - the NSC either has to go to the next address (increment the program counter on an OUT or failed JC) or jump to a different address (load the program counter with the address in the last 4 bits of the instruction).
Counterintuitively, on some exams, JC might jump when LOC = 0. On other exams, the NSC won't perform an OUT unless LOC = 0 (or 1).
All the questions give you the current memory address, LOC, and DOUT, then ask "what is the value of DOUT and the next address to execute after running this instruction?"
You can type DOUT and the next address in decimal or binary, but if you use binary, be sure to prefix it with 0b. You can use as many bits as you want; if the answer is two, "0b10", "0b0010", "2", or "0b00000000000000010" would be correct, but "10" or "0010" would be wrong. ("02" would also be wrong for some reason.)
We'll go over how to solve the Spring 24 exam questions, though the same method works for all of them. Here's the control logic:
PC_LD = (~OP[1] & OP[0]) | (LOC & OP[1] & ~OP[0])
PC_INC = ~PC_LD
OUT_LD = OP[1] & OP[0]
If we spend a few minutes making a truth table, it will save a lot of work on each of the following questions and reduce the chance of making errors, since we won't have to keep scrolling up to look at the problem or solve equations over and over.
1. Make a blank truth table like this:
2. OUT_LD occurs when OP[1] and OP[0] are both true. This is when the NSC will change the output. Fill in the truth table accordingly:
3. Next, examine PC_LD. The control logic is an OR statement.
a. PC_LD is high when OP[1] is false and OP[0] is true...
b. ...or when OP[1] is true and OP[0] is false and LOC is true:
4. Finally, PC_INC is true whenever PC_LD is false:
Now that we have our truth table, answering the questions is a piece of cake:
If the current address is 0, LOC = 1, and DOUT = 0b0101, what is the value of DOUT and the next address to execute after running this instruction?
The machine code at address 0 is 10_0100. The opcode is the first two bits, 10. LOC is 1:
Thus the DOUT will be unchanged, and the next address will be the last four bits of the instruction:
The following table shows the topics that have been covered on past Exam 1s:
Division has only appeared twice, the last time in spring 21.
Since the programming problems are such a large proportion of exam grades, they're given their own section here.
The highlighted topics, involving signed and 32-bit variables, are more advanced. They most frequently make it onto Exam 1 during summer offerings of the course, which have an accelerated pace. Ask your professor if they will be on the test. If so, they are discussed in Part 2 of the PIC24 Assembly Primer.
This topic is fairly easy, but there are two things to watch out for which could cause you to lose points even if you understand the subject:
Prefix binary numbers with 0b
Bits are numbered like this: 76543210
The following table tells you all the information you need about bitwise operations. I suggest you make it part of your cheatsheet.
Assume there is a 8-bit value u8_x. If we want to set bit #0, bit #3, and bit #5 of u8_x while making the rest of bits in u8_x remain unchanged, which bitewise operation should be used (answer AND, OR, or XOR)?
Since we want to set bits, the above table tells us that the answer is OR. (IOR in PIC24 assembly)
What 8-bit binary value should be used with the above bitwise operation?
The table shows that we set bits with 1s:
76543210
--1-1--1
And 0s keeps them unchanged:
76543210
00101001
Don't forget 0b, so our answer is: 0b00101001
This was a very easy topic only found in one Exam 1, and only worth 4 points.
Given the clock signal above, how long is the clock period (in μs)?
The period is the time for one complete cycle, i.e. both the "up part" and the "down part". So the answer is 4.
Given the clock signal above, calculate the clock frequency (in MHz). For reference, 1 MHz has a period = 1 μs = 1000 ns. 1 μs = 10-6 s, 1 ns = 10-9 s, 1 MHz = 106 Hz.
If you remember the formula frequency = 1/period, you could plug in and do 1/(4x10-6) = 250,000 = 0.25 x 10-6 = 0.25 MHz.
Or you could just figure that since longer period (slower) = lower frequency, a period of 4 us is 4x as long as 1 us, so the frequency has to be 4x lower and 1/4 = 0.25.
These questions appear on every Exam 1. There are two types. The first, about clock frequency, are very easy. You need to know two things for them:
One instruction cycle = Two clock cycles. (This was literally a question at least one Exam 1.)
1 / ____ MHz = period (us)
(Alternately, replace with 1 / GHz = (ns) and 1/ kHz = (ms), but all of the previous exam questions have dealt with MHz)
Assume the clock frequency of a PIC microcontroller is Fosc = 4 MHz. How long does it take to execute 20 instructions?Assume each instruction needs only one instruction cycle. The time unit of your answer needs to be microsecond (us).
1 / 4 MHZ = _____ us
So a clock cycle takes 0.25 us. An instruction cycle is 2 clock cycles, so 20 x 2 x 0.25 us = 10 us.
The other type of question gives you some assembly code and asks you how many instruction cycles it takes. (If it asks you how many clock cycles it takes, just multiply by two; sometimes it's the exact same code.)
For these questions, you have to know a few other things:
3a. BRA - takes four instruction cycles if branch taken, one if not.
3b. repeat #17 - takes 1
div.u - takes 18
3c. Everything else, MOV, ADD, SUB, INC, LSR etc. that you will see on Exam 1 - takes 1.
4a. ADD, CP, INC, SUB, and DEC (and other commands, see Instruction Execution, below) all can affect the zero flag, potentially causing branches to be taken.
4b. MOV(.b) f, WREG and MOV(.b) f affect the zero flag. (f is a variable like u16_a.) Other kinds of MOV do not.
Although you don't have to know very much to answer them, you do have to be careful - if you're off by 1, you'll get the question just as wrong as if you typed cheese into the answer box. I got the first nine that I tried wrong because I was rushing. DO NOT RUSH. In fact, for these and several types of problems from Exam 3, I recommend solving the question once, doing some other questions, and then coming back to it and starting over from scratch. Make sure your two answers match. Do not just "check over your work," since you'll likely fail to catch the error that previously eluded you.
The best way to solve these problems is by making three columns, one for the line number, one for how many instruction cycles it takes, and one to write down values that change, which are often used to decide if a branch is taken. I will also put comments in mine; you can too if it helps you keep things straight.
line #inst values
1 1 w0 = 3
2 1 w1 = 2
3 1 u16_a = 2
4 1 w1 = 5 // labels don't count for any instructions
5 1 u16_a = 1
6 1 // dec affects the Z flag, but since u16_a - 1 was not zero, we don't take the Z branch
7 4 // we DO take the NZ branch, so it's 4 instruction cycles
4 1 w1 = 8
5 1 u16_a = 0
6 4 // this time around, we DO take the Z branch
8 1 // not going to bother writing down values because the program's over
total: 17 instruction cycles. (If the question asked for clock cycles, it would be 34.)
This type of question appears on every Exam 1, and is worth the second most points. You are given a list of memory addresses and registers, along with their contents. Each question is an assembly language instruction, and you have to give:
what memory loc/register is changed (address)
what the new value is (data)
what happens with the Zero flag (Z bit)
what happens with the Carry flag (C bit)
Here's a look at the last 16 exams. Duplicated types of instructions are in (the same) color:
Here are the answers to all the Exam 1 Instruction Execution problems since Summer 2018:
se - sign extend, is unlikely to be on your Exam 1
While you could copy this entire table into your cheatsheet, it would be much better to practice solving previous exams and learn the following general rules:
1a. If W0 is modified, calling it WREG still gets you credit and vice versa. Additionally, the answer is not case-sensitive, so "wreg", "w0", and "wREg" are all accepted.
1b. 8-bit variables on the left are stored in an odd memory address. But on exams you give the even address from the chart that contains both 8-bit variables.
So here, if something happens to u8_c, the address that's modified is 0x1002.
2a. An 8-bit operation to the right u8 variable affects the LSB (the right 2 digits) of the data.
inc.b _u8_b ; makes 0x4801 -> 0x4802
2c. An 8-bit operation to the left u8 variable affects the MSB (the left 2 digits) of the data.
inc.b _u8_c ; makes 0x4801 -> 0x4901
(3 and 4 are not case-sensitive and can be answered T, t, F, f, X, or x.)
3a. Most instructions that you have learned affect the Zero flag (Z bit). Instructions that do not affect the Zero flag:
bra (never been tested on these questions)
call / rcall (never been tested on these questions)
mul.uu (never been tested on these questions)
repeat (neverbeen tested on these questions)
mov instructions except mov(.b) f, WREG and mov(.b) f which do affect the Zero flag. NB: mov(.b) WREG, f is a different command and doesn't affect the Zero flag. (These have been tested and this might be something to write in your cheatsheet!)
mov W1, W2 ; does not affect Zero flag
mov.b _u8_a, WREG ; affects the Zero flag
mov _u16_a, W0 ; does not affect Zero flag
mov.b WREG, _u8_a ; does not affect Zero flag
3b. If the instruction does not affect the Zero flag, the answer is X (again, case-insensitive).
3c. If if does affect the Zero flag, if it makes the destination = 0, the answer is T, otherwise it's false.
3d. If the destination is a single byte, then making that byte 0x00 will set the zero flag. For example:
Here we move the 0x00 part of 0x7800 to WREG (W0) and overwrite its LSB. So although WREG is not now 0x0000 (it is 0xA400), the zero flag is set.
4a. The following instructions do not affect the Carry flag (C bit) so the answer is X: (and, bra, r/call, clr, com, ior, all forms of mov, mul.uu, repeat, xor)
4b. Addition-type operations - includes inc and inc2: Carry flag is set if the addition "wraps around". So 0xFFF0 + 0x0020 = 0x0010 SETS the carry flag (T), as does 0xFFFF + 0x0001 = 0x0000 (which also sets the zero flag). If there is no wraparound, the carry flag is CLEARED (F).
4c. Subtraction-type operations - includes dec, dec2, cp, cp0 (compare instructions have never been tested) : Carry flag is SET (T) if the answer does not wrap around, and CLEARED (F) if it does.
0xFFFF - 0xFFFE = 0x0001 // carry flag cleared (F)
0x0001 - 0x0002 = 0xFFFF // carry flag set (T)
4d. ze (zero extension) always sets the carry flag (T).
4e. Bit shifts - Some types of these instructions affect the carry flag and some do not. The kinds that can shift only by a single bit (sl/lsr(.b) f, sl/lsr(.b) f, WREG, and sl/lsr(.b) Ws, Wd) do affect the carry flag. They make the C bit = whatever bit got shifted out. The kinds that can shift multiple bits (sl/lsr Wb, Wns, Wnd and sl/lsr Wb, #lit4, Wnd) do not affect the carry flag. However these instructions have never appeared on this type of question.
Advanced Tip
It sure would make the test easy if instead of having to sit there with a pencil and a piece of scratch paper, trying to figure out what was in W3, you could actually run the code and see for yourself. But unfortunately you cannot open MPLAB mid-exam, because you are confined within the HonorLock browser. However, there is a secret way: Go to any of the programming problems (preferably one you haven't answered yet) and move the values into the registers/variables, then execute the instruction in question. The rcall _print_regs instruction may also come in handy here.
Do your ebook homework. (Fall 2024 - Chapters 1.3.4-1.3.6 and their exercises would also help, although they are not officially listed as topics.)
Read the study guide for each topic before attempting the type of problem. That's why it was created.
Make a rough copy of your cheatsheet as you go along. Just put concepts on it that you are constantly forgetting.
Rough copy, because you'll probably memorize a lot of it before you finish studying.
It's pointless to try to put the entire lecture notes on there.
If you need to write whole assembly language programs in miniscule font, it does not bode well for you.
If you don't bring a cheatsheet, you'd better get 100.
There's very little value in staring at the lecture notes or the ebook when you have actual test questions.
Programming questions are worth about half the test. There are 82 of them to practice. You don't need to do them all, just until they become laughably easy.
If you still have questions, ask a TA. Good luck and God bless!