Mips - Array initialization and index value output - mips

#include<stdio.h>
int main() {
int a[] = { 1,2,3,4,5,6,7,8,9,10 };
int b[] = { 1,2,3,4,5,6,7,8,9,10 };
int f = 0;
int f1 = 0;
int h = 0;
int g = 0;
printf("Please, type a number for g:");
scanf_s("%d", &g);
printf("Please, type a number for h:");
scanf_s("%d", &h);
f = -g + b[h];
f1 = a[b[g] + 1];
printf("The 1st result is:%d\n", f);
printf("The 2nd result is:%d\n", f1);
return 0;
}
I want to convert this c language into mips.I tried this, but there was an error. What should I do?
Below is my code
Maybe this code has problem at Array. I'm not used to using it.
Please tell me the problem and solution.
.globl main
.data
A: .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
B: .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
str1:.asciiz"Please, type a number for g:"
str2:.asciiz"Please, type a number for h:"
str3:.asciiz"The 1st result is:"
str4:.asciiz"The 2nd result is:"
.text
main:
li $v0,4 #print str1
la $a0,str1 #str1
syscall
li $v0, 5 #input g
syscall
move $s1, $v0 #$s1= g
li $v0,4 #print str2
la $a0,str2 #str2
syscall
li $v0, 5
syscall
move $s2, $v0 # $s2 = h
sll $t0,$s2,2 # t0 = 4 * h
add $t0,$t0,$s7 # address of B[h]
lw $t0,0($t0) # t0 = B[h]
sub $s0,$t0,$s1
move $t3,$s0
sll $t0,$s1,2 # t0 = 4 * g
add $t0,$t0,$s7 # t0 = address of B[g]
lw $t0,0($t0) # t0 = B[g]
addi $t0,$t0,1 # t0 = B[g]+1
sll $t0,$t0,2
add $t0,$t0,$s6
lw $s0,0($t0) # f= A[B[g] +1]
move $t4, $s0
li $v0,4 #print str3
la $a0,str3 #str3
syscall
move $a0,$t3
li $v0,1
syscall
li $v0,4 #print str4
la $a0,str4 #str4
syscall
move $a0,$t4
li $v0,1
syscall
li $v0,10
syscall
I don't know why there's an error because I'm not very good at mips. Please help me.

Related

Reverse the order of user inputted string

goodafternoon, i made this code that takes in user input and reverses the order. the code works perfectly except when there is long user input such the alphabet. in this case the output excludes the last letter, i am unsure why this is and any insight would be greatly appreciated.
.data
.align 2
array: .space 80
size: .word 20
string: .space 20000
op: .asciiz "Enter n, followed by n lines of text:"
prompt: .asciiz ""
text: .asciiz "The values are:"
newline: .asciiz "\n"
.text
.globl main
main:
#prompt user for array length
li $v0,4
la $a0,op
syscall
jal new_line #output newline
#read in array count
li $v0,5
syscall
addi $s0,$v0,0 #$v0 contains the integer we read
add $t0,$zero,$zero #index of array
addi $t1,$zero,1 #counter=1
la $s2,string #load address of string storage area
read_string:
bgt $t1,$s0,L1 #if ($t1 > length) then array is done
# prompt the user for next string
li $v0,4
la $a0,prompt
syscall
#get the string
move $a0,$s2 #place to store string
li $a1,20
li $v0,8
syscall
#store pointer to string into array
sw $a0,array($t0)
addi $t0,$t0,4 #advance offset into pointer array
addi $t1,$t1,1 #advance iteration count
addi $s2,$s2,20 #advance to next string area
j read_string
#### here i want to print the array ####
L1:
addi $t1,$zero,1 #counter = 1
#output the title
la $a0,text
li $v0,4
syscall
jal new_line
while:
addi $t0,$t0,-4 #advance array index
bgt $t1,$s0,done #if no more strings to output then done
lw $t2,array($t0) #get pointer to string
#output the string
li $v0,4
move $a0,$t2
syscall
addi $t1,$t1,1 #advance count
j while
new_line:
la $a0,newline
li $v0,4
syscall
jr $ra
done:
li $v0,10
syscall
if the user enters a n value of 26 and following lines a b c d e f g h i j k l m n o p q r s t u v w x y z then the output should be z y x v u t s r q p o n m l k j i h g f e d c b a. However what is outputted is this: z y x v u t s r q p o n m l k j i h g f e d c b. so its missing the letter a
From what I can tell, the problem is that you're ending the loop one pass too early.
while:
addi $t0,$t0,-4 #advance array index
bgt $t1,$s0,done #if no more strings to output then done
Here, you're effectively comparing $s0 to 26, since that's the whole alphabet size.
But since you started $t1 as equaling 1, you're encountering an "off-by-one" error most likely.
When compilers implement a loop like while(count < 26), often they don't do this literally like you have done here. It's usually easier to do the following:
#read in array count
li $v0,5
syscall
addi $s0,$v0,1 #$v0 contains the integer we read plus 1.
# do your other stuff here
while:
addi $t0,$t0,-4 #advance array index
lw $t2,array($t0) #get pointer to string
#output the string
li $v0,4
move $a0,$t2
syscall
addi $s0,$s0,-1
bnez $s0,while
Since you're only adding 1 to your count variable it's easier just to make it a downward for-loop (as I said eariler, a C compiler typically does this even if you declare the loop as a while.)
Sometimes you just need to adjust your loop counter by 1 and that may be enough to fix things.

MIPS - how to write a for loop while also accessing and saving arrays

I won't lie, I'm a total beginner at programming in general with my first time being last year when I started programming in Computer Programming I. A lot of this is still over my head so uh... go easy on me will ya?
The question poised is as follows:
"1. (5 pts) Translate the following C code to MIPS. Assume that the variables i and j are assigned to registers $s0 and $s1, respectively. Assume that the base address of the arrays A and B are in registers $s6 and $s7, respectively. Assume that the elements of the arrays A and B are 4-byte words:
for (i = 0; i< j; i++)
B[i] = A[i+1] - A[i];
For my program I wrote:
.data
arrayA: .word 5,8, 12, 13, 28
sizeA: .word 5
arrayB: .space 4
i: .word 0
_j: .word 5
.text
# for (i = 0; i< j; i++)
# B[i] = A[i+1] - A[i];
main:
la $s6, arrayA #loads the base address of arrayA into register s6
la $s7, arrayB #loads the base address of arrayB into register s7
lw $s0, i #Loads zero into register s0 for i
lw $s1, _j #loads the value of 4 into register s2 for j
Loop:
beq $s0, $s1, Exit #Does the operation i < j in the for-loop
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
mul $t0, $s0, 4 #Get address of i
add $t1, $t0, $s6 #Finds and stores the base address of a[i]
add $t2, $t0, $s7 #Finds and stores the base address of b[i]
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
sub $t5, $t4, $t3 #subtracts a[i + 1] and a[i]
sw $t5, ($t2) #Stores the above into b[i]
add $a0, $zero, $t5
li $v0, 1
syscall
J Loop #loops back to beginning
Exit:
li $v0 10
syscall #syscall to exit the program
When I run it, it spits out 33333, which means it isn't incrementing. How do I fix this?
arrayA: .word 5,8, 12, 13, 28
may be wrong. You didn't add a space between 5, and 8 while giving spaces between the other elements. My QtSpim Version 9.1.21 didn't accept that.
arrayB: .space 4
is wrong. You are allocating only 4 bytes while space for 4 words (16 bytes) is required.
_j: .word 5
is wrong. The stored value is 5 despite of the comment saying "loads the value of 4 into register s2 for j". Using value 5 is wrong also because the array a has only 5 elements.
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
is in the wrong place. The increment should be after the loop body.
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
is wrong. The address of a[i] is stored in $t1, so you should use that.
J Loop #loops back to beginning
may be wrong. You used an uppercase letter for instruction name only here. At least my QtSpim Version 9.1.21 didn't accept that.
li $v0 10
may be wrong. You didn't use a comma for separating the operands while you used that in previous use of li: li $v0, 1. I'm surprised by seeing my QtSpim Version 9.1.21 accepting this.
Fixed code:
.data
arrayA: .word 5, 8, 12, 13, 28
sizeA: .word 5
arrayB: .space 4 * 4
i: .word 0
_j: .word 4
.text
# for (i = 0; i< j; i++)
# B[i] = A[i+1] - A[i];
main:
la $s6, arrayA #loads the base address of arrayA into register s6
la $s7, arrayB #loads the base address of arrayB into register s7
lw $s0, i #Loads zero into register s0 for i
lw $s1, _j #loads the value of 4 into register s2 for j
Loop:
beq $s0, $s1, Exit #Does the operation i < j in the for-loop
mul $t0, $s0, 4 #Get address of i
add $t1, $t0, $s6 #Finds and stores the base address of a[i]
add $t2, $t0, $s7 #Finds and stores the base address of b[i]
lw $t3, ($t1) #get the value of a[i]
lw $t4, 4($t1) #get the value of a[i + 1]
sub $t5, $t4, $t3 #subtracts a[i + 1] and a[i]
sw $t5, ($t2) #Stores the above into b[i]
add $a0, $zero, $t5
li $v0, 1
syscall
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
j Loop #loops back to beginning
Exit:
li $v0, 10
syscall #syscall to exit the program
Don't mix friendly register names with the raw register names — very confusing.
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
Here you're mixing $t3, $t4, $s6, and $10, which is actually $t2.
Your assembly code is doing the following C code (modulo the above bug):
int *s6 = A;
int *s7 = B;
for ( int i = 0; i != j; ) {
i++;
int *t1 = s6 + i; // i is automatically scaled by C
int *t2 = s7 + i; // ditto
int t3 = *s6; // A[0]
int t4 = s6[1]; // A[1]
int t5 = t4 - t3;
*t2 = t5; // B[i]=...
}
Can you see why it keeps loading A[0] & A[1]?
You should have noticed these problems during single stepping debugging.  After each step, check that every effect you're expecting happens as you expect.  When it doesn't, look for typos or logic problems.

Why is MIPS printing memory locations on the second time around

[Solved]
We were tasked with writing a bubble sort in MIPS and printing both the unsorted and sorted arrays
I've written the following code to accomplish this.
But when I go to run it, the original array prints as I would expect
Original Array
[34, 23, -1, -2, 0]
But then it prints this for the sorted array.
Sorted Array
[173496791, 1818324585, 1920090400, 686433, 1919898378]
(the Unicode squares do print)
array: .word 34, 23, -1, -2, 0, 89
length: .word 6
original: .asciiz "Original Array\n"
sorted: .asciiz "\nSorted Array\n"
.text
# main()
main:
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
la $a1, array # a1 = &array[0]
addi $t0, $0, 0 # for t0=0 to
addi $a2, $a2, -1 # because we do [i+1]
#says prints original array
la $a0, original
li $v0, 4
syscall
#prints array
jal print
#printing the string saying sorted
la $a0, sorted
li $v0, 4
syscall
#after printing original we reset the values?
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
add $t8, $0, $0 # t10 : counter 2
la $a1, array # a1 = &array[0]
addi $t0, $0, 0 # for t0=0 to
addi $a2, $a2, -1 # because we do [i+1]
#see if that worked it did
li $s0, 1 #boolean swapped = false 0=false 1=true
outerLoop:
beqz $s0, exit #if flag is false exit
li $s0, 0
addi $a1, $a1, 4 # next array offset
addi $t9, $t9, 1 # counter++
move $t8 $0
sub $s2, $a2, $t9
innerLoop:
bge $t8, $s2, exitInner
lw $t7, 0($a1) # t7 = array[i]
lw $t8, 4($a1) # t8 = array[i+1]
ble $t7, $t8, skip #if array[i]<= arr[i+1] skip the swapping
sw $t8, 0($a1) #a[i+1] = a[1]
sw $t7, 4($a1) #a[i] = a[i+1]
li $s0, 1#flag update
skip:
addi $t8, $t8, 1 #count
addi $a1, $a1, 4
j innerLoop
exitInner:
j outerLoop
exit:
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
addi $a2, $a2, -1 # because we do [i+1]
jal print
j quit#end Program
#print array
print:
lw $t7,0($a1) # t7 = array[i]
lw $t8,4($a1) # t8 = array[i+1]
add $a0, $t7, 0
addi $v0, $0, 1 #print int using system call the value stored in a0
syscall
addi $a0, $0, 0x20 # ascii 0x20 = ' '
addi $v0, $0, 11
syscall
addi $a1, $a1, 4 # next array offset
addi $t9, $t9, 1 # counter++
beq $t9, $a2, return #return to the where we were we were at beforehand
j print
return:
jr $ra
quit:
addi $v0, $0, 10
syscall
I think these are memory locations? I'm not sure why it's printing that as it is because I reset my counter values before trying to print. So the question is. Why am I printing memory locations? if that is what is happening
I was sorting in place so I had to reset the array before the print function.

convert C factorial code to MIPS factorial

I'm having trouble with converting the following C code to MIPS
#include <stdio.h>
int main (void)
{
int n = 0;
printf ("n = ");
scanf ("%d", &n);
int fac = 1;
for (int i = 1; i <= n; i++)
fac *= i;
printf ("n! = %d\n", fac);
return 0;
}
My code is not printing out the expected result, but it could successfully print "n:" etc.
### Global data
.data
msg1:
.asciiz "n: "
msg2:
.asciiz "n! = "
eol:
.asciiz "\n"
### main() function
.data
.align 2
.word 4
.text
main:
la $a0, msg1
li $v0, 4 #printf("n: ")
syscall
li $v0, 5 #scanf("%d", &n)
syscall
li $t0, 1
li $t1, 1
mul $t1, $t1, $t0 #t1 = t1*t0
add $t0, $t0, 1 #t0 = t0+1
la $a0, msg2
li $v0, 4 #printf("n!= ")
syscall
li $v0, 1 #print %d
la $a0, eol
li $v0, 4 #printf("\n")
syscall
li $v0, 0
jr $ra #return from main
My code does not produce any output, so I guess something may have went wrong in my loop
You are doing the loop section of the code that correwpods to the for loop in the c code, and you are not setting the value and calling syscall for the printf("%d") code.
### Global data
.data
msg1:
.asciiz "n: "
msg2:
.asciiz "n! = "
eol:
.asciiz "\n"
### main() function
.data
.align 2
.word 4
.text
main:
la $a0, msg1
li $v0, 4 #printf("n: ")
syscall
li $v0, 5 #scanf("%d", &n)
syscall
move $t2, $v0 # n = t2
li $t0, 1 # i = 1
li $t1, 1 # fact = 1
loop:
bgt $t0, $t2, end_loop # i > b - stop looping
mul $t1, $t1, $t0 #t1 = t1*t0
add $t0, $t0, 1 #t0 = t0+1
j loop
end_loop:
la $a0, msg2
li $v0, 4 #printf("n!= ")
syscall
li $v0, 1 #print %d
move $a0, $t1
syscall
la $a0, eol
li $v0, 4 #printf("\n")
syscall
li $v0, 0
jr $ra #return from main

how do I implement a jump address table in MIPS64? [duplicate]

C++ Program
# include < iostream >
# include <string >
using namespace std;
int main ()
{
int resistance ; // in Ohms
string partNum ; // Part Number
cout << " Enter resistance : " << endl ;
cin >> resistance ;
switch ( resistance )
{
case 3 : partNum = " OD30GJE "; break ;
case 10 : partNum = " OD100JE "; break ;
case 22 : partNum = " OD220JE "; break ;
default : partNum = "No match "; break ;
}
cout << " Part number : " << partNum << endl ;
return 0;
}
Translate the C code to MIPS assembly code, add to your code the capability to match the closest resistor. Be sure to use the jr instruction for the switch statement. Have your code get the resistance as input from the user and display to the console the resistor's corresponding or closest part number.
Mips Assembly Code
.data
int_value: .space 20
.align 2
input: .asciiz "Enter resistance.\n" # declaration for string variable,
string1: .asciiz "OD30GJE\n" # declaration for string variable,
string2: .asciiz "OD100JE\n"
string3: .asciiz "OD220JE\n"
string11: .asciiz "No Match\n"
string12: .asciiz "Enter resistance\n"
.text
main:
li $v0, 4
la $a0, input # print for input
syscall
la $t0, int_value
li $v0, 5 # load appropriate system call code into register $v0;
syscall # call operating system to perform operation
sw $v0, int_value # value read from keyboard returned in register $v0;
# store this in desired location
lw $s1, 0($t0)
condition1:
slt $t1, $s1, $zero # if $s1 < 0 $t1 = 1 else $t1 = 0
beq $t1, $zero, condition2 # if $t1 = 0; InvalidEntry
bne $t1, $zero, invalid_entry
condition2:
sgt $t1, $s1, -1 # if $s1 > -1 then $t1 = 1 else $t1 = 0
beq $t1, $zero, invalid_entry # if $t1 = 0; InvalidEntry
sgt $t1, $s1, 9 # if s1 > 9 t1 = 1 else $t1 = 0
bne $t1, $zero, condition3 # if $t1 does not equal = 0; condition3
li $v0, 4
la $a0, string1
syscall
j exit
condition3:
sgt $t1, $s1, 9 # if $s1 > 9 then $t1 = 1 else $t1 = 0
beq $t1, $zero, invalid_entry # if $t1 = 0; InvalidEntry
sgt $t1, $s1, 21 # if s1 > 21 t1 = 1 else $t1 = 0
bne $t1, $zero, condition3 # if $t1 does not equal = 0; condition3
li $v0, 4
la $a0, string2
syscall
j exit
invalid_entry:
li $v0, 4
la $a0, string11
syscall
j exit
exit:
li $v0, 10 # v0<- (exit)
syscall
The following shows how to make a jump table. The offset within the jump table is assumed to be in $s1. $s1 must be a multiple of 4 (i.e. a byte offset).
This code has not been tested!
. . . .
b 1f # jump past the jump table
nop # branch delay slot
# table of jump addresses
JTAB: .word LABEL1
.word LABEL2
.word LABEL3
1: la $t0, JTAB # load start address of the jump table
add $t0, $t0, $s1 # add offset to table address
lw $t1, 0($t0) # load the address stored at JTAB + $s1
jr $t1 # and jump to that address
nop # branch delay slot
LABEL1: # do something
b 2f # break
nop
LABEL2: # do something else
b 2f # break
nop
LABEL3: # do a different thing
b 2f # break
nop
2: # after the end of the "case statement"