SYSCALL_PRINT_STRING = 4 # As defined by the MIPSY ABI (application binary interface)
## Constant for the return value of the main function
EXIT_SUCCESS = 0 # In C, this is defined in `stdlib.h`
# Define some data
# Everything after the `.data` directive until the next `.text` directive is "data" and not "code"
.data
string: .asciiz "I love MIPS\n"
# `string` is a label, it is a name that can be used to refer to the address of the data (a pointer)
# The `.asciiz` directive is used to define a null-terminated string (just like "double quotes" in C)
# we can also use the `.ascii` directive and manually add a null byte at the end of the string (e.g. `.ascii "I love MIPS\n\0")
# Define some "text"
# "text" is the executable code of the program
# Everything after the `.text` directive until the next `.data` directive is "code" and not "data"
# There is also a implicit `.text` directive at the beginning of the program so everything before the first `.data` directive is "code" and not "data"
.text
# The `.globl` directive is used to define a global symbol, this isn't necessary for MIPSY
# but you might see it in other MIPS assembly programs
# (why is the word "global" spelled with an "a"? who knows?)
.globl main
# `main` is a label (just like `string`), it is a name that can be used to refer to this address
# but instead of referring to the address of some data, it refers to the address of some code (a function)
# this means that a function is just a pointer
# Just like in C, all MIPS assembly programs must have a `main` function
# the `main` function is the entry point of the program
# so the first line of code executed by the program is the first line of the `main` function
main:
## printf("%s", "I love MIPS\n")
la $a0, string ## pass address of string "I love MIPS\n" as first (and only) argument
li $v0, SYSCALL_PRINT_STRING ## magic number for the print string syscall ( printf("%s") )
syscall
# the `LA` instruction is used to load an *address*
# this means that the operand is a label, or a memory location (pointer)
# the `LI` instruction is used to load an *immediate*
# an immediate is a fancy word for a constant value, like a number (6, 0, -42, etc.) or a character ('a', ' ', '\n', etc.)
# immediates can also be binary numbers (0b1010, 0b1111, etc.), octal numbers (0o123, 0o777, etc.), and hexadecimal numbers (0x123, 0xABC, etc.)
# immediates can also be constants defined earlier in the program (e.g. `SYSCALL_PRINT_STRING` as this is equivalent to the number 4)
## return 0
li $v0, EXIT_SUCCESS
jr $ra
# the `JR` instruction the `return` part
# The value of the register `$v0` is the return value of the function