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.