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.

#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).
.global isqrt
.global output_string
.global uart_init

and the definitions of each of these functions and any functions they call.

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 first 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: