The PowerPoint
Calling functions
- Translating C to PIC: Functions
- Translating recursive !
- Largely the result of xc32 – uses
$fp
and allocates space on the stack for four save arguments - textbook’s implementation
- CSCI 255 instructor’s implementation – follows Chapter 11 and 14 of MPLAB® XC32 C/C++ Compiler User’s Guide.
- Largely the result of xc32 – uses
Accessing variables
How do functions access variables?
Variables in registers
The first few arguments to a function are stored in
$a0
to $a4
.
The return value is stored in
$v0
(along with $v1
for 64-bit returns).
With the exception of arrays and structures,
most local variables of the functions can be stored in the
ten caller saved temporary registers,
$t0
to $t9
.
Variables on the stack
The automatic
(local) variables of C that can’t
be fit into registered, will be stored on the stack.
At compilation time, automatic variables are allocated registers
or space within a function’s stack frame.
Variables on the stack
will be addressed at a fixed offsets from either the stack or
frame pointer.
These means that a variable that is allocated at address
X bytes from the stack pointer, will be loaded
with an instruction similar to the following:
lw $tv,X($sp)
All local arrays of a function must be stored on the stack.
Suppose, the base of an array starts
X bytes from the stack pointer. In that case, the
address of the array can be loaded into register with an
instruction similar to the following:
addi $ta,$sp,X
Think about it.
Variables in the data area
Global variables are stored in the data area of the program’s memory. In general, the address of a global variable cannot be determined at compile time. In this case, the object code contains relocation information that specifies the name and type of global variables and the locations of instructions that reference global variables.
On the PIC32, the location of global variables can be determined
when the object modules are joined together to form the executable
at link time.
Let’s say that an assembly program writes the following statement:
lw $tv,X
where X
is an integer.
Now suppose the linker has determined that X
will be
stored at memory location 0xA0BEEF44
. Then the lw
will be implemented as a two instruction sequence:
lui $tv,0xA0BE
lw $tv,0xEF44($tv)
If you wish to load the address of X
,
that is, to implement
la $tv,X
Then the following two instruction sequence is used:
lui $tv,0xA0BE
ori $tv,$tv,0xEF44
An optimization
To save an instruction, the compiler and linker will conspire to allocate
small data items in the ”small“ region, also known
as .sdata
and .sbss
, no more than 64 KB in size.
At run time (also known as
execution time), the global pointer $gp
is
initialized to an address near the middle of the small data region.
At link time each
variable stored in the small data area is associated with an offset
from the global pointer.
Now small global data can be addressed with a fixed offset from a
the global pointer very similar to how automatic variables are
addressed at fixed offsets from the stack or frame pointer.
In case of dynamic libraries
The Global Offset Table (GOT) is often used with dynamic libraries because the address of a global will not be known until load time. In these situations, a unique Global Offset Table, containing the address of each global variable is associated with each function and populated when the program is loaded in memory. The GOT is effectively a collection of pointers to a function’s global variables.