Search code examples
assemblymips

How to improve this MIPS-Assembly program


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: "

Solution

  • Correctness Issues:

    1. 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.

    2. 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:

    1. 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.

    2. 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...