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 become ori $2, $0, 10 in the QtSpim. Since 0 | 10 = 10 so the constant 10 is 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 become
    • lui $1, 4097 [nln]
    • ori $4, $1, 62 [nln]
  • Based on the translated instruction, we can know the address of label nln is 0x1001003E. The first instruction loads the 0x1001 into the upper half of the bits of $1, then the second instruction uses an or operation to combine 0x10010000 and 0x3e, which is 0x1001003e, 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.