Day 19
I. Last Time:
Hw #5 - Due!
Lab #2 Due
Register for 235 NEXT SEMESTER!!! - Last chance to take it!
(Talk to your advisor!)
A. Segments:
Text - Program Text
Data - Static & Dynamic Data
Static - "exists" for the entire run of prog.
Global Variables, things declared static,
"initializers" and constants.
Dynamic - "allocated" data (new/malloc)
Stack - Local variables and backup space.
Things private to a specific instance of a function.
B. Functions, Callers and Callees:
int main(...)
{ ...
result=calc(data)
}
int calc(...)
{
...
pavg=average(p_data)
...
mavg=average(m_data)
...
}
int average(...)
{
...
}
main is both callee and caller
calc is both callee and caller
average is only a callee (leaf function)
Callee responsibilities:
If any registers other than t and v (s, a, sp, ra)
are used, they should be backuped and restored.
(Backup at begining of function, restore at end)
Caller responsibilities:
If any t or v regs are being used, back them up before call.
(And restore when needed)
Backup to where? The Stack Frame: space private to a
specific instance of a function. I.e. created right
when needed.
It's all about sharing the registers
(these 32 global vars that every program uses)
C. Why the stack:
1. Only require minimum space at a time
2. Re-use space
3. Recursion
Implications - Local variables are un-init &
take on old stack value!
II. New Stuff
A. Pointers vs. Array indexing:
clear1 vs. clear2 (pg 171):
clear1:
void clear1(int array[] int size)
{
int i;
for(i=0;i<size;i++)
array[i]=0;
}
clear2:
void clear2(int *array, int size)
{
int *p;
int *end=array+size;
for(p=array;p<end;p++)
*p=0;
}
Array Version:
...
for_body:
mul $t6, $a2, 4 # Compute Array Index
# Could Use sll $a2,2
addu $t7, $a0, $t6
sw $zero, 0($t7)
addu $a2, $a2, 1 # Add 1 to i
# for loop test
blt $a2, $a1, $for_body
Pointer Version:
...
# a3=4*size+array
for_body:
sw $zero, 0($a2)
addu $a2, $a2, 4 # Add "1" to p
# for loop test:
bltu $a2, $a3, $for_body
Notice that this is MUCH more efficient - No longer need to
re-calculate the memory address for every clear.
Additional Notes:
mul is usually MUCH slower than add because multilication
uses repreated additions.
For each iteration of the loop we save an add and a mult.
B. Call By Value vs. Call be reference
class Employee { ... };
print(Employee emp) vs. print(Employee &emp)
What's the difference?
Multi/Larg Argument Functions
1. C/C++ use a mechanism called
"Pass by Value" by default
(The & operator can be used to specify pass by reference)
Pass by value - Pass the "value" of something.
I.e. make a copy of it and let the function
work with the copy.
Pass by reference - Pass the address of the object.
I.e. let the function work with the actual
object.
What if you want to pass more than 128 bits?
What if you want to return more than 64 bits?
Example Handout/Overhead
Summary/Things We've learned:
Large Static Initializations are done with a "copy" loop
at the begining of the function where they aer declared.
Compilers play some funny tricks to optimize copying data.
These same tricks typically are specific to a single
implementation of the ISA.
Compilers will sometimes add in what looks like unndeeded
branches, but these may really be harmless.
Passing (large data) by value is much less efficient than
passing by reference because the entire object must be copied.
Compilers use pointers to help deal with return values.
The return value is written into the caller's stack space
and then copied (by the caller) into it's final destination.
Saving space for a0-a3 in the caller's frame gives us the
ability to completly re-construct large arguments in memory.
C. MIPS Addressing Styles
Addressing refers to identifying a piece of data
which you want to work with. More specifically,
addressing is describing where the data is or what
it is.
1. Register Addressing - The data you want is in a
register. Ex: Add inst - all the elements to add
are in registers.
2. Base/Displacement Addressing - Describing where the
operand is based on a "base" address. Ex: lw
(A base + displacement = true address)
In C an array's name is just used as the base.
The index is used to compute an offset from the
base.
A class instance's name is also a "base" and the
class members are displacements from the base.
3. Immediate Adderssing - The data is immeadiately
available - i.e. it's part of the instruction.
Ex: li, la, etc.
4. PC-Relative Addressing - The desired location is
relative to the current instruction. Ex: Beq/Bne.
5. Pseudo-Direct/Absolutute Addressing - The exact
location is provided. Ex: j is pseudo-absolute.
Absolute in a sense, but dependent on current PC.
Note that some instructions "mix" these.
addi - register and immediate.
III. Next Time:
A. Multi-Dim arrays
B. MIPS floating point
C. More C++ / ASM examples
D. Stack & security concerns.