This lab has you convert a C program that performs 8/16-bit unsigned operations into PIC24 assembly language.
Download the ZIP archive which contains the lab files. It is located in Canvas > Files > Labs S2025 > Lab 3, and is called lab3.zip. Extract it directly into C:\ece3724. You should now have a folder called C:\ece3724\lab3.
Inside this folder, there are three different exercises, called case1, case2, and case3. You only need to complete one of these. There is also an example exercise that's already been completed.
If you are in lab section...
07 or 05 then you will be doing case1.
03 or 06, then you will be doing case2.
04, then you will be doing case3.
Be sure you do the correct case or you won't get credit for the lab.
For each case, there's a folder containing MPLAB files, an assembly file for you to complete (case#.s), and a C file (case#_check.c) which contains the C code you'll be translating and also automatically checks your results.
The C code is just a series of arbitrary computations, similar to netid.s, but with branching. For instance, from example_check.c:
if (u16_b & 0x0100) {
u16_a = u16_b + u8_c;
u16_b = u16_a - u16_b;
}
else {
u16_b = u16_a - u16_b;
u16_a = ~u16_b;
}
u8_c = u8_c + 0x5;
u8_e++;
}
These computations will run in a loop for 100 iterations. The computations are not meaningful in themselves; we are only interested in the variable values that are produced on each iteration.
The assembly code you write (in case#.s) must perform the same computations. The assembly language program is a loop that calls a C function named check to compare the variables in your assembly language program with the correct variable values during each loop iteration. The check function implements the same C code that you are supposed to implement in your assembly language file and tests whether you've done it correctly.
Your task is to manually convert the C code fragments in the comments of your case#.s file to PIC24 assembly language. Once you have implemented the assembly code correctly, the messages printed out by the check function will say PASS instead of FAIL. To complete the lab, you need to get 100 passes.
Part 1 of the PIC24 Assembly Primer covers the assembly programming knowledge you will need to complete this lab.
Sections 1.3.4 - 1.3.6 of the ebook will also be helpful.
In this and subsequent labs, when the directions tell you to run a project, they mean to execute it by using "Debug" in MPLab (Debug > Debug Project). The term "debugging" will be used in the conventional sense of "removing bugs, aka fixing".
Load the example project, example.X. Run it. Stop execution (Debug ->Finish Debugger Session). Examine the output in the UART 1 Output tab. You should see something like this:
100 passes. (It starts from 0; 0x63 = 99)
If you do not have a UART 1 Output tab, or it's empty, follow the directions on the Troubleshooting page under Missing / Empty UART tab. If you still cannot see it, contact a TA. You need this to be able to perform the prelab.
Clear the UART 1 Output tab (right-click > Clear, or Ctrl-L).
Close the example.X project (and any other projects you may have open). Open your case project. When you run it, you'll see something like this in the UART tab:
The FAILS are because you haven't written the assembly code that computes the new variable values yet.
Read the "Basics" section if you have not already done so. If you are having a problem with MPLAB and can't run your case project, it is your responsibility to contact a TA and get it resolved before coming to lab. Otherwise, you will not get your prelab points.
Complete the program header with your name, date, and section number.
There are three parts of the program labeled PRELAB that you must complete.
Declare your variables:
2. Initialize your variables:
Variable initialization from example.s. Do not copy these exact numbers or variable names, use the ones in your case program!
3. Move your variables into registers so that the C check function can test them:
They go in the blue area. Leave _u8_e on top. Do _u8_d next.
Clear your UART window (get in the habit of doing this or you could be passing tests and not knowing it). Debug your program. You should have one PASS:
If you don't have a PASS, or the program now has errors:
Check that you're using # for literals.
Check that you're doing mov.b for 8-bit variables and using WREG properly.
For #3, make sure you put _u8_d into its register (W3) right after _u8_e. Otherwise you might be overwriting _u16_a, which is supposed to be in W0.
Check that you are putting the right numbers into your variables.
Your program gets at least one PASS. (20)
Now for the meat of the task, translating the code to assembly.
You have to use register assignments. This is a requirement of the lab.
You have to sort your code into Input/Process/Output. This is a requirement of the lab.
You have to move the variables into registers during the Input phase. You have to move the registers to variables (or branch) during the Output phase. This is a requirement of the lab.
For example, this is approximately how the beginning of your code should look. You would then need an ELSE1 label. Notice the lack of a pointless bra NZ, IFBODY line. (And you won't need an IFBODY label either.)
You can add extra comments if it helps you keep things straight, but they are not required. If you do not have register assignments and/or are making a big mess of your code, the TA will not help you debug it.
Run your code after writing each fragment. Don't worry about if it passes or not, just make sure it runs. Do not write your entire program and then discover that you have a syntax error but don't know where you went wrong.
You may not ‘optimize’ away any statements – you are to implement the code exactly as shown.
For every code fragment, move the variables into registers during the Input phase. Do not count on values you need still being in registers from some previous part of the code!
Be careful of mixed unsigned 8-bit and 16-bit operations -- be sure to zero-extend the 8-bit value, when indicated by (uint16_t):
; W0
;; (uint16_t) _u8_a
ze W0, W0
Don't forget about branching after you do an IF - otherwise you'll do the ELSE too!
Do 8 bit operations with .b, and remember to use WREG when you are supposed to.
Do not use registers W8-15. Use only registers W0-W7.
Don't get carried away with labels. You only need three. You do not need one to jump to the beginning of the program. You will need one before the last code fragment you translate:
HINT: If you put your labels all the way to the left, they'll be easier to find.
Once you have all your assembly written, and gotten your program to build without errors, now is the time to examine the UART Output Window. Probably you're seeing a lot of FAIL. This is normal. No student has ever gotten it exactly right their first time around. A major point of the lab is that you are able to debug your program yourself without immediately flagging down a TA for help.
Double check that you've got at least one PASS and that e is correct for all 10 iterations. _u8_e should always be correct, that is, e=e1 for every iteration. If you ever notice that this is not the case, it means you've changed something you shouldn't have (probably at the bottom of the program).
If you only pass that first test and all your values besides e are wrong after the first iteration, you probably branched wrong:
Set a breakpoint in your case#_check.c program on the first line after "Execute body of loop" (which should be an if-statement).
Debug and step through the code (F8), watching which lines execute and which branches the C code takes.
Continue pressing F8. Your assembly code should be taking the same branches. If not, fix it. A very common mistake is to forget to jump to the END/ENDIF (or whatever you called your label to the code right before _u8_e increments) and running both branches of an if/else.
If you pass a few tests and then start to fail, see which variables are wrong on the first FAIL.
Check the branches that alter those variables and look there for errors.
If you can't find any, you probably are going into one of those branches by mistake. Check and recheck your conditionals.
You can keep an eye on the Watches window while you debug.
You can also try inserting printf statements into the C code to see where you are supposed to be branching and what the values should be at this point in the program.
Once you pass 10 iterations, you're almost done! Set NUM_LOOPS to 100 and debug again. If you still get all passes, take a screenshot of your UART1 tab (be sure to show e1:63 PASS in the screenshot as well as a few lines preceding it), raise your hand, and a TA will come check you off (unless you're doing the lab at home).
You show the TA something like this for your assigned case:
FINALLY
Once you've been checked off:
Change NUM_LOOPS to 99.
Set watches for your variables (you don't need registers)
Set a breakpoint near the end of your case#.s file, on the line "bra GEU, do_end"
4. Run and get a screenshot of your watched variables. They should contain the same values as in the last iteration of your program from the previous screenshot.
Shrink your Watches window columns and make sure the variables display the correct sizes (1 or 2 bytes)
See Lab Policy Summary for formatting guidance and a sample report.
The title page should contain the following: Lab name & number, your name & NetID, and course & lab section on successive lines.
Second page should begin with a brief description of the overall lab activity, intelligible to an outside reader. Write a few sentences about what you did in the lab so that an outside reader could understand, e.g. "I translated the following C code into PIC24 assembly..." not "I did case3.s"
Copy/paste the C code you translated (using a monospace font like Courier New) or include a screenshot of it in the report. Do not include your assembly code in the report.
Include the screenshots of your UART window and your variables. Write what it is that you are showing the reader. Be sure that you are actually showing it (you have the last few lines of passes, and the variable values match)!
Look over your report and be sure:
It has a neat, professional appearance (Legible screenshots, no blank pages, spelled your name right, etc).
It includes the aforementioned text.
It includes the required 2-3 screenshots, but not extraneous ones (like screenshots of your entire case#.s file).
Tidy your code so there are not blank lines and random indentations everywhere:
F
Check that your code:
Has the heading filled out with your name and etc.
Has (correct) register assigments.
Uses the Input, Process, Output method correctly.
Does not have any ;Replace this line with your register assigments.
Still gets 100 passes - if you submit non-working code, expect a penalty of up to 60 points.
If you do not successfully complete a task and your report fails to mention or glosses over this fact, you will receive a zero for the report portion of your grade as well as for the task. If you attempt to deceive the grader, e.g. by including screenshots not generated by the code you submitted, your instructor will be notified and you will be recommended for an Honor Code violation. Do not mess with the code in case#_check.c to get passes. Do not submit screenshots from example.s. Do not steal screenshots from the lab directions. Do not use code from previous semesters. Do not attempt any other malfeasance: You will get caught, and it is not worth it. Just ask for help.
The report is worth 20 points for neatly and coherently presenting your information to a reader. The following non-exhaustive list of errors will result in losing credit from the report portion of the lab grade:
bad screenshots (not cropped properly, blurry, too small)
text is "lab jargon" unintelligible to an outside reader ("I did case2 and got 100 passes.")
text is phrased as instructions to a second party ("Student must complete assembly translation!")
text is copy-pasted from the lab directions rather than using your own words.
text is a literal recap of the activities you performed rather than communicating your results and understanding ("Well, I started out getting only one pass, and then I realized that I needed a label next to the second else. I added this in, along with the appropriate comments and register assignments, and then took a break to get a drink of water...")
blatantly erroneous text ("0x63 = 100")
garbled / confusing / gibberish text ("Sure, I can help you with that! In assembly language written for the PIC24 microprocessor, a MOV command typically...")
using vague or incorrect terminology ("I wrote C code to preform addition and ran it in modelsim.")
excessive text
careless use of pagebreaks that leave blank pages, 1-2 lines of text on a page, etc.
general unprofessional appearance
code is untidy
code is missing header, has wrong header, and/or contains default header
The task is worth 60 points. If your report indicates that you did not successfully complete or do not understand a task, you will lose credit, even if you performed it during the lab. There is one task. The following non-exhaustive list of errors will result in losing credit from the task:
missing screenshot
screenshot of the wrong thing
screenshots show wrong values
cannot read screenshot
code won't run
code performs incorrectly
code doesn't follow lab directions - no/missing/wrong register assignments, no/missing/wrong C code, etc.
Lab reports that flagrantly violate submission policy (wrong lab, no screenshots, no title page, no text besides headings/labels, mostly blank, assembly code pasted into pdf, paragraphs of lab text pasted in, extremely sloppy/unprofessional, missing code etc.) will not be accepted. You will receive a zero for the lab and may resubmit with late penalty.