//****************************************************************************//
//************** More Assembly Instructions- October 3rd, 2017 **************//
//**************************************************************************//

- 2 tests down, 2 A's thus far, but the hardest one hasn't been returned yet...
- Also, checking assembly code is stressful. I thought regular debugging was bad enough, but comparing actual machine code to physical hardware components to see if they match up is entirely new levels of blood-pressure-raising pedantic
    - "Eh, tha there's nothin' compare wi' what us ol' time fellers faced. Yeh see, back in the ol' days, I fought off dem' electrons wi' nothin' but a sauterin' iron an' a copper pipe! Yessir!"
- Also, Prof. Leahy is sorry/not sorry for forgetting to give us a break last time
-----------------------------------------------------------------------

- Today, we'll be going over the CONTROL instructions for the LC-3 ISA. These are what let us do more than just execute instruction x3000, then x3001, then x3002, then...

- The first command is the CONDITIONAL BRANCH (BR)
    - Format: [0000 | n | z | p | pcoffset9]
        - If any of the N, Z, P bits are on, then it'll check it's respective register (N, Z, P) (e.g. if the "n" bit is 1, it'll check to see if there's a 1 stored in the "N" condition code register); if ANY of those registers contain a 1, then it'll change the PC address to the address pointed to by the "pcoffset9"
        - In assembly, we write "BRN" for "check if N is 1", "BRP" for "check if P is 1", and "BRZ" for "check if Z is 1" 
    - To force it to ALWAYS branch, you can do "BRNZP", and make ALL of them 0
        - As a shortcut for this, there's an UNCONDITIONAL BRANCH instruction if we just write "BR"; this'll always change the address (this is how WHILE loops work)
    - If you leave ALL of the "n", "z", "p" fields as 0, then the instruction will never execute and it'll just get skipped over. It becomes a "no-op"; an instruction that doesn't do anything!

- Let's say we have the following Java code:
    "int a[] = {5, 3, 6, 8, 3, 4};
    int total = 0;
    for (int i = 0; i < 6; i++) {
        total = total + a[i];
    }"
    -...how would an assembly programmer think about this?
    - All of the "a" variables and "total" would be saved in memory, since we want them to be persistent later on
        - "i" is just temporary, though, so we'll keep it in R0 as the "loop counter"
        - We'll then keep the current value of "total" in R1, and the current index of a we're looking at ("a[i]") in R2
            - R3 would then be the address of the START of the array, 
        - Now, we do NOT have a function for checking equality...but we DO have a built-in function in the computer for checking if it's 0: the "Z" register!
            - "Even in C or C++, it's slightly more performant to have your arrays count down to 0 and end there; not all compilers will do this optimization for you."
        - So, we want our array counter to start at 6; let's start writing the assembly code

        - The assembly program:
            .ORIG x3000
            AND R0, R0, 0 ;;clears R0; serves as our "i" counter
            ADD R0, R0, 6 ;;this would NOT fit in the instruction if the # is >255, so we could instead declare a symbol "ArraySize .FILL 6", and replace this line with "LDR R0, ArraySize"
            AND R1, R1, 0 ;;stores our "total"
            LEA R3, A ;;stores the starting address in our array
            LoopStart LDR R2, R3, 0 ;;gets the current array element; LoopStart points to it
            ADD R1, R1, R2 ;;adds number to total and stores it in "total"
            ADD R3, R3, 1 ;;moves our "current array element" up
            ADD R0, R0, -1 ;;decrements our counter
            BRP LoopStart ;;AS LONG AS the R0 value is still positive, go back up to our "LoopStart" address! Note that this command is LINKED with the one before it; it's testing the most recently changed register, so the counter HAS to be set right before we test for branching!
            ST R1, Total;; stores our total value in the "Total" address
            HALT

            ;;all our variables
            Total .Fill 0 ;;where we will store our total value after it's calculated
            A .FILL 5 ;;declares the array; if no symbol exists, assembly just puts the value in the current address
            .FILL 3
            .FILL 6
            .FILL 8 
            .FILL 3
            .FILL 4

         - "EVERY good assembly programmer I've seen comments their code; not just with what the line LITERALLY does, but what algorithm it's supposed to be implementing, etc.; WHY the code exists, AND what it's doing"

- SIDE NOTE: You're currently at the level where you think the compiler always gets things right..."HAHAHAHAHAHAHAHAAAAAAAAAAAAAAAAAAAAAAAAA!!!!!"
    - "More immediately relvant to you guys, though, if you've ever programmed in C (and if you haven't, you will in a few weeks), there's an option in the C compiler to print out the assembly your program generates. That could be a good learning tool."

- Now, back to control instructions:
    - The JUMP (JMP) instruction is ALSO a control instruction, although we did go over it earlier
        - Format: [1100 | 000 | BaseR | 000000]
    - This is used because, if you were paying attention, the BR instruction only has 9 bits for the PC offset, so we can ONLY go to addresses that are within -256 or +255 of the current PC address!
        - JMP, since it lets us use the value in a base register, has no such limitations 
    - So, we can use JMP both to do long-distance branching AND to implement GOTO statements
        - Side note: do NOT use GOTO! If you're experienced enough to know when using a GOTO is good, you shouldn't be in this course.

    - The TRAP instruction
        - Basically, modern operating systems have systems to prevent user programs from accidentally (or maliciously) interfering with system functions
            - The details of HOW they do this isn't important in this class, but it's mostly built to prevent accidents, rather than to keep out hard-core hackers
        - The TRAP function gives us a way of communicating with the operating system
            - Format: [1111 | 0000 | trapvect8]
                - So, there's 256 different possible addresses we can access with the TRAP command
            - Examples of common trapvects:
                - x23: IN, stores input from the keyboard in R0
                    - This'll overwrite anything in there, so MAKE SURE the register doesn't have anything important
                - x21: OUT, outputs the character stored in R0 to the monitor
                - x25: HALT, halts the program
            -...there are more of them
                - Also, for convenience, they allow you to call certain TRAP functions using their own keywords without writing it explicitly as a TRAP: HALT, OUT, IN, etc., can be called on their own
        - When the TRAP is executed, a few things happen in order:
            1) Store the PC in R7 (R7 gets overwritten)
            2) Zero-extend trapvect8 (put zeroes in front)
            3) Put that into the MAR
            4) Address now in the MDR
            5) Put the MDR into the PC
    - If your program doesn't have a HALT instruction, the computer will just keep running your code

- NOTE: Tuesday NEXT WEEK (not this week), we don't have class. So remember that.