Upload
phamdien
View
221
Download
3
Embed Size (px)
Citation preview
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 2N.
• 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 <address> This stores subsequent items in the user data segment.
• .kdata <address> This stores subsequent items in the kernel data segment.
• .ktext <address> This stores subsequent items in the kernel text area, which holds instructions for kernel code.
• .text <address> 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: F0 = 1, F1 = 1, and FN = FN-1 + FN-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 [email protected] # # 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.
• j jump to the instruction at the target address
• jr jump 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: Input the device has data ready to transfer Output the device is ready to receive data Timer the 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.
Coprocessor Registers
• Coprocessor 0 has a number of registers to control exceptions and manage memory.
• Here are some of the registers used by SPIM $12 the interrupt mask and enable bits $13 the exception type and pending interrupt bits $14 EPC: 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.