![]() |
Jupyter at Bryn Mawr College |
|
|
Public notebooks: /services/public/dblank / CS240 Computer Organization / 2015-Fall / Notes |
More abstract, with additional powers:
New: when you write in assembly code, the memory dumps will be disassembled automatically for you. That is, they will be converted from bits to instructions.
BUG: Always provide a LABEL for .BLKW
This is completely up to you! Some like to line up items in columns:
LABEL: OPCODE OPERANDS ; COMMENTS
DIRECTIVE
OPCODE and OPERANDS are mandatory. All spacing is optional, but lines are meaningful.
Colon after the LABEL is optional with the Calysto LC3 Assembler. Develop your own style!
Review, and some new ones:
%bp [clear | SUSPENDHEX] - show, clear, or set breakpoints %cont - continue running %dis [STARTHEX [STOPHEX]] - dump memory as program %dump [STARTHEX [STOPHEX]] - list memory in hex %exe - execute the program %mem HEXLOCATION HEXVALUE - set memory %pc HEXVALUE - set PC %reg REG HEXVALUE - set register REG to HEXVALUE %regs - show registers %reset - reset LC3 to start state %step - execute the next instruction, increment PC %labels - show the labels after first pass
; Example from book, Figure 7.1, page 179
; Program to multiply an integer by the constant 6.
; Before execution, an integer must be stored in
; NUMBER.
.ORIG x3050
LD R1, SIX
LD R2, NUMBER
AND R3, R3, #0 ;; clear R3; will contain product
;; Loop
AGAIN: ADD R3, R3, R2
ADD R1, R1, #-1
BRp AGAIN
HALT
NUMBER: .BLKW 1
SIX: .FILL x0006
.END
; Example from book, Figure 7.1, page 179
; Program to multiply an integer by the constant 6.
; Before execution, an integer must be stored in
; NUMBER.
.ORIG x3050
LD R1, SIX
LD R2, NUMBER
AND R3, R3, #0 ;; clear R3; will contain product
;; Loop
AGAIN: ADD R3, R3, R2
ADD R1, R1, #-1
BRp AGAIN
HALT
NUMBER: .BLKW 1
SIX: .FILL x0006
.END
%mem x3057 x1
%exe
We used to have to figure out PC-offsets by hand, but now the assembler will figure that out for you.
Recall, for something like:
.ORIG x4000
LD R1, SIX
HALT
SIX: .FILL #23
.END
You would have to compute the value for SIX in line 2 manually. No more!
But how would the assembler do this?
The assembler first goes through the source code collecting labels, and their locations. During the second pass, it can substitute the used label in the operands with the label location minus instruction location - 1.
.ORIG x4000
x4000 LD R1, SIX
x4001 HALT
x4002 SIX: .FILL #23
.END
So, the PC-offset for SIX is x4002 - x4000 - 1 = 1. Verify that this is correct.
Warning: you still only have 9 bits to represent the distance between label and instruction!
How far away can the label be?
So, this is ok:
.ORIG x4000
LD R1, SIX
HALT
BLOCK: .BLKW #254
SIX: .FILL #23
.END
%exe
But this is not ok:
.ORIG x4000
LD R1, SIX
HALT
BLOCK: .BLKW #255
SIX: .FILL #23
.END
Lesson: labels have to be within 255 instructions of where they are used.
There is a way around this limitation. What is it?
Will be able to do this:
SIX: .FILL DATA
Bug: But it doesn't work yet.
High-level | LC3 |
---|---|
int a; // simple variable (uninitialized) | a .BLKW 1 ; simple variable (or .FILL 0) |
int b = 2014; // simple initialized variable | b .FILL #2014 ; simple initialized variable |
int c[10]; // array of 10 (uninitialized) | c .BLKW 10 ; array of ten ints (initialized to 0) |
int *d = &e; // address of e | d .FILL e ; store address of e in variable d |
High-level | LC3 |
---|---|
b = a; | LD R0, a ; load from memory to a register |
ST R0, b ; store from register to memory | |
b = a + 1; | LD R0, a ; load from memory to a register |
ADD R0, R0, #1 ; increment value | |
ST R0, b ; store from register to memory |
High-level | LC3 |
---|---|
pa = &a; | LEA R0, a ; get the address of the variable |
ST R0, pa ; store it in the pointer variable | |
b = *pa; | LDI R0, pa ; get the value at the address stored in pa |
ST R0, b ; store it in b | |
*pa = b; | LD R0, b ; load the value of b |
STI R0, pa ; store it at the address stored in pa |
High-level | LC3 |
---|---|
if (a < b) { | LD R0, a ; load a |
// do something | LD R1, b ; load b |
} | NOT R1, R1 ; begin 2's complement of b |
ADD R1, R1, #1 ; R1 now has -b | |
ADD R0, R0, R1 ; R0 = a + (-b) | |
; condition code now set | |
BRzp SKIP ; if false, skip over code | |
; code to do something (the then clause) | |
SKIP ; remainder of code after if |
High-level
if (a < b) {
// do something
}
else {
// do something else
}
LC3
LD R0, a ; load a
LD R1, b ; load b
NOT R1, R1 ; begin 2's complement of b
ADD R1, R1, #1 ; R1 now has -b
ADD R0, R0, R1 ; R0 = a + (-b)
; condition code now set
BRzp ELSE ; if false, skip over code
; code to do something (the then clause)
BR END_ELSE ; don't execute else code
ELSE ; code for else clause here
END_ELSE ; remainder of code after else