MIPS Intro
COMP1521 23T2: lec01+02
How do our programs execute?
In COMP1[59]11:
What’s going on here? What’s even in hello?
Abiram’s show and tell: hard disk drives
Long-term, non-volatile storage
This is where we typically save files! *
Okay - so my compiler spat out hello and saved it to my hard drive - what next?
* hard disk drives are much less common these days - replaced by SSDs which are functionally equivalent
Abiram’s show and tell: hard disk drives
Long-term, non-volatile storage
This is where we typically save files! *
Okay - so my compiler spat out hello and saved it to my hard drive - what next?
* hard disk drives are much less common these days - replaced by SSDs which are functionally equivalent
Abiram’s show and tell: RAM (or ‘memory’)
Abiram’s show and tell: RAM (or ‘memory’)
Abiram’s show and tell: the CPU
But wait…
We’ve discussed memory and storage drives as being a place to store things.
Abiram’s show and tell: the CPU
Inside a CPU
What can instructions do?
and more!
A day in the life of a CPU - as C code
int program_counter = START_ADDRESS;
while (1) {
// Fetch an instruction from memory
int instruction = memory[program_counter];
// Move to the next instruction
program_counter++;
// Execute the next instruction
execute(instruction, &program_counter);
// ^ note: some instructions may
// modify the program counter
}
Writing instructions ourselves
In this course we will be writing CPU instructions ourselves instead of making a compiler do it.
Why might we do this?
Assembly
Instructions are really just 0s and 1s
A sample instruction + assembly
00100001000010010000000000001100
addi $t1, $t0, 12
Assembly
Instruction sets
“But I don’t have a MIPS CPU!”
We can’t run our MIPS instructions on our x86-64/ARM CPUs.
Instead, we use an emulator called mipsy:
* some contributions from Josh Harcombe, Dylan Brotherston and me :)
When will he shut up and actually write a MIPS program?
soon™
two more things to cover.
Registers
The CPU has a small amount of storage on the chip itself:
Registers
Almost all of our computations happen between registers!
Want to multiply 2 and 3 and store the result�Load 2 and 3 into registers:
And store the result:
li $t0, 2
li $t1, 3
mul $t2, $t0, $t1
Registers
Registers are denoted by a $ and can be referred to using a number ($0…$31) or by symbolic names ($zero…$ra)
$zero ($0) is special!
$ra ($31) is also special!
Registers
Could use the other 30 registers however we please technically, but there are some conventions we have to follow - will be discussed in next week’s tutes + Week 3 lectures.
Relevant registers (for now)
System calls
Our programs are useless!
Let’s go back and look at the types of instructions mentioned earlier:
What can instructions do?
and more!
System calls
Common mipsy syscalls
We won’t use syscalls 8, 12 much in COMP1521 - most input will be integers.
Other mipsy syscalls - seldom used
Probably not needed for COMP1521 - except maybe challenge exercises/provided code.
The system call workflow
li $v0, 1
li $a0, 42
syscall
MIPS and mipsy documentation
Literally your best friend (it’ll even be there for you in the exam 🥺)
Lecture chat
Lecture chat
Recap of lec01
The system call workflow
li $v0, 1
li $a0, 42
syscall
Finally, we can write hello world.
DISCLAIMER:
Code written in lectures may not necessarily have the best style!
li vs la vs move
Syntax overview
Assembly language programs contain:
MAX_NUMBERS = 256
Style
Simplified C
Translating C code directly to MIPS is not fun
Pro strat - simplify your C code and then translate it:
MIPS Control
COMP1521 23T2: lec02
So far…
All of our programs so far have implemented fixed, predictable behaviour.
However, what if we want to implement logic in our code?
if/else and loops don’t exist in MIPS - we have to use branching to implement these ourselves
Branch/jump instructions
In other words
A lot of these branch instructions are of the form:
“if condition is true, jump to instruction”
How do we implement this for our simplified C code?
COMP1511 staff hate this one simple trick!
In C, goto allows jumping to any arbitrary point within a program - as long as we define a label - meaning we can effectively yeet around within a program however we wish.
Simplifying if, if/else:
print_if_even, odd_even
goto is cool for simplification!
but don’t use it in your actual C programs.
More complex conditionals: || and soft serve machines
if (milk_age > 48 ||
milk_level < 10) {
printf("Replace milk\n");
} else {
printf("Milk okay!\n");
}
printf("Done!\n");
if (milk_age > 48) goto milk_replace;
if (milk_level < 10) goto milk_replace;
printf("Milk okay!\n");
goto milk_replace__end;
milk_replace:
printf("Replace milk\n");
milk_replace__end:
printf("Done!");
More complex conditionals: &&
if (x >= 0 && x <= 100) {
// in bounds
} else {
// out of bounds
}
return 0;
if (x < 0 || x > 100) {
// out of bounds
} else {
// in bounds
}
return 0;
Invert the condition to use || (De Morgan’s Law)
More complex conditionals: &&
if (x < 0 || x > 100) {
// out of bounds
} else {
// in bounds
}
return 0;
Split into separate conditionals:
if (x < 0) goto x_out_of_bounds;
if (x > 100) goto x_out_of_bounds;
// in bounds
goto epilogue;
x_out_of_bounds:
// out of bounds
epilogue:
return 0;
Simplifying loop structures
General structure:
Use labels to show structure!
Counting to 10
for (int i = 0; i < 10; i++) {
printf("%d\n", i);
}
int i = 0;
while (i < 10) {
printf("%d\n", i);
i++;
}
Counting to 10
int i = 0;
while (i < 10) {
printf("%d\n", i);
i++;
}
loop_i_to_10__init:;
int i = 0;
loop_i_to_10__cond:
if (i >= 10) goto loop_i_to_10__end;
loop_i_to_10__body:
printf("%d", i);
putchar('\n');
loop_i_to_10__step:
i++;
loop_i_to_10__end:
// ...
Simplifying for loops:
sum_100_squares
Sidenote: C break/continue
break can be used in a loop to completely exit the loop.
The loop condition here makes this look like an infinite loop:
but break means it’s possible for the loop to be exited.�In simplified C/MIPS, a break is really just equivalent to going to the loop’s end label.
Avoid writing C code with break where possible.
while (1) {
int c = getchar();
if (c == EOF) break;
}
Sidenote: C break/continue
continue can be used to proceed to the next iteration of a for loop.
This would be a (terrible) way to print even numbers:
In simplified C/MIPS, a continue is really just equivalent to going to the loop’s step label.
Avoid writing C code with continue where possible.
for (int i = 0; i < 10; i++) {
if (i % 2 != 0) continue;
printf("%d\n", i);
}