sections in this module City College of San Francisco - CS270
Computer Architecture

Module: MIPS-II (Decisions)
module list

Problems

Problem One - comparing branch instructions

Let's compare these three techniques using a section of code from a simple example from a section of a sort function:

if (a < b) {
temp=b;
b = a;
a= temp;
}

Translating to gotos:

if !(a < b) goto .L4  # (this is also if (a >= b) goto .L4)
temp=b;
b = a;
a= temp;
.L4:

We will now translate this to MIPS code, with the following assumptions:

We will translate the code without using pseudoinstructions so we can see how many actual instructions there are. (We have added the lower 16-bits of the instruction's address to the listing)

address
code using branch
code using jump (j)
code using jump reg (jr)
0x401040
0x401044
0x401048
0x40104C
0x401050
0x401054
0x401058
0x40105C
0x401060
slt   $t2,$t0,$t1
beq   $t2,$zero,.L4
move  $t3,$t1
move  $t1,$t0
move  $t0,$t3
.L4:
slt  $t2,$t0,$t1
bne  $t2,$zero,.L5
j    .L4
.L5: move  $t3,$t1
move $t1,$t0
move $t0,$t3
.L4:
slt  $t2,$t0,$t1
bne  $t2,$zero,.L5
lui  $at,0x0040
ori  $t3,$at,0x1060
jr   $t3
.L5: move  $t3,$t1
move $t1,$t0
move $t0,$t3
.L4:

You can see that the sequence using the branch instruction is shorter.

Last, let's go through the encoding of each of our branching instructions:


beq   $t2,$zero,.L4

This is a regular I-type instruction with opc=4, rs=10 and rt=0. The current PC is 0x401048 (the next instruction, remember?) and the target is 0x401054, so it is 12 bytes, or three instructions, away. Thus, imm = 3

op
rs
rt
imm


1
1
4
0
0
0
0
3

j    .L4

The address of .L4 in the second sequence is 0x401058. Right-shifting this by 2 bits yields 0x100416. The opc is 2 and the remaining 26 bits of the instruction hold this word address:

op
imm


0
8
1
0
0
4
1
6

jr  $t3

This is a modified R-type instruction where only the rs register is used. The opcode=0, the funct=8 and, in our case, rs=11:

op
rs
rt
rd
shamt
funct


0
1
6
0
0
0
0
8

Problem Two - outelement

Write a MIPS program to output A[i] from an int array A[5] initialized with the values 4,-15,22,6,8.  Your code should request the index from the user using I/O, then output the array element. If the index is less than 0 or greater than 4, output an error message.

This program does not use a loop. Simply allow one attempt at accessing the array, then exit.

Step One

Write an algorithm for the program, using the following prototype for retrieving an integer from the user and outputting an integer value with a message

extern int error;
void message_int(char *message, int value);
int get_int(char * prompt);

This corresponds to InputDialogInt and MessageDialogInt syscall. The error variable is the status returned by the Input syscall.

int A[5] = {4,-15,22,6,8};
int index;
main() {
index=get_int("Enter index:");
if (error != 0) {
printf("Cannot get index");
exit;
}
if ((index < 0) || (index > 4)) {
printf("index must be between 0 and 4\n");
exit;
}
message_int("A[index] = ",A[index]);
return;
}

Step Two

Rewrite this algorithm using gotos and labels. Make a single exit.

int A[5] = {4,-15,22,6,8};
int index;
main() {
index=get_int("Enter index:");
if (error == 0) goto goodindex;
printf("Cannot get index");
goto doexit;
goodindex:
if (index < 0) goto illegalindex;
if (index > 4) goto illegalindex;
goto goodindex1;
illegalindex:
printf("index must be between 0 and 4\n");
goto doexit;
goodindex1:
message_int("A[index] = ",A[index]);
return
doexit:
exit;
}

Finally, code this in MIPS. In this code we have intermixed the data and text segments much the way a compiler would generate them. This is not good coding style for a real assembler program, but it makes it easier to translate. We will make it prettier at the end.

#
# outelement.s
#
# int A[5] = {4,-15,22,6,8};
    .data
    .globl A
A:  .word  4,-15,22,6,8
# int index;
    .globl index
index:     .space 4
# main() {
    .text
    .globl main
main:
# index=get_int("Enter index:");
    li   $v0,51
    .data
.prompt: .asciiz "Enter index:"
    .align 2
    .text
    la   $a0,.prompt
    syscall
    sw   $a0,index
# if (error == 0) goto goodindex;
    beq  $a1,$zero,.goodindex
# printf("Cannot get index");
    li   $v0,55
    .data
.msg1:  .asciiz "Cannot get index"
    .align 2
    .text
    la   $a0,.msg1
    syscall
# goto doexit;
    b   .doexit
# goodindex:
.goodindex:
# if (index < 0) goto illegalindex;
    lw   $t0,index
    blt  $t0,$zero,.illegalindex
# if (index > 4) goto illegalindex;
    li   $t1,4
    bgt  $t0,$t1,.illegalindex
# goto goodindex1;
    b    .goodindex1
# illegalindex:
.illegalindex:
# printf("index must be between 0 and 4\n");
    li   $v0,55
    .data
.msg2:  .asciiz "index must be between 0 and 4\n"
    .align 2
    .text
    la   $a0,.msg2
    syscall
# goto doexit;
    b   .doexit
# goodindex1:
.goodindex1:
# message_int("A[index] = ",A[index]);
    li    $v0,56
    sll   $t0,$t0,2
    la    $t1,A
    add   $t1,$t1,$t0
    lw    $a1,0($t1)
    .data
.msg3:  .asciiz "A[index] = "
    .align 2
    .text
    la    $a0,.msg3
    syscall
# return
    jr    $ra    # exit main() (normal exit)
# exit;
# doexit:
.doexit:
    li   $v0,10
    syscall
# }

Finally, merging the .data portions so that it is prettier, we get the final version:

#
# outelement1.s
#
# int A[5] = {4,-15,22,6,8};
    .data
    .globl A
A:  .word  4,-15,22,6,8
# int index;
    .globl index
index: .space 4
# messages and prompts
.prompt: .asciiz "Enter index:"
.msg1:  .asciiz "Cannot get index"
.msg2:  .asciiz "index must be between 0 and 4\n"
.msg3:  .asciiz "A[index] = "
    .align 2

# main() {
    .text
    .globl main
main:
# index=get_int("Enter index:");
    li  $v0,51
    la  $a0,.prompt
    syscall
    sw  $a0,index
# if (error == 0) goto goodindex;
    beq    $a1,$zero,.goodindex
# printf("Cannot get index");
    li  $v0,55
    la  $a0,.msg1
    syscall
# goto doexit;
    b  .doexit
# goodindex:
.goodindex:
# if (index < 0) goto illegalindex;
    lw  $t0,index
    blt $t0,$zero,.illegalindex
# if (index > 4) goto illegalindex;
    li  $t1,4
    bgt $t0,$t1,.illegalindex
# goto goodindex1;
    b   .goodindex1
# illegalindex:
.illegalindex:
# printf("index must be between 0 and 4\n");
    li  $v0,55
    la  $a0,.msg2
    syscall
# goto doexit;
    b  .doexit
# goodindex1:
.goodindex1:
# message_int("A[index] = ",A[index]);
    li  $v0,56
    sll $t0,$t0,2
    la  $t1,A
    add $t1,$t1,$t0
    lw  $a1,0($t1)
    la  $a0,.msg3
    syscall
# return
    jr  $ra    # exit main() (normal exit)
# exit;
# doexit:
.doexit:
    li  $v0,10
    syscall
# }

There are a lot of optimizations that can be done in this code, but we should move on.

outelement.s and outelement1.s are in the online/mipsII directory in the public work area on hills


Prev This page was made entirely with free software on linux:  
the Mozilla Project
and Openoffice.org    
Next

Copyright 2012 Greg Boyd - All Rights Reserved.