Procedures, Stacks, and Mmio: February 25, 2021 MIT 6.004 Spring 2021 L04-1
Procedures, Stacks, and Mmio: February 25, 2021 MIT 6.004 Spring 2021 L04-1
MMIO
x0 Address 31 0
x1 100110....0 0x0
x2 0x4
Holds
0x8
32-bit “words” program
...
0xC
0x10 and data
Program Counter 0x14
x31
32-bit “words”
ALU
Arithmetic Machine language directly
Logic Unit reflects this structure
February 25, 2021 MIT 6.004 Spring 2021 L04-2
Program Counter
§ The PC register keeps track of the address of
your current instruction.
§ For non control-flow instructions, PC ß PC + 4
§ Instructions and data are stored as 32-bit
binary values in memory.
Address 31 0
. = 0x0 blt instr
if x1 < x2: PC ß 0x8 0x0
blt x1, x2, label 0x4 addi instr
else: PC ß PC + 4
addi x1, x1, 1 0x8 xor instr
0xC lw instr
label: xor x2, x1, x1
0x10
lw x3, 0x100(x0) x3 = 0x12345678 0x14
…
. = 0x100 …
0x12345678
.word 0x12345678 0x100
PUSH
sw a1, 0(sp) R[sp] stacked data
§ Pop sequence: stacked data
lw a1, 0(sp) stacked data
stacked data
addi sp, sp, 4
§ Stack contents:
Before call to f During call to f After call to f
unused
space R[sp] Saved s0 Saved s0
Saved s1 Saved s1
R[sp] R[sp]
func:
February 25, 2021 MIT 6.004 Spring 2021 L04-10
Nested Procedures
§ If a procedure calls another procedure, it needs to
save its own return address
§ Remember that ra is caller-saved
§ Example: bool coprimes(int a, int b) {
return gcd(a, b) == 1;
}
coprimes:
addi sp, sp, -4
sw ra, 0(sp)
call gcd // overwrites ra
addi a0, a0, -1
sltiu a0, a0, 1
lw ra, 0(sp)
addi sp, sp, 4
ret // needs original ra
int main() {
int ages[5] =
{23, 4, 6, 81, 16};
int max = maximum(ages, 5);
}
February 25, 2021 MIT 6.004 Spring 2021 L04-13
Passing Complex Data Structures
as Arguments
// Finds maximum element in an
// array with size elements
int maximum(int a[], int size)
{
int max = 0; main: li a0, ages
for (int i = 0; i < size; li a1, 5
i++) { call maximum
if (a[i] > max) { // max returned in a0
max = a[i];
} ages: 23
} 4
return max; 6
} 81
16
int main() {
int ages[5] =
{23, 4, 6, 81, 16};
int max = maximum(ages, 5);
}
February 25, 2021 MIT 6.004 Spring 2021 L04-14
Passing Complex Data Structures
as Arguments
// Finds maximum element in an maximum:
// array with size elements mv t0, zero // t0: i
int maximum(int a[], int size) mv t1, zero // t1: max
{ j compare
int max = 0;
loop:
for (int i = 0; i < size;
i++) { slli t2, t0, 2 // t2: i*4
if (a[i] > max) { // t3: addr of a[i]
max = a[i]; add t3, a0, t2
} lw t4, 0(t3) // t4: a[i]
} ble t4, t1, endif
return max; mv t1, t4 // max = a[i]
}
endif:
int main() { addi t0, t0, 1 // i++
int ages[5] = compare:
{23, 4, 6, 81, 16}; blt t0, a1, loop
int max = maximum(ages, 5);
} mv a0, t1 // a0 = max
February 25, 2021 MIT 6.004 Spring 2021 ret L04-15
Memory Layout
§ Most programming languages (including C) have
three distinct memory regions for data:
§ Stack: Holds data used by procedure calls
§ Static: Holds global variables that exist for the entire
lifetime of the program
§ Heap: Holds dynamically-allocated data
§ In C, programmers manage the heap manually,
allocating new data using malloc() and releasing it
with free()
§ In Python, Java, and most modern languages, the heap
is managed automatically: programmers create new
objects (e.g., d = dict() in Python), but the system
frees them only when it is safe (no pointers in the
program point to them)
§ In addition, the text region holds program code
February 25, 2021 MIT 6.004 Spring 2021 L04-16
RISC-V Memory Layout
Main memory
0x0 § Text, static, and heap regions
pc Text (code) are placed consecutively,
starting from low addresses
gp § Heap grows towards higher
Static
addresses
§ Stack starts on highest address,
Heap
grows towards lower addresses
Program
ISA
Hardware (e.g., RISC-V)
…
Processor Memory Display Keyboard
§ Outputs:
§ 0x 4000 0000 - performing a sw to this address prints an
ASCII character to the console corresponding to the ASCII
equivalent of the value stored at this address
§ 0x 4000 0004 - a sw to this address prints a decimal
number
§ 0x 4000 0008 - a sw to this address prints a
hexadecimal number