Presentation on theme: "Some Samples of MIPS Assembly Language Lecture for CPSC 5155 Edward Bosworth, Ph.D. Computer Science Department Columbus State University."— Presentation transcript:
Some Samples of MIPS Assembly Language Lecture for CPSC 5155 Edward Bosworth, Ph.D. Computer Science Department Columbus State University
Structure of This Lecture This lecture will be built around a number of sample programs, written in assembly language and run under both SPIM and MARS. We begin with some of the syntax for writing the programs and then illustrate.
System Calls Almost all programs, user and system, are written to be run on a machine with a fully functional operating system. The operating system provides a number of services to other programs. We shall use a number of SPIM system calls to facilitate input and output.
Example of System Calls.data str: asciiz “The answer is ”.text li $v0, 4 # Code for print string la $a0, str # Address of string syscall # Print the string li $v0, 1 # Code for print integer li $a0, 5 # Value to print syscall li $v0, 10 # Code for exit syscall
SPIM Data Directives Here are a number of directives used to set aside memory and initialize it..asciiz str stores the string in memory and null terminates it in the style of C or C++..space N allocates N bytes of storage for structures such as arrays, etc..word w1 … wn allocates and initializes n 32-bit words.
Sample of Space Allocation S1:.asciiz “A null-terminated string” This associates label S1 with the string. C1:.space 80 This allocates 80 bytes, possibly for an array to hold 80 characters or 20 32-bit integers. W1:.word 1, 2, 3 This initializes three integer values. Same as W1:.word 1.word 2 # At address W1 + 4.word 3 # At address W1 + 8
Conventions for Strings Strings should be null terminated, as in the style of C and C++. String constants are enclosed in double quotes “This is a string” Special characters follow the C/C++ style newline\n tab\t quote\”
Data Alignment The assembler will normally align data as required by the data type. The. align N directive aligns the next entry on an address that is a multiple of 2 N. Character data can be stored anywhere. Byte data must be stored at an address that is a multiple of 2. Use.align 1 Word data must be stored at an address that is a multiple of 4. Use.align 2
Kernel and User Mode All modern computer systems restrict certain operations to the operating system, when it is operating in what is called “kernel mode”. Example restricted operations: direct access to I/O devices, memory management, etc. SPIM allows programs to be run in either user mode or kernel mode, as both modes are emulated on the host machine.
SPIM Text & Data.data This stores subsequent items in the user data segment..kdata This stores subsequent items in the kernel data segment..ktext This stores subsequent items in the kernel text area, which holds instructions for kernel code..text This stores subsequent items in the user text area, also for program instructions.
The Optional Address Each of these directives has an optional address, commonly not used. One exception will be for an interrupt handler, which must be in the kernel at a fixed address..ktext 0x80000180 sw $a0, savea0 sw $a1, savea1 More code goes here..kdata savea0.word 0 savea1.word 0
Compute Fibonacci Numbers The Fibonacci sequence was introduced in 1202 by the Italian mathematician Leonardo of Pisa, known as Fibonacci. The sequence is defined for N 0 as follows: F 0 = 1, F 1 = 1, and F N = F N-1 + F N-2 for N 2. This is often used as an example of recursion. We shall implement a non-recursive solution in the MIPS assembly language.
The Basic Algorithm The basic non-recursive algorithm for computing Fibonacci numbers uses a loop. To compute F(N), do the following F1 = 1 F2 = 1 For (J = 2; J <= N; J++) F0 = F1 F1 = F2 F2 = F1 + F0 End For
The Program (Page 1) Here is the standard program header. # Fibonacci # # This is a non-recursive program to calculate Fibonacci # numbers, defined as follows: F(0) = 1, F(1) = 1, # and F(N) = F(N - 1) + F(N - 2), for N >= 2. # # This runs under both MARS and SPIM. # # Written by Edward Bosworth, Ph.D. # Associate Professor of Computer Science # Columbus State University # Columbus, GA 31907-5645 # E-Mail bosworth_edward@ColumbusState.edu # # Date first written: July 4, 2012 # Date last revised: July 4, 2012.
The Program (Page 2) Here is the start of the code. Note that the program must have a globally visible label “main” at its start..text.globl main # Make this global main: li $v0, 4 # Print string la $a0, str0 # Address of title string syscall # Print the title # getN: li $v0, 4 # Print string la $a0, str1 # Address of input prompt syscall # Print the prompt. # li $v0, 5 # Read an integer syscall # Return the value in $v0
The Program (Page 3) The program is designed to loop: read user input and then to produce the result. The user input is found in $v0. Non-positive input is a signal to terminate the program. A value of 1 disrupts the loop logic, so treat as special. blez $v0, done # Do we stop? li $v1, 1 # F(1) is trivial. bgt $v0, $v1, doit # Is N > 1? # li $v0, 4 # F(1) will disrupt la $a0, str2 # the loop logic; syscall # just print answer j getN # Get more input. #
The Program (Page 4) Here is the main computational loop. doit: li $t1, 1 # Initialization li $t2, 1 # code for loop. # loop: addi $v1, $v1, 1 # Bump $v1 move $t0, $t1 # New F(N - 2) move $t1, $t2 # New F(N - 1) addu $t2, $t0, $t1 # New F(N), where # $v1 contains N blt $v1, $v0, loop # Are we done? #
The Program (Page 5) Print out the result and get more input. move $a1, $v0 # Set aside the value of N li $v0, 4 la $a0, str3 # Print part of output string syscall # li $v0, 1 move $a0, $a1 # Get the value of N back syscall # Print N # li $v0, 4 la $a0, str4 # Print more of the string syscall # li $v0, 1 # F(N) is found in $t2 move $a0, $t2 # Print the result syscall # j getN # Get more input.
The Program (Page 6) Here is the closing code and data section. # Set up for a proper exit # done: li $v0, 4 # Print closing remark la $a0, finis # Address of closing remark syscall # li $v0, 10 # Call exit syscall #.data str0:.asciiz "Program to calculate a Fibonacci number“ str1:.asciiz "\nInput an integer: “ str2:.asciiz "\nF(1) is equal to 1.“ str3:.asciiz "\nThe Fibonacci number F(“ str4:.asciiz ") is equal to “ finis:.asciiz "\nAll done. \n" # \n is New line
Comments on the Text Figure B.1.4 on page B-7 contains the following. It has a problem..text.align 2.globl main main: The MARS emulator does not allow the.align directive within the text area.
When to Use Assembly Language When should one prefer assembly language for writing programs? Your instructor’s opinion is “almost never”. Compiler technology has advanced to a point that it is almost impossible to write code better or faster than that emitted by a modern compiler. The only real use for assembly language is as a part of teaching computer science.
Ancient History (PDP-9 FORTRAN) The PDP-9 computer was fairly advanced for the early 1970’s. Your instructor programmed such a machine from 1971 to 1973. The PDP-9 supported programs written in the FORTRAN programming language. The code produced was very slow. The preferable method was to have the FORTRAN compiler emit assembly language code, edit that code, and assembly it.
Labels: Local and Global A label is called “global” or “external” if it can be referenced from another module. The label may refer to a memory storage location or to a function or procedure. The linker will resolve global references as a part of creating the executable image. If module A references a global in module B, the linker will make the correct connection. Any label not declared as global is local, not available for reference by other modules.
Rdata & Sdata The sample code on page B-28 includes a data directive “.rdata ”. There is another directive, “.sdata ”. The MARS emulator does not recognize either directive. Use “.data ” for user data and “.kdata ” for kernel data.
Various Jump Commands The code near the bottom of page B-28 contains an error: 2 commands are confused. jjump to the instruction at the target address jrjump to the instruction at the address stored in the register. The instruction should be j L1. Also, the label should be L1, not $L1.
The Assembly Temporary ($at) Register Register $1 (called “$at”) is reserved for use by the assembler. The SPIM emulator will raise an error if the code references the $at register. To avoid this problem, when it is necessary to save the $at register, use the following..set noat # Allow use of $at move $k1, $at # Save it.set at # Assembler can now # use $at again.
Exception Handler Code The sample code on page B-36 contains the following code, which should be corrected.ktext 0x80000180 mov $k1, $at # Save the register $at It should read as follows.ktext 0x80000180.set noat move $k1, $at.set at
Exceptions & Interrupts Exceptions are events that disrupt the normal flow of program control and cause exception code to be executed. Almost always, this is kernel code managed by the operating system. Interrupts are exceptions from outside sources such as I/O devices. The terminology is not uniformly applied.
Examples of Exceptions External interrupts include: Inputthe device has data ready to transfer Outputthe device is ready to receive data Timerthe CPU timer raises an interrupt, used to run the CPU clock. Exceptions include Arithmetic overflow – an arithmetic error Page fault – a reference has been made to an invalid virtual memory address.
Exceptions: Control Unit Implications For most external interrupts, the implications for the control unit are rather simple. As the control unit begins the execution of each instruction, it tests a signal (often called “INT”) that indicates that there is an interrupt pending. If there is a pending interrupt, the control unit branches unconditionally to kernel code.
Handling Exceptions Depending on the exception type, the control unit will begin execution of kernel code at one of two locations. 0x80000000 for undefined instructions 0x80000180 for other exceptions For that reason, the standard exception handler begins as follows:.ktext 0x80000180.set noat move $k1, $at # This at 0x80000180.set at
More Control Unit Implications The handling of page fault exceptions shows one of the strengths of a load/store RISC. Only register load and register store instructions can reference memory. Neither load nor store change the computer state prior to referencing memory, so that any instruction can be restarted after a page fault.
The Coprocessors CP0 for exceptions; CP1 for floating point
Coprocessor Registers Coprocessor 0 has a number of registers to control exceptions and manage memory. Here are some of the registers used by SPIM $12the interrupt mask and enable bits $13the exception type and pending interrupt bits $14EPC: address of the instruction that caused the exception.
Accessing CP0 Registers There are two instructions for accessing the registers in coprocessor 0: mfc0 and mtc0. mfc0 $k0, $13 Copy CP0 cause register ($13) into CPU register $k0 ($26). mtc0 $k1, $12 Load CP0 status register ($12) from CPU register $k1 ($27).
Sample Exception Handler Code.ktext 0x80000180 sw $a0, savea0 # Use static storage sw $a1, savea1 # It uses $a0 and $a1, so save sw $v0, savev0 # It also uses $v0 # # Now determine the cause of the exception or interrupt # mfc0 $t0, $13 # Move cause into $t0 srl $t0, $t0, 2 # Shift to get exception code andi $t0, $t0, 0xF # Put the code into $t0 # More code here to handle exception
Returning from Exception la $a0, L4 # L4 is the return address, # defined elsewhere in code mtc0 $a0, $14 # Put it into the EPC # mtc0 $0, $13 # Clear the cause register mfc0 $a1, $12 # Get the status register andi $a1, 0xFFFD # Clear the EXL bit ori $a1, 0x1 # Enable the interrupt and mtc0 $a1, $12 # reset the status register # lw $v0, savev0 lw $a1, savea1 lw $a0, savea0 # eret # Return to new spot # Not a subroutine return.