Day 14
I. Last Time:
Hw #4 - Due Next Time

A. Basic Structure/Syntax of an assembler program:
        1. Comments: # to end of line (like // in C++)
        2. Commands: 1 per line 
        3. Directives:
              Special "notices" to the assembler. 
              Begin with a period (.)
        4. Case: case sensetive to commands

B. 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: )

C. 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

  D. Branching and Control: beq,bne
Normally, we just do one instruction followed
by another, but occasionally we want to make a
"decision" to do something else - going someplace
else is called branching.
(Branching off from our normal path)

MIPS basically has 2 branching insts.
1. We can branch when 2 things are equal: beq
2. We can branch when 2 things are NOT equal: bne

These are I-format insts...
Q. What goes in the I-Data field?
Answer: "displacement"
      
Jumping oddities
          a. Pre-conditions: Jump to AVOID things
          b. Post-Conditions: Jump to do things again

II. New Stuff:   
A. Branching and decisions continued:

       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: <,>,<=,>=


       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)       

        3. 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

C. Other handy pseudo-ops:
move $t0,$t1 # Copy t0=t1
li $t0,1 # Load immediate: t0=1
USE Pseudo-ops: They make the meaning of the
program clearer.
Ex: add $t0,$0,10 vs. li $t0,10

    D. 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"

   E. How does a program do IO/talk to hardware/get memory? OS!
      How does the computer contact the OS? 
      In Many os's through syscalls (There are other mechanisms 
      though like jump gates)

Syscalls - How SPIM simulates an OS for IO and Mem alloc

      1. Exceptions, Interrupts, and dealing with the un-expected
         External Problem/Request - an INTERRUPT
             I.e. an external device has some data ready for the CPU
                  or user software needs something from the OS
         Internal - an EXCEPTION
             I.e. a bad inst., a bad address - an ERROR
         MIPS - Refers to EVERYTHING as an exception.
                Uses a special co-processor (co-pro 0) to deal with
         What happens during an interrupt - Control is transfered
         to a special set of instructions called an Interrupt handler.

         Tricky to write, because they must be bullet proof.

         We'll be using syscalls for IO, mem allocation, and 
         program termination.

      2. How syscalls work:
         See Page A-49
         1. Pick the Function to be performed via v0
         2. Set up any "arguments" needed via a0,a1,and f12
            (a0 and a1 - "Argument" registers. F12 will be used later
         3. Perform syscall - I.e. Tell the OS we're ready for it
         4. Collect/deal with any results. 
            (Ex: integers are returned in v0 - we may need to move
             this results elsewhere so we can get another int)

      3. A simple syscall:
        .data
        mesg_pmt:  .asciiz "Hello World!!!\n"
        .text
        main:
              li $v0,4
              la $a0,mesg_pmt
              syscall
              
              li $v0,10
              syscall

        Misc:
            main - A Label telling of the ADDRESS that the 
                   OS should start executing our program.
            mesg_pmt - An address of initialized data in the 
                   data segment. In this case our message.
            li - Load an immediate value. Pseudo-op for ori.
            la - Load an Address. Pseudo-of for ori and lui.
            Both of these are pseudo ops, and they both do the 
            same thing! - More on this later.
            syscall - Generates a software interrupt/exception. 
                 the OS looks at an exception code to deal 
                 with and performs function specified in v0
                 with args specified by a0,a1, and f12.
                 Then returns to caller.
       4. What WE use syscalls for:
          ALL IO - to screen only. 
              print/read int,string,float
              Terminate program
              allocate memory (sbrk)             

III. Next Time:
A. Continue with ASM
B. MIPS memory segmentation
C. Using SPIM