im in a class learning assembly using mips. I am working on sorting an array of numbers and i think that I have the method working correctly, but just a bit of trouble. I do
Coding direct in assembly is a pain. What I do instead is start with an algorithm (psuedocode or actual code) then translate systematically, as if I am a compiler. I will ignore the input and output stuff and focus on a function that sorts.
You would call in a high-level lanaguage like C as:
insertionsort(data, N);
where data
is an integer array and N
the number of elements (there are no size attributes at machine level).
Since the function calls nothing, it needs no stack frame. Observe the standard MIPS conventions of using $t
registers so you are not trashing anything anyone else relies on and pass in parameters in $a0
and $a1
in that order.
Step 1: get an algorithm. Here’s one from [Wikipedia][1] for insertion sort:
i ← 1
while i < length(A)
x ← A[i]
j ← i - 1
while j >= 0 and A[j] > x
A[j+1] ← A[j]
j ← j - 1
end while
A[j+1] ← x
i ← i + 1
end while
Step 2: paste into a text file, turn all lines into comments and systematically convert to assembly. I use templates for things like loops that take the guess work out of coding (see my free book for examples). I will just give the finished product here; to call it, you need to put the start address of the array into $a0
and its size in $a1
, then jal insertionsort
:
# algorithm for insertion sort
# from https://en.wikipedia.org/wiki/Insertion_sort
# usage: insertionsort (a,N)
# pass array start in $a0, size in elements, N in $a1
# Philip Machanick
# 30 April 2018
.globl insertionsort
.text
# leaf function, no stack frame needed
# Registers:
# $a0: base address; $a1: N
# $t0: i
# $t1: j
# $t2: value of A[i] or A[j]
# $t3: value of x (current A[i])
# $t4: current offset of A[i] or A[j] as needed
insertionsort:
# i ← 1
li $t0, 1
# while i < N
j Wnext001 # test before 1st iteration
Wbody001: # body of loop here
sll $t4, $t0, 2 # scale index i to offset
add $t4, $a0, $t4 # address of a[i]
# x ← A[i]
lw $t3, 0($t4)
# j ← i - 1
addi $t1, $t0, -1
# while j >= 0 and A[j] > x
j Wnext002 # test before 1st iteration
Wbody002: # body of loop here
# A[j+1] ← A[j]
sll $t4, $t1, 2 # scale index j to offset
add $t4, $a0, $t4 # address of a[j]
lw $t2, 0($t4) # get value of A[j]
addi $t4, $t4, 4 # offset of A[j+1]
sw $t2, 0($t4) # assign to A[j+1]
# j ← j - 1
addi $t1, $t1, -1
# end while
Wnext002: # construct condition, j >= 0 and A[j] > x
blt $t1, $zero Wdone002 # convert to: if j < 0 break from loop #####
sll $t4, $t1, 2 # scale index j to offset
add $t4, $a0, $t4 # address of a[j]
lw $t2, 0($t4) # A[j]
bgt $t2, $t3, Wbody002 # no need to test j >= 0, broke from loop already if false
Wdone002: # branch here to short-circuit and
# A[j+1] ← x
add $t4, $t1, 1 # scale index j+1 to offset
sll $t4, $t4, 2 # scale index j to offset
add $t4, $a0, $t4 # address of a[j+1]
sw $t3, 0($t4) # A[j+1] becomes x
# i ← i + 1
addi $t0, $t0, 1
# end while
Wnext001: blt $t0,$a1, Wbody001 # i < N easy this time
jr $ra # return to caller
Longer than the other examples – but if you start from an algorithm and translate you are less likely to go wrong. This can go in a separate file if your assembler respects the .globl
directive, which makes the name visible in other files.
[1]: https://en.wikipedia.org/wiki/Insertion_sort – actually from Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2001). "Section 2.1: Insertion sort". Introduction to Algorithms (2nd ed.). MIT Press and McGraw-Hill. pp. 15–21