CST 250 Lab 7 -- Calling Assembly from C and C from
Assembly
Note: You should complete Lab 6 before working on this lab. Once Lab 6 is complete, Lab 7 will not take very long.
Lab
Description
Whenever we call assembly from C or C from assembly we need to pay
extra attention to the calling convention and the stack frame.
Remember that C and assembly functions pass their first four
parameters in a0 -- a3. Also remember that C associates its
function argument list with a0 through a3 in left to right
order. Any C routine calling a function will also allocate
four locations at the bottom of its stack frame reserved for
storage of a0 -- a3, assuming that a0 -- a3 may need to be
preserved by the called function. Any arguments beyond 4 are
assumed to be in the callers stack frame immediately above the a0
-- a3 reservations. Furthermore, any local variables will be
positioned above the arguments area and below the register save
area (for ra, fp and any other s and t registers needed for
preserving live values).
In the first part of this lab, we will have a C program call
assembly routines. In the second part of the lab we will
have an assembly program call a C routine.
Part 1 -- Calling Assembly from C
We will have a C program call the Isqrt function you developed in
the last lab, use a C library function to convert the returned
value to a string and then call the output_string function from
the last lab to output the result in the UART1 Output window.
- Create a new project (i.e.: Lab7p1). Do not use a template
to create the project. Instead, follow the "Starting a New
Project from scratch" instructions in the MPLab Setup document
on the class web page.
- At the "Create a new source file" step, instead of choosing
the Empty File type, select the "new > C Source File"
option. Call the file cfuncs with a .c (lowercase) extension.
- Copy the following into cfuncs.c:
#include <stdio.h>
extern int isqrt(int temp);
extern void
output_string(char* ptr);
extern void uart_init(void);
void main(void)
{
char
mystr[100];
unsigned
int i, j;
uart_init(); // setup uart1 for output
for(i =
1; i <= 200; i++) {
j = isqrt(i);
sprintf(mystr, "The isqrt of
%u is %u. Check: %u^2 = %u, %u^2 = %u\n", i, j, j, j*j, j+1,
(j+1)*(j+1));
output_string(mystr);
}
}
This program uses the
sprintf
(string print formatted) C library function. Its first argument is
a pointer to a string that will contain the result. The second
argument is a format string. For each
%u in the format
string there must be a corresponding unsigned integer argument
following the format string. In this case the first
%u corresponds to
the unsigned integer
i.
Sprintf will convert
i
to an ascii string and insert it in place of the first
%u in the format
string as it copies the format string to the result string.
It does the same for each subsequent
%u. (
%d
is used for signed integers).
- Create a new assembly source file by right clicking on the
"Source Files" section of your project in the Projects window
and selecting New > Other > Other > Empty
File.) In step 2 name the file afuncs.S. It must end in .S (dot
capital-S). You don't need to select a new folder. Click
Finish. This should create and open an empty assembly source
file.
- afuncs.S should include the following:
.global isqrt
.global output_string
.global uart_init
and the definitions of
each of these functions and any functions they call.
- Equate or #define "debug" to 0 (or remove the debug
output statements from the isqrt function) so that isqrt does
not produce any console output.
- Note that you will also need to convert the code that
initializes the uart into a subroutine.
- Remember, there should only be one main function in a
program. Since main is declared and implemented as a C
function, there will be no main in your afuncs.S file.
Part 2 -- Calling C from Assembly
Once you have demonstrated Part 1, start another project (lab7p2)
that contains a complete copy of your original lab 6 assembly
program. Also, create a cfuncs.c file in this project. It will
contain a modified version of the c source code above.
Modify the c source code so that it is now a function that is
responsible only for formatting the final message. It will be
passed two parameters -- the binary value of a number that
we are finding the integer square root of and the output of the
Isqrt routine. The c function should only call sprintf and
output_string and then return. Modify your copied original lab 6
assembly code to call this c function. Thus, assuming we are
finding the integer square root of 253 (and assuming "debug" is
0), the final output of the program will be:
The isqrt of 253 is 15. Check:
15^2 = 225, 16^2 = 256
The isqrt of 253 is 15. Check: 15^2 = 225, 16^2 = 256 (from C)
where the f
irst output line comes from the assembly program
itself, and the
second line comes from the called C function.
Note that, in this part, you
must make sure your
assembly program has space in its stack frame for the C function
to save its passed parameters, as the C compiler will create code
that does this by default (unless we turn on optimization). You
should be able to use the Window > PIC Memory Views > Data
Memory facility to observe the fact that the C function actually
uses this space in the stack frame.
Deliverables:
- Demonstrate each working program and the fact that
the C function in the second program uses the assembly
program's parameter space to the professor.
- Make sure there is an accurate representation of the stack
frame for each function in afuncs.S that uses a stack frame
using a comment block. Include the frame element offsets. This
only needs to be done for functions that use stack frames.
- Make sure the modified lab 6 assembly main routine (from
part 2) has an accurate representation of its modified stack
frame in its comments.
- Turn in a copy of
each of your commented assembly source program (.S) files.
Make sure you save the file before submitting it. (Changes to
the .S file made in the MPLab editor do not get automatically
saved to the file unless you compile the program after you
make changes, explicitly save the file, or close MPLab.)
- Also turn in a pdf printout
of each one of your .S programs. When printing code from
MPLab, I would ask you to please set the print options to
change the default text font size to 12 points monospaced,
turn on line wrapping, turn off the border and set the
set the background color to white. The default header and
footer settings are fine.
- I will actually grade your .S files (after converting it to
pdf myself), but I need you to have submitted pdf files via
canvas so that when I return the graded pdfs, Canvas will have
a place to put them.