Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439
 1 
ECE 473 Computer Architecture and Organization 
Lab 4: MIPS Assembly Programming 
Due:  Thursday, October 10 
(100 points) 
Objectives: 
 Get familiar with MIPS instructions 
 Assemble, execute and debug MIPS assembly programs 
What to hand in: 
1. Assembly Programs 
Submit your project codes in one zip file to http://web.eece.maine.edu/hw/  
 
1. MIPS Instructions 
 
MIPS stands for Microprocessor without Interlocked Pipeline Stages. MIPS designs are 
used in many embedded systems such as Sony PlayStation 2, Cisco routers, and 
Windows CE devices. Since MIPS has greatly influenced later design of instruction sets 
and processors, MIPS will be the main assembly language used in ECE 473. 
 
The following shows a simple loop example in C. 
 
 
 
We can translate this simple loop into a MIPS program: 
 
 
 
2. MIPS simulator running on MARS: SPIM 
 
MARS is an interactive software simulator for MIPS based on Java. You can download 
the latest version of MARS from here 
http://courses.missouristate.edu/KenVollmar/MARS/index.htm 
 
In Linux, in command line, run: java -jar Mars.jar 
In Windows, either double-click the Mars.jar file or run java -jar Mars.jar 
 
 
 2 
The website also provides the following three sample programs:  
Fibonacci.asm, row-major.asm, column-major.asm 
 
 
3. Quick Reference of MIPS Programming 
 
3.1 Accessing Array 
 
list: .word 3, 0, 1, 2, 6, -2, 4, 7, 3, 7 
  
 la $t3, list          # put address of list into $t3 
    lw $t4, 0($t3)       # get the value list[0] 
    lw $t4, 4($t3)       # get the value list[1] 
    lw $t4, 8($t3)       # get the value list[2] 
 
3.2 Conditional Statement 
Assume $r1 stores i and $r2 stores j. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  
if ( i == j ) 
  i++ ; 
j-- ; 
         bne  $r1, $r2, L1     # branch if ! ( i == j )  
         addi $r1, $r1, 1      # i++  
L1:  addi $r2, $r2, -1     # j 
if ( i == j ) 
  i++ ; 
else 
  j-- ; 
j += i ; 
       bne  $r1, $r2, ELSE    # branch if ! ( i == j )  
       addi $r1, $r1, 1       # i++  
       j L1                    # jump over else  (ADD THIS!!!) 
ELSE:  addi $r2, $r2, -1      # j--  
L1:    add $r2, $r2, $r1      # j += i 
if ( i == j && i == k ) 
  i++ ;  // if-body  
else 
  j-- ;  // else-body  
j = i + k ; 
       bne  $r1, $r2, ELSE    # cond1: branch if ! ( i == j )  
       bne  $r1, $r3, ELSE    # cond2: branch if ! ( i == k )  
       addi $r1, $r1, 1       # if-body: i++  
       j L1                    # jump over else 
ELSE:  addi $r2, $r2, -1      # else-body: j--  
L1:    add $r2, $r1, $r3     # j = i + k 
if ( i == j | | i == k ) 
  i++ ;  // if-body  
else 
  j-- ;  // else-body  
j = i + k ; 
       beq  $r1, $r2, IF      # cond1: branch if ( i == j )  
       bne  $r1, $r3, ELSE    # cond2: branch if ! ( i == k )  
IF:    addi $r1, $r1, 1       # if-body: i++  
       j L1                    # jump over else  
ELSE:  addi $r2, $r2, -1      # else-body: j--  
L1:    add $r2, $r1, $r3      # j = i + k 
 3 
 
 
 
 
 
 
 
 
 
 
 
 
3.3 Loop Statement 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
There's only one special case. Suppose the  has a continue statement. Then, 
you need to jump to the  code, which is at the UPDATE label. 
 
Name Number Usage    Name Number Usage 
$zero 0 constant 0  $s0-$s7 16 temporary saved 
$at 1 reserved for assembler  $t8 24 temporary 
$v0 2 return value  $t9 25 temporary 
$v1 3 return value  $k0 26 reserved for OS kernel 
$a0 4 procedure argument 1   $k1 27 reserved for OS kernel 
$a1 5 procedure argument 2  $gp 28 pointer to global area 
$a2 6 procedure argument 3  $sp 29 stack pointer 
$a3 7 procedure argument 4  $fp 30 frame pointer 
$t0 8 temporary   $ra 31 return address 
$t1-$7 9 temporary      
 
  
while ( i < k ){ 
    k++ ; 
    i = i * 2 ; 
  } 
 
L1: if ( i < k ){ 
        k++; 
        i = i * 2;  
        goto L1; 
    } 
 
# $r1 = i and $r3 = k. 
L1:   bge  $r1, $r3, EXIT    # branch if ! ( i < k ) 
        addi $r3, $r3, 1           # k++ 
        add  $r1, $r1, $r1        # i = i * 2  
        j    L1                          # jump back  
EXIT: 
for (  ;  ;  ) 
 { 
       
  } 
 
 
L1:  if (  ) { 
                
UPDATE:     
           goto L1 ; 
       } 
EXIT: 
switch( i ) { 
 case 1: i++ ;  // falls through  
 case 2: i += 2 ; 
        break; 
 case 3: i += 3 ; 
} 
               addi $r4, $r0, 1       # set temp to 1  
               bne $r1, $r4, C2_COND  # case 1 false: branch to case 2 cond  
               j C1_BODY              # case 1 true: branch to case 1  
C2_COND:  addi $r4, $r0, 2       # set temp to 2  
               bne $r1, $r4, C3_COND  # case 2 false: branch to case 2 cond  
               j C2_BODY              # case 2 true: branch to case 2 body  
C3_COND:  addi $r4, $r0, 3       # set temp to 3  
               bne $r1, $r4, EXIT     # case 3 false: branch to exit  
              j C3_BODY              # case 3 true: branch to case 3 body  
C1_BODY:  addi $r1, $r1, 1       # case 1 body: i++  
C2_BODY:  addi $r1, $r1, 2       # case 2 body: i += 2  
               j EXIT                 # break   
C3_BODY: addi $r1, $r1, 3       # case 3 body: i += 3  
EXIT:    # j = i + k 
 4 
 
3.4 Function Calls 
 
Calling a subroutine is between a caller, who makes the subroutine call, and the callee, 
which is the subroutine itself. 
 The caller passes arguments to the callee by placing the values into the argument 
registers $a0-$a3. 
 The caller calls jal followed by the label of the subroutine. This saves the return 
address in $ra. 
 The return address is PC + 4, where PC is the address of the jal instruction 
 If the callee uses a frame pointer, then it usually sets it to the stack pointer. The 
old frame pointer must be saved on the stack before this happens. 
 The callee usually starts by pushing any registers it needs to save on the stack. If 
the callee calls a helper subroutine, then it must push $ra on the stack. It may 
need to push temporary or saved registers as well. 
 Once the subroutine is complete, the return value is place in $v0-$v1. 
 The callee then calls jr $ra to return back to the caller. 
 
The following give two examples of recursive function calls. 
 
Example 1: Sum all elements of an array. 
 
 
 
 
 
 
 
Assume arr is in $a0 and size is in $a1. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
int sum( int arr[], int size ) { 
       if ( size == 0 ) 
       return 0 ; 
       else 
       return sum( arr, size - 1 ) + arr[ size - 1 ] ; 
} 
sum:       addi $sp, $sp, -8        # Adjust sp 
         addi $t0, $a0, -1        # Compute size - 1 
        sw   $t0, 0($sp)         # Save size - 1 to stack 
         sw   $ra, 4($sp)         # Save return address 
         bne  $t0, $zero, ELSE    # branch ! ( size == 0 ) 
         li     $v0, 0              # Set return value to 0 
         addi $sp, $sp, 8         # Adjust sp 
         jr     $ra                   # Return 
 
ELSE:    move  $a1, $t0           # update second arg   
         jal     sum  
        lw     $t0, 0($sp)        # Restore size - 1 from stack 
         sll     $t1,  $t0,  2            # Multiple size - 1 by 4  
         add   $t1, $t1, $a0      # Compute & arr[ size - 1 ] 
         lw    $t2, 0($t1)        # t2 = arr[ size - 1 ] 
         add   $v0, $v0, $t2     # retval = $v0 + arr[size - 1] 
         lw    $ra, 4($sp)        # restore return address from stack          
         addi $sp, $sp, 8         # Adjust sp 
         jr $ra                    # Return 
 5 
 
Example 2: Sum only the odd elements of an array. 
 
 
 
 
 
 
 
 
The difficult part is to decide what registers to save.  
 arr is stored in $a0,  and it is not changed throughout.  
 size may need to be saved, though size - 1 appears to be more useful.  
 Since we make calls to sumOdd, we need to save $ra. 
So, let's save size - 1 and $ra to the stack. It turns out we also need to save arr[ size - 1 ] 
to the stack too. 
 
  
int sumOdd( int arr[], int size ) { 
   if ( size == 0 ) 
      return 0 ; 
   else if ( arr[ size - 1 ] % 2 == 1 ) 
      return sumOdd( arr, size - 1 ) + arr[ size - 1 ] ; 
   else 
      return sumOdd( arr, size - 1 ) ; 
} 
 
sumOdd:  addi $sp, $sp, -12       # Adjust sp 
          addi $t0, $a0, -1        # Compute size - 1 
          sw   $t0, 0($sp)         # Save size - 1 to stack 
          sw   $ra, 4($sp)         # Save return address 
          bne  $t0, $zero, ELSE2   # branch !( size == 0 ) 
          li   $v0, 0               # Set return value to 0 
          addi $sp, $sp, 12        # Adjust sp 
          jr   $ra                  # Return 
 
ELSE2:   sll $t1, $t0, 2            # Multiple size - 1 by 4  
          add   $t1, $t1, $a0      # Compute & arr[ size - 1 ] 
          lw    $t2, 0($t1)        # t2 = arr[ size - 1 ] 
          andi  $t3, $t2, 1        # is arr[ size - 1 ] odd 
          beq   $t3, $zero, ELSE3  # branch if even  
          sw    $t2, 8($sp)        # save arr[ size - 1 ] on stack  
          move  $a1, $t0           # update second arg   
 
        jal   sumOdd  
        lw    $t2, 8($sp)        # restore arr[ size - 1 ] from stack  
        add   $v0, $v0, $t2     # update return value  
        lw    $ra, 4($sp)        # restore return address from stack          
        addi  $sp, $sp, 12       # Adjust sp 
        jr    $ra                # Return 
 6 
4. Quick Reference of Mars 
 
4.1 User interface 
 
 
Pictures are obtained from http://courses.missouristate.edu/KenVollmar/MARS  
 7 
4.2 Comments and directives 
 “#” starts a comment 
 .text is a directive. A directive is a statement that tells the assembler something 
about what the programmer wants, but does not itself result in any machine 
instructions. This directive tells the assembler that the following lines are ".text" -
- source code for the program. 
 .globl main is another directive. It says that the identifier main will be used 
outside of this source file (that is, used "globally") as the label of a particular 
location in main memory (here, it is 0x00400020. The address of the 1
st
 
instruction). 
 .data starts the data segment. All of these are used in the data segment: 
.asciiz string Defines a null-terminated string (strings you output with a syscall must 
end with a null, which is a 00 in ascii) 
.byte b0,b1,b2 Defines and initializes subsequent bytes in memory 
.half h0,h1,h2 
 
Defines and initializes subsequent half-words (16-bit values) in memory 
– alignment forced to next even address 
.word w0,w1,w2 
 
Defines and initializes subsequent words (32-bit values) in memory – 
alignment forced to next word address (multiple of 4) 
.space n  allocates n bytes of space 
 Identifier names are sequence of letters, numbers, underbars (_) and dots (.). 
 Labels are declared by putting them at beginning of line followed by colon.  Use 
labels for variables and code locations. 
 Instruction format: op field followed by one or more operands: addi $t0, $t0, 1 
 Operands may be literal values or registers. 
 Register is hardware primitive, can stored 32-bit value: $s0 
 Numbers are base 10 by default.  0x prefix indicates hexadecimal. 
 Strings are enclosed in quotes.  May include \n=newline or \t=tab.  Used for 
prompts. 
 
4.3 Endianness 
 
Endianness is the byte ordering used to represent data. The two orders are called "Little 
Endian" and "Big Endian".  
 
Little Endian means that the low-order byte of the number is stored in memory at the 
lowest address, and the high-order byte at the highest address. (The little end comes first.) 
For example, a 4 byte LongInt 
Byte3 Byte2 Byte1 Byte0 
will be arranged in memory as follows: 
Base Address+0    Byte0 
Base Address+1    Byte1 
Base Address+2    Byte2 
Base Address+3    Byte3 
 
Intel processors (those used in PC's) use "Little Endian" byte order. 
 
 8 
Big Endian means that the high-order byte of the number is stored in memory at the 
lowest address, and the low-order byte at the highest address. (The big end comes first.) 
Our LongInt, would then be stored as: 
Base Address+0    Byte3 
Base Address+1    Byte2 
Base Address+2    Byte1 
Base Address+3    Byte0 
 
Motorola processors (those used in Mac's) use "Big Endian" byte order. 
 
4.4 Data Storage in Memory 
For ASCII, every character is represented by its corresponding ASCII code (a byte). For 
example,  
str: .asciiz “the answer = ” 
 
You will see the following in PCSPim (in a system with little endianness). 
           [0x10010000] 0x20656874 0x77736E61 0x3D207265 0x00000020 
 
The data represents: 
 
 
Address Data(hex)  
1001000F 00 undefined 
1001000E 00 undefined 
1001000D 00  
1001000C 20  
1001000B 3D = 
1001000A 20  
10010009 72 r 
10010008 65 e 
10010007 77 w 
10010006 73 s 
10010005 6E n 
10010004 61 a 
10010003 20  
10010002 65 e 
10010001 68 h 
10010000 74 t 
 
Here is another example:  
#specify some data to be loaded into memory 
.data 
nums:  .byte 1,2,3,4 
.half 5,6,7,8 
.word 9,10,11,12 
.space 5 
.word 9,10,11,12 
.asciiz “ABCD” 
 9 
.ascii “ABCD” 
.byte -1 
.text 
.globl main 
main: li $v0,10  #sys call for exit 
syscall 
 
After loading the program, the data display would show: 
DATA 
[0x10010000] 0x04030201 0x00060005 0x00080007 0x00000009 
[0x10010010] 0x0000000A 0x0000000B 0x0000000C 0x00000000 
[0x10010020] 0x00000000 0x00000009 0x0000000A 0x0000000B 
[0x10010030] 0x0000000C 0x44434241 0x43424100 0x0000FF44 
 
Address Data 
1001003C 0000FF44 
10010038 43424100 
10010034 44434241 
10010030 0000000C 
1001002C 0000000B 
10010028 0000000A 
10010024 00000009 
10010020 00000000 
1001001C 00000000 
10010018 0000000C 
10010014 0000000B 
10010010 0000000A 
1001000C 00000009 
10010008 00080007 
10010004 00060005 
10010000 04030201 
 10 
ECE 473 Computer Architecture and Organization 
Fall 2013 
Lab Assignment 4 
 
 
1. String handling [30 points] 
Declare a string in the data section: 
.data 
string: .asciiz "ABCDEFG" 
Write a program that converts the string to all lower case characters.  
Hint: add 0x20 to each character in the string. 
 
 
2. Pointers [30 points] 
Write a program in MIPS assembly language that will compute the sum of all the 
elements in an array. Write this program using a function “PSum”, which takes two 
parameters, including a pointer to the running sum and a pointer to the current element. 
The “C” function looks like this: 
int sum = 0; int *sump = ∑ 
int a[10]; 
void PSum(int *s, int *e) { 
     *s += *e; 
} 
int main() { 
    for (int i=0; i<10; i++) { 
        a[i] = i; 
    } 
    for (int i=0; i<10; i++) { 
        PSum(sump, a+i); 
    } 
} 
 
3. Recursion [40 points] 
Write a program in MIPS Assembly Language that to find fix(i, x), where fix(i, x) is 
defined recursively as: 
int fix(int i, int x) { // assume i > 0, x > 0 
    if (x>0) 
        return fix(i, x-1); 
   else if (i>0) 
       return fix(i-1, i-1)+2; 
   else 
       return 0; 
} 
  
 11 
ECE 473 Lab Check off Sheet 
Lab 4: MIPS Assembly Programming 
Fall 2013 
 
Student Name: _______________________________ 
TA: ___________________________________ 
Time & Date: ________________________ 
 
 
1. String Manipulation (30%) 
 
 
 
 
 
 
 
 
2. Pointers (30%) 
 
 
 
 
 
 
 
 
 
3. Recursion (40%) 
 
 
 
 
 
 
 
 
 
 Total