Day 13
I. Last Time:
Hw #3 DUE!!
Hw #4 - Due Next Week

   A. Memory: lw & sw:
1. Describing Location: Base + Offset
Base in "register" offset is how "far"
lw/sw just move 32-bits: No Type

   B. I-Format Instructions - 
         Immeadiate data - Some Data is included in 
         the instructions. Data Manipulation and some 
         control instructions

      Format: 
          6 bits  5 bits 5 bits      16 bits
          op code   rs     rt    Immediate data         

  C. Alignment: MIPS designers designed the machine around
      "aligned" words - lw and sw can ONLY access words that
     are on an address/index that is a multiple of 4.
     Shortcut test: If you're given an address in binary/hex, 
    just check to see if the last 2 digits are 0s.
Ex: 0xACD487A = ...1010 (Bad)
             0xACD487C = ... 1100 (Good)

II. New Stuff:   
   A. Misc. Working with Bytes: lb & sb can be used to 
      load and store bytes in the same way that lw & sw 
      can be used to store words. 
      Differences: No Word Alignment Constraints
                   Loads byte into LOWER byte of reg, rest is 0
                   Stores byte from LOWER byte of reg


     Things that won't work: if $s0=0 and $s1=1:
        lw $s4,0($s1), lw $s4,1($s1), lw $s4,1($s0), etc.

      There are some good reasons for this choice.
      (And it typically doesn't really waste much space)
      We'll see one advantage of this later in the jump instruction

      NOTE: This is only true with WORDS: lw, sw.
            (lb, sb don't have any problems)

B. Basic Structure/Syntax of an assembler program:
       1. A program in a text File
        2. Give Text File to Assembler to convert to Machine Lang. (typ)
           In Our case - The simulator we use (SPIM) also acts as an Assembler

        1. Comments: # to end of line (like // in C++)
           (Don't tell me WHAT you're doing, tell me WHY!)
           We don't have "data types" or relevant variable names 
           in ASM, we even re-use single variables for a lot of 
           different tasks. Good commenting is absolutely vital!!!
        2. Commands: 
              Simple Instructions, 1 per line 
(eol = terminator (like ; in C++))
              Each Inst. has a specific format
              (Like C++ keywords: add, lw, sw, sub, or, etc.)
        3. Directives:
              Special "notices" to the assembler. 
              Begin with a period (.)
              (Similiar to #defines in C++)
        4. Constants: 
              Numbers/characters embedded in the program:
                  Characters: in Quotes: "This is text"
                  Decimal Numbers: Just the number: 45
                  Hex Numbers: Preceeded by a 0x Ex: 0x12AC
                  Labels: Like labels in C/C++ character name 
                          using normal identifier conventions, followed
                          by a colon.  (Ex: default: )
        5. Spacing/Indentation - 1 command per line. 
               Try to make clear.
        6. Case: case sensetive to commands
        7. Register Names: Registers have both a symbolic and a numeric Name
           Numeric name: $<number>
            $0  - $zero - Register[0]
            $1  - $at   - Register[1]
            $2  - $v0   - Register[2]
            //    v1,a0-a3,
            $8  - $t0   - Register[8]
            $9  - $t1   - Register[9]
            ...
            $15 - $t7   - Register[15]
            $16 - $s0   - Register[16]
            $17 - $s1   - Register[17]
            ...
            $23 - $s7   - Register[23]
            $24 - $t8   - Register[24]
            $25 - $t9   - Register[25]
          We'll only work with the "s-registers" today

          Names established to enforce usage conventions so 
          different assembly programmers can work together.
          We'll discuss these usage conventions next week.
          They are established to ensure that modules written
          by different programmers will successfully work 
          together. They are NOT enforced by the hardware but 
          they WILL be enforced by me. 

C. Labels.
A label is a special part of an ASM program that is really
a pointer into memory. I.e. it indicates where something
special is.

We'll use labels for both data and instructions.
Data: Label will indicate where a particular variable/
storage area is located.
Instructions:
Label will indicate where a particualar set of
instructions begins.
     Like labels in C/C++ character name 
        using normal identifier conventions, followed
        by a colon.  (Ex: default: )

D. Immeadiate Instructions:
I-Format instructions are "I"mmeadiate because
one of the pieces of data needed by the instruction
is actually IN the instruction.
(Immeadiately available)

This also allows us to work with "constants":
int a;
a=0; add $t0,$0,$0
a++; addi $t0,$t0,1 # constant 1

  E. Branching and Control: beq,bne
      Branching is used to make decisions in a program:
         If statements, Loops, etc.
         (It's called "branching" because the program "branches"
          off of it's "normal" (sequential) path)

       1. MIPS only has TWO instructions for conditional control
          (This is an oversimplification - really there are 
           more, but we'll only need these 2)
          beq - Branch on equal:
                I-Format
                Compare the RS and RT registers. If there are equal
                jump of I-Data bytes. I-Data is SIGNED!
          bne - Branch on NOT equal
                I-Format
                Compare the RS and RT registers. If there are NOT 
                equal jump of I-Data bytes. I-Data is SIGNED!

       2. Performing Comparison - Often we want to compare two 
          values and jump, so we need another instruction(s)
          to perform the comparison, and the beq/bne insts 
          to do the jump.

          Trick Question: li $zero,100, add $s0,$0,$0. s0?

          We'll also use/abuse register 0, which ALWAYS 
          has a value of 0 - This is why. It's very usefull in 
          comparisons.

          slt/sltu - Store Less Than and Store Less Than Unsigned
          If rs<rt, rd=1, else rd=0
          This instruction stores the "truth value" of the expresion
               rs<rt. 
          We can then use this value with beq/bne and $zero to 
          perform all comparions: <,>,<=,>=

       3. Jumping oddities
          a. Pre-conditions: Jump to AVOID things
          b. Post-Conditions: Jump to do things again

       Example:
           if(s0>s1){...} after_if:
           When do we want to SKIP the block? if S0<=S1
       
           slt possibilities:
               slt t0,s0,s1   if t0=1 then s0<s1  (s1>=s0)
                              if t0=0 then s0>=s1 (s1<=s0)
               slt t0,s1,s0   if t0=1 then s0>s1  (s1<s0)  
                              if t0=0 then s0<=s1 (s1>=s0)
               (== and != are just done with beq/bne)
           So, we want s1,s0 since it's the only way to do 
           a s0<=s1. 

           Which branch do we want?
               The only thing we can compare to is 0.
               beq $t0,$0,after_if

         Remember: slt for signed, sltu for unsigned.
                  (beq/bne work for either signed or unsigned)       

        4. Real Stuff: Using Pseudo-Ops
          As ASM programmers we usually utilize the pseudo-ops
          to make the program readable. There are a very rich 
          variety os pseudo-ops for branching in MIPS,
          beqz,bge,bgeu,bgt,bgtu,ble,bleu,blt,bltu,bnez

          Psuedo-Ops are converted by the assembler. 
          The $at register is reserved for this purpose.
          Test Type Question: What real instructions does
              the instrcution "ble $s0,$s1, after" convert to and what c
              construct is it most similiar to:
              First think of possibilities:
                 slt $at,$s1,$s0 
                     if at=1 -> s1<s0 / s0>s1
                     if at=0 -> s1>=s0 / s0<=s1
              We want to branch on less than
                     slt $at,$s1,$s0
                     beq $at,$0 after


                 after:
               The closest if statement is:
                  if(s0>s1) 
                     {...} 
                  after:
           ble s0,s1,after_if

    F. jumping:
       Relative - a distance (and direction) to go
       Absolute - The REAL address
       beq/bne - A relative jump. The i-data tells how 
                 many bytes the intended destination is 
                 from the current location.
       j - An absolute jump. Gives a specific address 
           to jump to.

       J-Format:
           6-bits      26-Bits
             op     Target Address
       
       Instructions are ALWAYS word aligned - so we know the 
       last 2 bits will always be 0. (Mult by 4 in binary)
       Since we know this, we never store them - the 26 bits 
       we store are bits 27-2.
       (Bits 28-31 come from the current address - so the 
        jump is only pseudo-absolute)
       j 0x1414
       op=2=00 0010b
       Ta = 0001 0100 0001 0100b = 
            (drop 2 lowest bits) 0001 0100 0001 01b
            Append to 26 bits:
            0000 1000 0000 0000 0000 0101 0000 0101b
            =0x08000505

       If we use the assembler, it just uses labels and 
       computes the correct number for us - saves us a lot
       of time and trouble. So we don't have to worry about 
       these details soo much.

       Any change to the program (insert or delete an inst) 
       will prob. require that these addresses be re-computed.
       
       Virtual Memory is usually utilized to make a program 
       "re-locatable"

III. Next Time:
C. Continue with ASM