The Complete Assembly Code Structure
The first thing I’ve noticed about the assembly code file is the structure. Based on the comments, there are two parts of code segment and data segment.
Code segment:
.text
.align # align number (not necessary)
.globl [func name] (not necessary)
[func name]:
# something
Data segment:
.data
[declaration of the data schema]
name: type value
Pseudoinstructions about Load Data
Besides the lw instruction that we’ve learned in class, the simple assembly code uses li and la. After searching, I learned that these are some pseudoinstructions for loading.
li (Load Immediate):
- This is used to load an immediate (constant) value into a register.
- E.g., in
simple.s:li $v0, 10, then becomeori $2, $0, 10in the QtSpim. Since0 | 10 = 10so the constant10is loaded into$2($v0).
la (Load Address):
- This is used to load the memory address of a label into a register. (Not the data stored at that address, but the address itself.)
- E.g., in
simple.s:la $a0, nln, then becomelui $1, 4097 [nln]ori $4, $1, 62 [nln]
- Based on the translated instruction, we can know the address of label
nlnis0x1001003E. The first instruction loads the0x1001into the upper half of the bits of$1, then the second instruction uses an or operation to combine0x10010000and0x3e, which is0x1001003e, and loads it into$4.
I/O Function by Syscall
We usually want to use the I/O to show something or get some input from the user, and syscall actually provides such functions. I found a document that shows the details about how to use this.
Store the Return Address
When I was working on problem 4, I wrote the following code and encountered a problem.
foo:
add $v0, $a0, $a1
jr $ra
main:
li $a0, 1
li $a1, 2
jal foo
jr $ra
Whenever using jal to call a function, we need to remember to store the return address in advance to avoid losing it. So it should be like this:
foo:
add $v0, $a0, $a1
jr $ra
main:
addi $sp, $sp, -4
sw $ra 0($sp)
li $a0, 1
li $a1, 2
jal foo
lw $ra 0($sp)
addi $sp, $sp, 4
jr $ra
When I was working on problem 5, I found the description asked to ignore saving %ra for this exercise……Never mind.
Restore the Stack Pointer
When writing the recursive functions, don’t forget to restore the stack pointer. Otherwise the $ra might get some unexpected address.
Compile C into MIPS Assembly
I am curious about how to get the MIPS assembly by compiling the C file, and I found 2 ways to do that. The first is to use Compiler Explorer, an online tool. But I want to compile on my own computer, so I found a document about cross-compilation in Clang. So to compile the C into MIPS assembly, just use the following command:
clang -S -target mips-unknown-elf -mips32 -EB -o main.s main.c
However, this compiled assembly can’t be used for the QtSpim, since it only supports a subset of the MIPS instruction set, so I just open it and learn something from it.