I had this for a short exam and this is the solution I came up with. I left this subject for my last year because the teacher is really bad and I was under a lot of pressure so this is why this program is so ugly and brute forced. The task was to take a 21 letter string and build a right pointing pyramid starting from the middle, which means 1 letter to 3 letters etc. I didn't include the second part because it is obvious of what I would do.
Out of curiosity how do I shorten this program considerably? I heard a hint that we should use swift operations but I don't know how to use them.
.text
.globl main
# Code goes here
main:
#print 1st char
la $t0, str
lb $t1, 10($t0)
move $a0, $t0
li $v0, 11
add $a0, $t1, 0
syscall
jal print_endl
jal print3
jal print_endl
jal print5
jal print_endl
jal print7
jal print_endl
jal print9
jal print_endl
jal print11
jal print_endl
jal print13
jal print_endl
jal print15
jal print_endl
jal print17
jal print_endl
jal print19
jal print_endl
jal print21
# Program terminates here
exit: li $v0, 10
syscall
# Procedure that prints a newline
print_endl: addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 4
la $a0, endl
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
# Procedure that prints a space character
print_spc: addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 4
la $a0, spc
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print3:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print5:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print7:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print9:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print11:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print13:
li $v0, 11
lb $a0, 4($t0)
syscall
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lb $a0, 16($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print15:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 3($t0)
syscall
lb $a0, 4($t0)
syscall
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lb $a0, 16($t0)
syscall
lb $a0, 17($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print17:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 2($t0)
syscall
lb $a0, 3($t0)
syscall
lb $a0, 4($t0)
syscall
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lb $a0, 16($t0)
syscall
lb $a0, 17($t0)
syscall
lb $a0, 18($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print19:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 1($t0)
syscall
lb $a0, 2($t0)
syscall
lb $a0, 3($t0)
syscall
lb $a0, 4($t0)
syscall
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lb $a0, 16($t0)
syscall
lb $a0, 17($t0)
syscall
lb $a0, 18($t0)
syscall
lb $a0, 19($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
print21:
addi $sp, $sp, -4
sw $a0, 0($sp)
li $v0, 11
lb $a0, 0($t0)
syscall
lb $a0, 1($t0)
syscall
lb $a0, 2($t0)
syscall
lb $a0, 3($t0)
syscall
lb $a0, 4($t0)
syscall
lb $a0, 5($t0)
syscall
lb $a0, 6($t0)
syscall
lb $a0, 7($t0)
syscall
lb $a0, 8($t0)
syscall
lb $a0, 9($t0)
syscall
lb $a0, 10($t0)
syscall
lb $a0, 11($t0)
syscall
lb $a0, 12($t0)
syscall
lb $a0, 13($t0)
syscall
lb $a0, 14($t0)
syscall
lb $a0, 15($t0)
syscall
lb $a0, 16($t0)
syscall
lb $a0, 17($t0)
syscall
lb $a0, 18($t0)
syscall
lb $a0, 19($t0)
syscall
lb $a0, 20($t0)
syscall
lw $a0, 0($sp)
addi $sp, $sp, 4
jr $ra
# Data goes here
.data
endl: .asciiz "\n"
string: .asciiz "testring123\n"
str: .asciiz "mynameisslimshadyprol"
ans: .asciiz "The length is: "
Correctness Issues:
This code is following a non-standard calling convention, requiring $a0
to be call-preserved, though in the standard calling convention, $a0
is a call clobbered register. While it is ok to create a custom calling convention, one should be aware of it, and, it does mean that these functions would not necessarily mix well with the C language, for example, writing one or more of them in C.
On MIPS, we should be using addiu
instead of addi
for all pointer arithmetic, including stack pointer adjustments. While addi
may often work, it will trap/fault on signed overflow — but pointers are unsigned numbers, so we shouldn't ask for signed overflow checking on their arithmetic.
Code Size Observations:
There isn't a single loop in the whole program. Loops are one of the simplest approaches to abstraction — they allow repeating the execution of some code (the loop body) without restating that code repeatedly.
That code is using functions which is a good approach to abstraction. However, no function calls any other function — only the main
calls functions. Functions themselves calling other functions is another opportunity to repeat code execution without restating code repeatedly.
When you write C code do you avoid using loops and write everything out this way?
While this works for some problems, there are many problems that cannot easily be solved without using loops1 — for example, what if the string, came as input from the user and were allowed any length? It would wholly impractical to write a loop-less1 program that handles an arbitrary string.
1loops or recursion...