Starting from:
$35

$29

Computer Architecture and Design Lab 2 Solution

1. A simple MIPS program [25 points]
Write a MIPS program that takes a value in $s1 and stores a value as "2^i * $s1" into each of eight registers $ti (0 <= i <= 7). For example, if $s1 is 3, registers $t0 through $t7 will have the following values:
$t0 = 3 (3*2^0)

$t1 = 6 (3*2^1)

$t2 = 12 (3*2^2)



...



$t7 = 384 (3*2^7)

Hint: You don't need to use any multiplcation operation. It can be implemented only with "add" operation.
At the top of your program, put main: (the word "main" followed by a colon). "main:" is a MIPS assembly language label. This label tells SPIM assembler the starting point of the program. You can put the label in column 1, to the left of the first instruction, or on a separate line.
At the end of your program, add the following two instructions to notify the Operating System to regain control when the program execution is done.
        addi    $v0,    $0,     10      # Move "exit" system function code to argument reg

        syscall                         # Request the OS to carry out the program exit

Save your code as "Lab2_1.s" and load it into SPIM using "File->Open". Before you run the program, set register $s1 to some value using "Simulator->Set value...". Then run the program using "Simulator->Go". If the program does not have any syntax error, the message "successfully loaded" will appear in the "Messages" window when you load the program. Run your program and examine the register values.
For this part you may want to check the register values in decimal rather than hexadecimal format. Under the "Simulator->Settings" menu option, uncheck "General registers in hexadecimal", if the registers don't show values in decimal format.
Check-off Requirement: Have your TA watch you run your program.

2. Translation from C to MIPS [30 points]
Convert the following C program into a MIPS program:
int B[4] = { 300, 200, 100, 0 };

int i = 3;

void main ( void )

{

    B[i] = B[0] + B[1] + B[2];

}

This program has two variables, an integer array B and an integer i. It adds the first three array elements together and stores the result in the last element. To get started, use the following code.
.data 0x10008000                        # data segment start (assembler directive)

B:      .word 300                       # B[0]

        .word 200                       # B[1]

        .word 100                       # B[2]

        .word 0                         # B[3]

i:      .word 3

.text                                   # code segment start (assembler directive)

main:   la      $t1,    B               # load the address of B[0] (&(B[0]) == B) into register $t1

        lw      $t0,    0($t1)          # load value of B[0] into register $t0

        ##

        ## COMPLETE HERE. ##

        ##

        addi    $v0,    $0,     10      # `exit MIPS program' syscall

        syscall

This code gives you a partial solution to the problem. Your task is to complete the program by adding the missing MIPS instructions. Recall that in MIPS large data structures like arrays are stored in a memory, not in the registers. To move data from the memory to the register, use the "load word" instruction (lw). In the above program, "lw $t0, 0($t1)" loads the first array element (B[0]) to the register $t0. The format of lw is "lw $rt, offset_16bit($rs)", where $rt is a register to receive data and offset_16bit($rs) has an effective address (EA) (the address of the word in the memory to be fetched) for data. In MIPS, EA is determined by base register and offset. Base register ($rs) has a "base address" of the memory. Offset (offset_16bit) has a 16-bit signed integer.
Here, let's see how to get EA of the first element (B[0]) in array B. In C, you can get EA by using *B[0] or simply referring to B, the array name without a subscript. In MIPS, we use "load address" pseudo-instruction, la. In the above program, the instruction after the label main:, "la $t1, B", shows a pseudo-instruction example. It makes the SPIM assembler load the memory address of B into register $t1. Then the next instruction "lw $t0, 0($t1)" fetches a word from memory at location "$t1 + 0". Complete the program for loading the second and third elements of array B to registers, summing up three values, and store the sum in the forth element of array B.
Save your code as "Lab2_2.s" and run it in PCSpim.
Notes
    • .data and .text are assembler directives. They specify which part of the memory will be used for data or instructions during run-time. Other assembler directives can be found here.
    • Each element of the array is offset by four bytes, because MIPS uses four bytes (one word) to store an integer. MIPS memory uses byte addressing.
Check-off Requirement: Allow TA to view your program in the text editor and demonstrate program execution in SPIM.

3. Console input [10 points]
Write a MIPS program to get user input from keyboard and store value you enter to $s0 register. This program will print a prompt message on the PCSpim console window, and then wait for user input.
Step 1: As shown in Part 2, add .data and .text assembler directives to your program.
Step 2: Define a prompt message in data segment.
mesg: .asciiz "Enter the value for register s1:"

The assembler directive .asciiz says that a type of the mesg variable is a null-terminated string (exactly the same as in C language). The string value is enclosed by quotes.
Step 3: Add the following codes in text segment to print the message on console.
la      $a0,    mesg            # Load effective address(mesg) to $a0

addi    $v0,    $0,     4       # Load constant 4 to reg v0

syscall                         # Switch into the "kernel" to print 'mesg' out

Take a look at explanation about these three instructions.
    1. "la $a0, mesg" loads the memory address of the string variable mesg into register $a0.
    2. "addi $v0, $0, 4" loads a constant 4 into register $v0. 4 is used for Operating System to perform the "print string" operation. This instruction literally means "store the result of $0+4 into register $v0". Because register $0 has a constant 0, the result of this instruction is to copy the immediate constant 4 to register $v0.
    3. "syscall" instruction invokes operating system to perform a task on behalf of the calling program, in this case, to print a string on the console. syscall is used when a system procedure call is required. Arguments for the procedure are passed by two registers, $a0 and $v0. After a system procedure is finished, OS forwards control to the user program.
Step 4: Add the following codes to get keyboard input from a user.
addi    $v0,    $0,     5       # reg v0 = 5

syscall

Take a look at explanation about these two instructions.
    1. "addi $v0, $0, 5" loads the constant value 5 in to register $v0. System call 5 is used for "input number" operation.
    2. When "syscall" is executed with $v0=5, your program will allow a user to input a number from a keyboard. The input number is stored to register $v0.
Since we are using "exit" system call at the end of the program, put those instructions after "read integer" system call to copy the value to $s0.
        add     $s0,    $v0,    $0

Save your code as "Lab2_3.s" and run it in PCSpim.
Check-off Requirement: Allow TA to view your program in the text editor and demonstrate program execution in SPIM.

Submission Requirement
Turn in three source files (Lab2_1.s, Lab2_2.s, and Lab2_3.s).

More products