Quick Links
Section 1: Modifying the Add Assembly Program
Section 2: An Assembly Level View of a C Program
Section 3: Running an Assembly Program
Files
|
File |
Description |
|
Add assembly program |
For instructions on creating a CodeWarrior project for an assembly program, refer as needed to Lab 1, Section 4 – Assembly Language.
Modify the add assembly language program Lab6_add.asm used in the SKIBLE Getting Started activity so that it uses digital input/output for the operands and result of the addition (instead of the DataSeg block in memory).
LED Bargraph 1 ß DIP Switch 1 + DIP Switch 2
Since the size of the numbers is 8 bits, use the load and store instructions that operate on bytes:
·
lbz, Load Byte and Zero: reads a byte from memory into
a register, and pads the high-order bytes of the register with zeros. For
example:
lbz r31, 0(r2): reads the byte
at Mem[r2+0], places it into the LSB of register r31, and zeros the rest of the
bytes in r31
·
stb, Store Byte: writes the LSB from a register into
memory. For example:
stb r30, 0(r2): writes the LSB
of register r30 to Mem[r2+0]

Make, test, and run your program. Verify its correct operation. Hand in a printout of the program.
Files
|
File |
Description |
|
Simple C program for investigating assembly code in CodeWarrior |
In this part of the lab, you will take a look at the assembly code generated by the CodeWarrior compiler when it compiles a C program.
Step 1 - Create Project
Create a new project and replace the main.c file with the Main1.c file listed above. Use the standard C project. Make sure that the Enable Debugger option is selected from the CodeWarrior menu.
When you are working with CodeWarrior, your C code is compiled to assembly code and then to machine code. CodeWarrior has a special option to allow you to view the assembly code produced by your C code while debugging.
First, execute the code and step inside the Do_Tasks function. Once inside the function, click on the source button to display a short menu list.

Notice the {} option in the corner as well. The braces option shows you the Call Stack (i.e., function A calls function B, calls function C, etc.). The Call Stack can be helpful in determining how you arrived at a function (interrupt, polling, etc.).

Click on the {} item to switch over to main and back to Do_Tasks. As you switch back and forth between the various functions, CodeWarrior will also adapt the local variable list as well to reflect the function that you are in if necessary.
Once you are back in Do_Tasks, switch to the Mixed view. Notice that code for only the Do_Tasks function is presented. In addition to the C code, the final assembly code is also displayed. This is a combination of machine code (32-bit memory addresses and 32-bit instruction words in hex) and assembly code (mnemonics and operands). Notice the code at the beginning of the function before the variables are declared.

This code allocates space on the stack for the stack frame. Remember, items such as return address (in the link register), local variables, and saved registers are placed on the stack. Notice the use of the SP (Stack Pointer) register as an operand in the assembly code. The SP notation is used by CodeWarrior to make the code easier to follow. The PowerPC does not have an explicit SP register. To see more, open up the GPR window from CodeWarrior.
Window à Registers Window à GPR
Step 2 - Viewing Registers
The GPR window opens up a listing of the General Purpose Registers in the processor (r0 to r31).

Notice how r1 is not listed. CodeWarrior uses r1 as the SP register. Thus, in your assembly code, you should avoid using r1 for your programs. You can also change the method used to display the register. Right click on an individual register to change its type.

Step 3 - Stepping Through the Assembly Code
When you are using Mixed or Assembler view, each debugging step will execute a single assembly instruction. Step through the code and watch the GPR window. You may need to shrink the code window in order to view both windows at the same time. Notice how registers that have changed are highlighted in red. The PC (Program Counter) register changes every time and displays where you are at in your program. Is the PC word-aligned?

The value of PC corresponds directly to the memory addresses listed in the first column of the machine code view: compare the PC in the GPR window above, with the memory address of the current instruction in the Mixed code window below. Your debugger windows will probably have different values, but you should make a similar observation.

Notice the first two columns in the code window: each assembly instruction mnemonic is preceded by two 32-bit hex numbers. The first number, e.g., in the top line, 203FA354, is the memory address where that instruction is located. Again, note the similarity between the value of the PC and the memory address. The PC contains the location of the next instruction to be executed. The blue arrow (pointing to the next line to execute) matches exactly the value of the PC. The second number (looking at the top line, 7C0802A6) is the actual instruction word consisting of opcode and operand fields. Since each instruction in the PowerPC is 32 bits long, CodeWarrior can easily translate between raw machine code and assembly code. You will learn more about this later.
Step 4 – Executing the Code
Switch back to the Source view of the code. Read the code and make sure you understand the C code. Switch back to the Mixed view, and step through the code until it finishes running. As the code executes, observe which assembly instructions and registers are used to implement statements in C.
Answer the following questions by inspecting the Mixed code window, and submit the answers with your Lab Evaluation Form.
1. What assembly instructions implement this C assignment statement?
byVal = *pDIPSwitch1;
2.
What assembly instructions implement this C for loop?
for(j=0; j<*pDIPSwitch1; j++)
{ byVal += 1; }
|
File |
Description |
|
Source assembly file for Section 3 |
Step 1 - Create a Project
Create a new assembly project from the project menu. Select Asm+C instead of C. The Asm+C option creates the appropriate linkage from C to assembly for linking the code together. Replace the MainAsm.asm file with the Lab6Asm1.s file. Make sure to click the Enable Debugger option as well from the menu.
Step 2 - Examining the C Linkage
asm
void JumpAsm ()
{
fralloc
bl StartAsm
frfree
blr // Branch to link register location
// i.e. return from function
}
CodeWarrior supports the direct inclusion of assembly into C files. The asm keyword in front of the function is similar to using the asm { } directive in C. Inside of the inline assembly function, it is possible to use PowerPC assembly code.
Step 3 - Examining the Assembly File
Now, open the Lab6Asm1.s file. Assembly files may use either the .s or the .asm file extension in CodeWarrior. Let's take a look at some of the extra information at the beginning of the assembly file.
.export StartAsm
The '.' is the assembly equivalent of the # sign in C. The export directive tells the assembler to export the StartAsm label to other files for linking. Without this directive, the linker would not be able to find our assembly code from main.c.
.include "defines.h"
CodeWarrior allows us to include files. Since defines.h contains only #defines, the assembler does not give us any errors. If the header contained actual C code, the assembler would generate an error. The defines.h is helpful for accessing the I/O ports on the PowerBox. Try including PPC_Support.h to see what happens when C code is included.
.function "Lab6Asm1", PPC_Start_Asm, PPC_End_Asm-PPC_Start_Asm
This directive is used to tell CodeWarrior how to debug the code. Without this, the debugger would simply show us inline assembly without any contextual information. This makes debugging the code much more difficult. The syntax for the function directive is as follows:
.function "FunctionName",
StartAddress, TotalLength
FunctionName - Any unique name
StartAddress - Starting address to include in debugging
TotalLength - Simply subtract the two labels to get the length
.text
The text directive signifies that executable assembly code is to follow. You can also use a .data section to mark a data area and switch back and forth at any time.
Answer the following question by inspecting the Mixed code window, and submit the answer with your Lab Evaluation Form.