Skip to main content
Engineering LibreTexts

7.7: A Full Assembly Language Program

  • Page ID
    28723
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Now that the basics have been covered, a real assembly language program will be implemented. This program will read numeric grades from a user and calculate an average. The average and corresponding letter grade will be printed to the console.

    Before starting the project, it is recommended that the pseudo code be written. This serves two purposes. First it allows the programmer to reason at a higher level of abstraction, and it makes it easier to implement the code because it is a straight translation from pseudo code to assembly. Second, the pseudo code serves as documentation for how the program works. The pseudo code should be included in a comment at the start of the assembly file, and not kept in a separate file so it does not get lost.

    Once the pseudo code is written, the assembly code can be implemented. This is done below. Note that this is a program, and not a code fragment that is used to illustrate a MIPS assembly feature. Therefore this has a preamble comment giving information such as Filename, Author, Date, Purpose, Modification History, and the Pseudo Code. Most professors and companies have their own standard for preamble comments, and they should be followed when documenting the code.

    Finally realize that it is a myth that assembly code is not readable. If care is taken when writing it and documenting it, it can be just as readable as code in a higher level language. However the code is much more verbose, and the ability to use abstraction is greatly reduced. Just as a high level language is no substitute for assembly when it is needed, assembly is no substitute for a high level language when it is appropriate.

    # Filename:     AverageGrade.asm
    # Author:       Charles Kann
    # Date:         12/29/2013
    # Purpose:      Illustration of program to calculate a student grade
    # Modification Log: 12/29/2014 - Initial release
    #
    # Pseudo Code
    # global main()
    # {
    #  // The following variables are to be stored in data segment, and
    #  // not simply used from a register. They must be read each time
    #  // they are used, and saved when they are changed.
    #  static volatile int numberOfEntries = 0
    #  static volatile int total = 0
    #  // The following variable can be kept in a save register.
    #  register int inputGrade # input grade from the user
    #     register int average
    #
    #  // Sentinel loop to get grades, calculate total.
    #  inputGrade = prompt("Enter grade, or -1 when done")
    #  while (inputGrade != -1)
    # {
    #      numberOfEntries = numberOfEntries + 1
    #      total = total + inputGrade
    #      inputGrade = prompt("Enter grade, or -1 when done")
    # }
    #
    #      # Calculate average
    #      average = total / numberOfEntries
    #
    #  // Print average
    #  print("Average = " + average)
    #
    # //Print grade if average is between 0 and 100, otherwise an error
    #     if ((grade >= 0) & (grade <= 100))
    #     {
    #        if (grade >= 90)
    #        {
    #            print("Grade is A")
    #        }
    #        if (grade >= 80)
    #        {
    #            print("Grade is B")
    #        }
    #        if (grade >= 70)
    #        {
    #        print("Grade is C")
    #        }
    #        else
    #        {
    #            print("Grade is F")
    #        }
    #    }
    #    else
    #    {
    #        print("The average is invalid")
    #    }
    # }
    
    .text
    .globl main
    main:
        # Register Conventions:
        #  $s0 - current inputGrade
        #  $s1 - average
        la $a0, prompt
        jal PromptInt
        move $s0, $v0
        
        BeginInputLoop:
        addi $t0, $zero, -1            # set condition $s0 != -1
        seq $t0, $t0, $s0
        xor $t0, $t0, 0x00000001
        beqz $t0, EndInputLoop         # check condition to end loop
            
            la $t0, numberOfEntries    # increment # of entries
            lw $t1, 0($t0)
            addi $t1, $t1, 1
            sw $t1, 0($t0)
            
            la $t0, total              # accumulate total
            lw $t1, 0($t0)
            add $t1, $t1, $s0
            sw $t1, 0($t0)
            
            la $a0, prompt             # prompt for next input
            jal PromptInt
            move $s0, $v0
            b BeginInputLoop
        EndInputLoop:
        
        la $t0, numberOfEntries        # Calculate Average
        lw $t1, 0($t0)
        la $t0, total
        lw $t2, 0($t0)
        div $s1, $t2, $t1
        
        la $a0, avgOutput              # Print the average
        move $a1, $s1
        jal PrintInt
        jal NewLine
        
        sge $t0, $s1, 0                # Set the condition
                                       # (average > 0) & (average < 100)
        addi $t1, $zero, 100
        sle $t1, $s1, $t1
        and $t0, $t0, $t1
        beqz $t0, AverageError         # if Not AverageError
            sge $t0, $s1, 90           # PrintGrades
            beqz $t0, NotA
                la $a0, gradeA
                jal PrintString
                b EndPrintGrades
            NotA:
                sge $t0, $s1, 80
                beqz $t0, NotB
                la $a0, gradeB
                jal PrintString
                b EndPrintGrades
            NotB:
                seq $t0, $s1, 70
                beqz $t0, NotC
                la $a0, NotC
                la $a0, gradeC
                jal PrintString
                b EndPrintGrades
            NotC:
                la $a0, gradeF
                jal PrintString
            EndPrintGrades:
            b EndAverageError
        AverageError:                   #else AverageError
            la $a0, invalidAvg
            jal PrintString
        EndAverageError:
        
        jal Exit
    
    .data
        numberOfEntries: .word 0
        total:           .word 0
        average:         .word
        prompt:          .asciiz "Enter grade, or -1 when done: "
        avgOutput:       .asciiz "The average is "
        gradeA:          .asciiz "The grades is an A"
        gradeB:          .asciiz "The grade is a B"
        gradeC:          .asciiz "The grade is a C"
        gradeF:          .asciiz "The grade is a F"
        invalidAvg:      .asciiz "The average is invalid"
    .include "utils.asm" 

    This page titled 7.7: A Full Assembly Language Program is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Charles W. Kann III.

    • Was this article helpful?