patternMinor
Listing the first five perfect numbers in MIPS assembly
Viewed 0 times
themipsfivenumbersperfectlistingassemblyfirst
Problem
I've done some programming in the past, but I'm new to MIPS, which I'm trying to learn on my own. This program lists the first five perfect numbers. It uses the Lucas-Lehmer and Miller-Rabin primality tests. Any suggestions on how I could improve will be most appreciated.
```
.data # marks the following as data
seed:
.word 127 # seed for random number sequence
newline:
.asciiz "\n" # newline character
tabchar:
.asciiz "\t" # tab character
header:
.asciiz "n\tp\tm\tpn\n"
.text # required - beginning of executable code
###############################################################################
# displays the first five perfect numbers
#
# register usage:
# $s0 n perfect number counter $s4 unused
# $s1 current prime $s5 unused
# $s2 mersenne number $s6 unused
# $s3 unused $s7 unused
#
# $t0 scratch $t5 unused
# $t1 scratch $t6 unused
# $t2 scratch $t7 unused
# $t3 unused $t8 unused
# $t4 unused $t9 unused
#
main: # required - address of first instruction
addiu $sp,$sp,-36 # make room for ra & s registers
sw $ra,0($sp) # preserve return address
sw $s0,4($sp)
sw $s1,8($sp)
sw $s2,12($sp)
sw $s3,16($sp)
sw $s4,20($sp)
sw $s5,24($sp)
sw $s6,28($sp)
sw $s7,32($sp)
la $a0,header # load address of string to print
li $v0,4 # os service "print_string"
syscall # call the os
li $s0,5 # get this many perfect numbers
move $s1,$zero # want first prime
main_loop:
move $a0,$s1 # get
```
.data # marks the following as data
seed:
.word 127 # seed for random number sequence
newline:
.asciiz "\n" # newline character
tabchar:
.asciiz "\t" # tab character
header:
.asciiz "n\tp\tm\tpn\n"
.text # required - beginning of executable code
###############################################################################
# displays the first five perfect numbers
#
# register usage:
# $s0 n perfect number counter $s4 unused
# $s1 current prime $s5 unused
# $s2 mersenne number $s6 unused
# $s3 unused $s7 unused
#
# $t0 scratch $t5 unused
# $t1 scratch $t6 unused
# $t2 scratch $t7 unused
# $t3 unused $t8 unused
# $t4 unused $t9 unused
#
main: # required - address of first instruction
addiu $sp,$sp,-36 # make room for ra & s registers
sw $ra,0($sp) # preserve return address
sw $s0,4($sp)
sw $s1,8($sp)
sw $s2,12($sp)
sw $s3,16($sp)
sw $s4,20($sp)
sw $s5,24($sp)
sw $s6,28($sp)
sw $s7,32($sp)
la $a0,header # load address of string to print
li $v0,4 # os service "print_string"
syscall # call the os
li $s0,5 # get this many perfect numbers
move $s1,$zero # want first prime
main_loop:
move $a0,$s1 # get
Solution
Comments
Overall, I think you do a really great job with your comments. You clearly separate each section of code, state its purpose, list the register usage (very important for assembly), and do not have many obvious comments spread throughout. You pretty much have that part nailed down.
I just have a few minor things to address:
-
You don't need to add a comment for every
-
Don't be afraid to add a summary comment on top or to the side of a block of similar code. This may be beneficial for large procedures that execute instructions that can be explained with one comment on top or to the side (like you did with the
Structure
You also do pretty well with structure. It's not too difficult to follow the code. Labels clearly stand out and the respective instructions are indented well.
I do still have some additional things to say about this:
-
Put appropriate linebreaks within procedures:
You may separate the
For larger procedures, you may separate the
-
It may help to give the loop labels more accurate names.
You should especially give distinction for nested loops. Even then, you would probably indent nested loops further unless this common style is to be maintained.
Consider stating the type of loop used, such as
Overall, I think you do a really great job with your comments. You clearly separate each section of code, state its purpose, list the register usage (very important for assembly), and do not have many obvious comments spread throughout. You pretty much have that part nailed down.
I just have a few minor things to address:
-
You don't need to add a comment for every
syscall. This can be added as a general comment at the top of the procedure(s) or the program.-
Don't be afraid to add a summary comment on top or to the side of a block of similar code. This may be beneficial for large procedures that execute instructions that can be explained with one comment on top or to the side (like you did with the
# preserve return address comment).Structure
You also do pretty well with structure. It's not too difficult to follow the code. Labels clearly stand out and the respective instructions are indented well.
I do still have some additional things to say about this:
-
Put appropriate linebreaks within procedures:
You may separate the
syscalls, especially since there are so many of them.For larger procedures, you may separate the
jmps and branches, especially if there are around the middle of the procedure. The ones at the end are okay as-is, especially since they're most commonly there. It would be good to make it clear if a procedure will ever jump or branch, otherwise it may be assumed that it will always fall to the next one (no change in the flow).-
It may help to give the loop labels more accurate names.
You should especially give distinction for nested loops. Even then, you would probably indent nested loops further unless this common style is to be maintained.
Consider stating the type of loop used, such as
for (counter), while (pre-test), or do-while (post-test). This may be an important distinction as it would otherwise take close reading of the code to determine the type of loop being used.Context
StackExchange Code Review Q#14366, answer score: 6
Revisions (0)
No revisions yet.