L09 [Assembly Programming] - Skyline-9/CS2110-Notes GitHub Wiki
L09 [Assembly Programming]
What can you do with ADD, AND and NOT?
Enough to be Turing Complete!
- Add
- And
- Not
- Subtract
- Or
- Clear a register
- Copy from one register to another
- Increment a register by n,
-16 <= n <= 15
How do you copy one register from another?
- Example: you want to copy R5 to R1
Do we load R5 into R1? NO! Load doesn't copy a register from a register
Subtraction
;SUB R1, R2, R3 ;instruction does not exist
; how to subtract
NOT R3, R3 ;flip the bits of R3
ADD R3, R3, #1 ;add 1 to R3 ;now R3 is -R3
ADD R1, R2, R3
Or
;OR R1, R2, R3 ;does not exist: R1=R2 | R3
; how to do OR ;use DeMorgan’s Law
NOT R2, R2 ;R2 = ~R2
NOT R3, R3 ;R3 = ~R3
AND R1, R2, R3 ;R1 = ~R2 & ~R3
NOT R1, R1 ;R1 = ~(~R2 & ~R3)
Clear
;CLR R1 ;e.g. set R1 = 0
AND R1, R1, #0 ;R1 = R1 & 0
;anything and zero is zero
Move
;MOV R1, R2 ;e.g. R1 = R2
ADD R1, R2, #0 ;R1 = R2+0; R1 = R2
What can we do with a BR?
- If then else
- For
- While
- Else
- Do while
- Conditional Branch
- Unconditional Branch (BRNZP or BR)
- Ex: end of a while loop
- Never branch (NOP)
What can we do with a JMP?
- What can we do with a JMP?
- GOTO
- Branch very long distances
- Rarely use JMP
How do we do IF using a BR (branch)?
- First do an operation to set the condition codes
- Then BR with the appropriate combination of NZP conditions in the instruction
- Every comparison in assembly is a comparison with 0 (e.g. A < B becomes A - B < 0)
Attendance Quiz Solutions [9/30/2021
- What does this assembly directive do?
C .blkw 20
Sets C to the current address and reserves 20 words of memory starting at C
- The assembly symbol table is
Created during the first pass of assembly
Recitation Notes
LC-3 Components (a quick review!)
What does the IR hold?
- The value of the current instruction
How do you execute an instruction?
Stages
- Fetch
- Decode
- Execute
What happens you do fetch?
- Use PC value (address of next instruction) to read the next instruction from memory
- Load this value into the IR so that it can be decoded and executed later
- Increment the value of PC
More specifically, you would
- Set PCMUX to +1
- Turn on LD.PC
- Turn on gatePC
- Trn on LD.MAR to read into MAR
- The +1 can happen in any of the FETCH cycles
Sample question: How would you increment the PC during the FETCH cycle?
- Turn on LD.PC and set PCMUX to +1
The macrostates are like Fetch, and the individual clock cycles are called microstates
What happens during decode?
- Now that the IR contains the instruction, the FSM can read the opcode
- If the instruction is BR (branch), the FSM will also check the condition codes to ensure that the branching condition is met
- The FSM will change to a specific state depending on the opcode. This takes a clock cycle in the LC-3, but some computers can combine DECODE with the last cycle of FETCH.
Other Notes About Tracing
What does LD do?
Specifically, LD has to take some address, take the value at that address, and then put that value into the register specified.
Effective address = PC* + PCOffset9 where PC* = PC + 1 and PCOffset9 is SEXT(IR[8:0])
What does LDI do?
The first address for LDI is the same for LDI as LD, but you take the value you first read and then push it back into the MAR
What does LDR do?
Effective address = Base Register + offset6
What does LEA do?
LEA = load effective address
- Only takes one clock cycle
- Calculate effective address and put it straight into Register because you don't have to read memory
For all the ones where you need to update the register, you need to set LD.CC except for LEA
- This allows you to do branching instructions
What stores the list of upcoming instructions?
- Memory
What calculates the list of effective addresses?
- The entire left half of the LC-3 (see diagram)
How many LC-3 instructions set the condition codes?
- Just count the ones with DR (both the ADDs count as one, same for the similar ones)
- 6 instructions set the condition codes
What happens when there is a branch instruction?
The branch instruction has these NZP bits (which match up with the NZP in our condition code)
Example, if we have if x > 0
- We just check if x is positive
We can reduce many problems to just that – ex: if x > y
- Check
x - y > 0
First, NZP are compared with the condition codes. Now, we have to jump somewhere. Where to jump? We calculate the effective address using PCOffset9
Fun fact: BRNZP is equivalent to BR.
What happens if we have all 0's?
You get what is called NOP (or no op). Basically, this tells the LC-3 to do nothing for a cycle.
We get to use reference sheet on our demos! ^_^
Assembly
Labels
- Some LC- 3 instructions use the PC-relative addressing mode for operands
- These accept labels as a second parameter, allowing programmers to load from labeled memory addresses
- Labels are not stored anywhere in memory. Instead, the assembler calculates the right numerical offset to get to the desired label
- To calculate the offset yourself, find the difference between the memory address of the label and the incremented address of the instruction (which will be the value stored in the PC when it executes)
When you do branch, you could count the lines of code and branch that way, but that's dumb. Instead, we use labels.
Friendly reminder: these addresses are in hex, so x10 is actually 16.
LC-3 Assembly “Pseudo-Ops”
.orig
- Stands for "Origin"
- Tells assembler to put block of code at desired address
.orig x3000
- You can have multiple origs
.end
- Denotes the end of block, closing tag for orig
.fill
- Puts value in memory location
.blkw
- Allocates memory for specified label
.stringz
- Assembler will put a string of characters in memory followed by ‘\0’
- Will allocate length of string + 1 for the null character
Random Notes
- Why did we learn DeMorgan's Law?
- The LC-3 actually does not have an OR operation!
- We have to negate it with DeMorgan's Law everytime
Tips for writing assembly
Don't try writing assembly natively from scratch! Instead, write pseudo-code like
short Mem[65536];
int S = 0;
int M = x3100;
int C = 12;
while (C > 0) {
S = S + Mem[M];
C = C - 1;
M = M + 1;
}
and then translate line by line into assembly. This way, we might not have the most efficient program, but we can have what's important – having correct code!