Discussion 01
ECE 391 – Computer Systems Engineering
ECE 391 TAs
Department of Electrical and Computer Engineering
University of Illinois at Urbana-Champaign
GRAINGER ENGINEERING
Discussion Agenda
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Announcements
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Review: Why Operating Systems?
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Review: Course at a Glance
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Control Flow Instructions
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Quick Exercise: Assembly Writing
ELECTRICAL & COMPUTER ENGINEERING
// Let a1 store x, a2 store y, assume unsigned.
GRAINGER ENGINEERING
Quick Exercise: Assembly Writing
ELECTRICAL & COMPUTER ENGINEERING
// Let a1 store i, a2 store y, assume signed.
GRAINGER ENGINEERING
Conditional Set Instructions
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Unconditional Jumps
ELECTRICAL & COMPUTER ENGINEERING
A) Next PC = Current PC + Offset
B) Next PC = Current PC - Offset
C) Next PC = Offset
GRAINGER ENGINEERING
Quick Exercise: Branches and Jumps
ELECTRICAL & COMPUTER ENGINEERING
if ((x >= 10) && (y < 20)) {
x = y;
}
if (x >= 10) {
if (y < 20) {
x = y;
}
}
GRAINGER ENGINEERING
Quick Review: Branches and Jumps
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Jump and Link
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Function Calls
ELECTRICAL & COMPUTER ENGINEERING
main:
# Prior instructions ...
# Set function argument (x) in a0
addi a0, zero, 2 # Let’s say x = 2
# Call x_squared function
jal ra, x_squared
# ret will return to this following instruction (PC + 4)
next instruction ...
GRAINGER ENGINEERING
JAL and JALR Function Call Example
ELECTRICAL & COMPUTER ENGINEERING
x_squared:
mul a0, a0, a0
ret # jalr x0, ra, 0
main:
# Set function argument (x) in a0
0x8000 addi a0, zero, 2 # Let’s say x = 2
# Call x_squared function
0x8004 jal ra, x_squared # ra = 0x8008
# ret will return to this instruction (8024 + 4)
0x8008 next instruction ...
...
x_squared:
0x8040 mul a0, a0, a0
0x8044 ret # jalr x0, ra, 0 (ra contains 8008)
GRAINGER ENGINEERING
JAL and JALR Function Call Example w/ Instruction Addresses
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Why do we need Calling Conventions?
ELECTRICAL & COMPUTER ENGINEERING
calc_x:
li a1, 4 # a1=4
mul a2, a0, a0 # a2=x^2
mul a0, a1, a2 # a0=4x^2
ret
GRAINGER ENGINEERING
RISC-V Calling Convention
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Calling Convention: Caller-side
ELECTRICAL & COMPUTER ENGINEERING
original position.
GRAINGER ENGINEERING
RISC-V Calling Convention: Caller-side
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Calling Convention: Callee-side
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Calling Convention: Callee-side Example
ELECTRICAL & COMPUTER ENGINEERING
# Prior to function call, the caller has set the arguments in a0-a7 and saved caller-saved registers onto the stack.
# Assume caller’s sp points to 0xECE3918, and fp points to a higher address.
0xECE3910
0xECE3908
0xECE3900
0xECE3920
caller saved regs
0xECE3918
caller saved regs
. . .
. . .
sp
fp
GRAINGER ENGINEERING
RISC-V Calling Convention: Callee-side Example Cont.
ELECTRICAL & COMPUTER ENGINEERING
my_function:
addi sp, sp -16 # Allocate stack space (16 bytes for ra and sp)
sd ra, 8(sp) # Save return address ra onto stack (8 bytes)
sd fp, 0(sp) # Save previous function’s fp onto stack (8 bytes)
addi fp, sp, 16 # Update frame pointer to point to current function’s stack
caller saved regs
caller saved regs
. . .
. . .
fp
0xECE3910
0xECE3908
0xECE3900
0xECE3920
0xECE3918
sp
ra (return addr)
fp (previous fp)
GRAINGER ENGINEERING
RISC-V Calling Convention: Callee-side Example Cont.
ELECTRICAL & COMPUTER ENGINEERING
my_function:
addi sp, sp -16 # Allocate stack space (16 bytes for ra and sp)
sd ra, 8(sp) # Save return address ra onto stack (8 bytes)
sd fp, 0(sp) # Save previous function’s fp onto stack (8 bytes)
addi fp, sp, 16 # Update frame pointer to point to current function’s stack
# Allocate more stack space to save callee-saved registers, if needed
# Allocate more stack space here for local variables, if needed
#### Function Body ####
sp
fp
caller saved regs
caller saved regs
. . .
. . .
0xECE3910
0xECE3908
0xECE3900
0xECE3920
0xECE3918
ra (return addr)
fp (previous fp)
GRAINGER ENGINEERING
RISC-V Calling Convention: Callee-side
ELECTRICAL & COMPUTER ENGINEERING
my_function:
addi sp, sp -16 # Allocate stack space (16 bytes for ra and sp)
sd ra, 8(sp) # Save return address ra onto stack (8 bytes)
sd fp, 0(sp) # Save previous function’s fp onto stack (8 bytes)
addi fp, sp, 16 # Update frame pointer to point to current function’s stack
# Allocate more stack space to save callee-saved registers, if needed
# Allocate more stack space here for local variables, if needed
#### Function Body ####
# De-allocate stack space for local variables, if allocated
# De-allocate stack space for callee-saved registers, if saved
ld fp, 0 (sp) # Restore previous fp
ld ra, 8(sp) # Restore return address ra
addi sp, sp, 16 # Deallocate stack space (the 16 bytes for ra and sp)
ret # Return
GRAINGER ENGINEERING
Memory Addressability
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Quick Quiz: Memory Addressability
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Quick Quiz: Memory Addressability
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Memory Endianness
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Load and Store Instructions
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Load Stores w/ Memory Endianness
ELECTRICAL & COMPUTER ENGINEERING
0x8000
0x8001
0x8002
0x8003
Address
Data
GRAINGER ENGINEERING
Memory Access Instructions
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Stack
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Memory Access Instructions
ELECTRICAL & COMPUTER ENGINEERING
sw a2, 0(a1)
lb a3, 1(a1)
where a2 = 0A0B0C0D and a1 contains a valid memory address.
GRAINGER ENGINEERING
Quick Quiz: Memory Endianness
ELECTRICAL & COMPUTER ENGINEERING
addi a0, zero, 0
addi a2, zero, 10
slli a2, a2, 8
addi a2, a2, 11
slli a2, a2, 8
addi a2, a2, 12
slli a2, a2, 8
addi a2, a2, 13
sw a2, 0(a0)
lb a3, 1(a0)
GRAINGER ENGINEERING
Recap: Memory Endianness
ELECTRICAL & COMPUTER ENGINEERING
Endianness doesn’t matter unless
you are accessing a subset of bytes …
GRAINGER ENGINEERING
Memory Layout of a Program
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
RISC-V Stack
ELECTRICAL & COMPUTER ENGINEERING
addi sp, sp -8 # Allocate stack space (for 8 bytes in this example)
sd a0, 0(sp) # Store data into stack (use sd to store 8 bytes)
ld a0, 0(sp) # Retrieve data from stack (use ld to load 8 bytes)
addi sp, sp, 8 # Deallocate stack space (the 8 bytes we allocated prior)
GRAINGER ENGINEERING
RISC-V Assembly Directives
ELECTRICAL & COMPUTER ENGINEERING
my_var: .word 391 # Allocates 4 bytes, with a value of 391
my_array: .space 80 # Allocates 80 bytes of memory, uninitialized
my_string: .string “Hello” # Allocates a string (6 bytes here)
.align 3 # Address of next symbol (my_array) is 2^3 = 8-byte aligned
my_array: .space 80 # my_array will begin at an 8-byte aligned address
GRAINGER ENGINEERING
RISC-V Assembly Directives Cont.
ELECTRICAL & COMPUTER ENGINEERING
GRAINGER ENGINEERING
Looping over Arrays Example
ELECTRICAL & COMPUTER ENGINEERING
.data
array_a:
.rept 100
.dword 0
.endr
.text
_start:
la t1, array_a # Loads address &a[0] into t1
li t2, 0 # Loads 0 into t2 (iterator i)
li t3, 100 # Loads 100 into t3 (max index)
loop: bge t2, t3, exit # Check if i >= 100
add t4, t1, t2 # Sets address &a[i] in t4
ld a0, 0(t4) # Loads a[i] into a0
addi t2, t2, 1 # i++
j loop
Rudra Section Notepad
if (a < b) {
x = y;
} else {
x = z;
}
// a0 = a
// a1 = b
// a2 = y
// a3 = z
slt t0, a0, a1 # t0 = 1 if a < b else 0
sub t0, x0, t0 # t0 = 0 or -1 (mask = 0x000...0 or 0xFFF...F)
and t2, a2, t0 # t2 = y if mask = -1 else 0
andn t3, a3, t0 # t3 = z if mask = 0 else 0 (andn = a & ~b)
or t1, t2, t3 # x = selected value
// a0 = a
// a1 = b
// a2 = y
// a3 = z
bge a0, a1, else # if a >= b, jump to else
mv t0, a2 # x = y
j done
else:
mv t0, a3 # else: x = z
done:
How do we know score's value persists? What if score is in a caller saved vs. callee saved?
How to pass arguments?
How to get return value?
int add(int a, int b) {
int y = a + b;
return y;
}
int func1() {
ra = lab
int score = 0;
jal ra, add
int x = add(3, 4);
lab2:
if (x == 7) {
score = 1;
}
ret: jalr, x0, ra, 0
}
main() {
func1();
lab:
a0-a7 in registers
high addr:
a11
a10
a9
a8
low addr:
a1 = 0x8000
0x8000: 0D
0x8001: 0C
0x8002: 0B
0x8003: 0A
a3 = 0000000C