MIPS findmin of array function - arrays

Hello I am getting exception 7 [bad data address] for the following findMin number in an array function. The length of the array is already in $a1, and the address of the start of the array is in $a0. I want to have the min in $v0 after all is said and done. My function works for arrays with 2 elements but shoots out exception 7 errors when using bigger sized arrays. I am offsetting the array by adding to the address instead of using something like the 4 in 4($a0) offsetting.

They key here is add $a0, $a0, $t1. Consider what that will do in the case of an array with N elements: on the second iteration you'll add 1*4, on the third iteration 2*4, and so on. So on the third iteration you'd be trying to read from array + 1*4 + 2*4 == array + 3*4 instead of array + 2*4. And on the N:th iteration you'd be trying to read from array + 1*4 + 2*4 + ... + (N-1)*4.
The sll + add before the lw should be removed. Updating the address can be done after the lw with an addiu $a0, $a0, 4.

Related

Use of keypad in Digital Lab Sim of Mars simulator

I do not achieve to control keypad of the Digital Lab Sim tool of Mars 4.2.
According to the directions in the help "Byte value at address 0xFFFF0014 : receive row and column of the key pressed, 0 if not key pressed ". Nevertheless, if you read that memory position it does not work. Next simple sequence should read the keypad, but it does not work
ini:
lui $1,0xffff
lw $2,0x0014($1)
j ini
It always returns a 0 in spite of pressing any key of the tools.
I have no problem with the seven segment digit of this tool at all. It is quite easy to use through the address 0xFFFF0012. Nevertheless, no way with the keypad of this tool
Does anybody know how to read the keypad of the Digital Lab Sim of Mars 4.2?
Thank you very much
I answer myself.
Before reading a key, you have to select the row. The next sequence check the three rows (and it works):
sub $0,$0,$0
lui $2,0xffff # Base address IO
main:
addi $3,$0,0x01 # bit 0 =1 for row 1
sb $3,0x0012($2) # Selection row 1 (write on port 0xFFFF 0012)
lb $4,0x0014($2) # $4= code of pressed key of row 1 ($4=0 if not pressed)
bne $4,$0,row1 # if some key of row 1 was pressed -> go row1
# test of row 2
addi $3,$0,0x02 # bit 1 =1 for row 2
sb $3,0x0012($2)
lb $4,0x0014($2)
bne $4,$0,row2
# test of row 3
addi $3,$0,0x04 # bit 2 =1 for row 3
sb $3,0x0012($2)
lb $4,0x0014($2)
bne $4,$0,row3
# test of row 4
addi $3,$0,0x08 # bit 3 =1 for row 4
sb $3,0x0012($2)
lb $4,0x0014($2)
bne $4,$0,row4
j main
row1: # $4 has the code of the pressed key of this row
row2: # $4 has the code of the pressed key of this row
row3: # $4 has the code of the pressed key of this row
row4: # $4 has the code of the pressed key of this row

maximize the top element of the stack after performing exactly K operations

Given a stack of N integers.You need to maximize the top element of the stack after performing exactly K operations.In one operation, you can either pop an element from the stack or push any popped element into the stack. If the stack becomes empty after performing K operations and there is no other way for the stack to be non-empty, print -1.
Input format :
The first line of input consists of two space-separated integers N and K.
The second line of input consists N space-separated integers denoting the elements of the stack. The first element represents the top of the stack and the last element represents the bottom of the stack.
Output format :
Print the maximum possible top element of the stack after performing exactly K operations.
Sample Input
6 4
1 2 4 3 3 5
Sample Output
4
Pop k-1 elements in k-1 operations. Now for the last operation, either you can pop one more element, or can push one element from the popped elements.
So compare both the cases, if you pop element in kth operation, the element on top should be more than all first k-1 popped elements, otherwise for kth operation push the largest element from k-1 popped elements.
I don't have enough reputation so adding it answer.
1.
For k>n it's not compulsory that answer is largest number, as from given example :
3 5
1 2 3
K = 5, in first operation we pop 1, then pop 2,
now we have K = 3, and top of stack element is 3
pop 3, K = 2,
push 3, K = 1, top of stack element = 3
so if here we pop 3 then K = 0 and stack is empty which will be -1 as answer according to question statement which will be wrong.
So coming back to scenario where K = 3 and st.top() = 3 and popped elements are 1,2
push 2, K = 2
pop 2, K = 1
push 2, K = 0
the answer i.e. max element is 2 after the 5 operation.
2.For n = 1 if value of K is odd then answer will be -1 else it will be the first element
python3 code :
n,k = [int(x) for x in input().split()]
arr = [int(x) for x in input().split()]
if n == 1:
if k%2 == 1:
print(-1)
else:
print(arr[0])
elif k >= n:
print(max(arr))
else:
print(max(arr[k-2],arr[k]))

Getting an error when trying to fill an array with Strings and ints in MIPS?

So I need to fill an array in MIPS with 10 "records", which consist of an employee's name, age, and salary. The employee's name is a max of 40 characters and both the age and salary are supposed to be integers. However, when testing this loop I wrote, I always get an "invalid integer input (syscall 5)" for line 18 after I go through the first 5 employees and I type "Emp6" and press enter and I can't seem to figure out why. Any help would be greatly appreciated!
Test Input:
Emp1
1
1
Emp2
2
2
Emp3
3
3
Emp4
4
4
Emp5
5
5
Emp6
Error Code:
Error in line 18: Runtime exception at 0x00400020: invalid integer input (syscall 5)
Go: execution terminated with errors.
Your main problem seems to be that the read_string system call expects the buffer size in $a1, but you use that for your loop counter. Thus, you eventually run out of space, and there will be unprocessed text left in the input buffer which will then be read by the subsequent read_int and that blows up.
Further problem is that you keep incrementing $a0 but fail to account for that in your addressing. Also sw $v0, 0($a0) doesn't make much sense, the string has been read into memory already, $v0 has nothing interesting in it.

MIPS Constructing Loops

Okay, so this might be a really silly question but I don't quite have the hang of Assembly yet. I have to write a program that calculates the summation of a series of numbers. It should behave like so:
Enter the first integer in the series: 5
Enter the number of integers in the series: 3
Enter the offset between integers in the series: 4
The series is: 5, 9, 13.
The summation of the series is 27.
Would you like to calculate another summation (Y/N)? y
Enter the first integer in the series: 4
Enter the number of integers in the series: 5
Enter the offset between integers in the series: 27
The series is 4, 31, 58, 85, 112.
The summation of the series is 290.
Would you like to calculate another summation (Y/N)? Y
Enter the first integer in the series: -16
Enter the number of integers in the series: -22
There must be a positive number of integers in the series.
Would you like to calculate another summation (Y/N)? n
This is what I have so far:
li $v0, 4 #put 4 in as main parameter in v0
la $a0, Q1 #syscall will print string query 1
syscall
Store first integer in series in s0
li $v0, 5 #put 5 in as main parameter in v0
syscall #syscall will read integer from Q1
move $s0, $v0 #move integer in v0 to s0
Request number of integers in series
li $v0, 4 #put 4 in as main parameter in v0
la $a0, Q2 #syscall will print string query 2
syscall
Store number of integers in series in s1
li $v0, 5 #put 5 in as main parameter in v0
syscall #syscall will read integer from Q2
move $s1, $v0 #move integer in v0 to s1
Request offset of integers
li $v0, 4 #put 4 in as main parameter in v0
la $a0, Q3 #syscall will print string query 3
syscall
Store offset of integers in s2
li $v0, 5 #put 5 in as main parameter in v0
syscall #syscall will read integer from Q3
move $s2, $v0 #move integer in v0 to s1
Set counter
li $s3, 1 #Set counter to zero
li $t0, 1 #iterator count is in t0
I'm just curious as to where to start my loop? And how exactly would I go about printing the entire series? Any advice would be greatly appreciated.
I'm not sure what you do in "set counter" part, as the s1 already contains number of series members.
And s0 contains current element.
All you need (additional information) is to clear current_sum, let's say as s3:
add $s3, $zero, $zero ; or "move $s3, $zero" if you prefer the pseudo-ops
So for your first example s0-s3 will be set to [5, 3, 4, 0] before first loop iteration. This is everything ("world state") you need, any other value you will set up is probably some temporary for particular sub-task like displaying some value and similar, but as long as the core computation goes, these four values represent all you need, and everything else can be based upon them.
If s1 is already less than 1 (<=0 test), report wrong input.
Then the loop algorithm:
add current element (s0) to current sum (s3) ; summing up all numbers
display current element (s0)
; handle the correct count of series' members
decrement counter s1
if s1 is zero, then goto exit_loop
; preparing for next loop iteration
add offset (s2) to current element (s0)
display ", "
jump to first step
exit_loop: logic will involve printing end of line, summation text description, current sum value (s3), another new line(s) and asking for repeat y/n.
For example that 4 core values will evolve during iterations like this:
[5, 3, 4, 0] => displays "5, " + all the updating of values
[9, 2, 4, 5] => displays "9, " + all the updating of values
[13, 1, 4, 14] => modifies s3 to 27, displays "13", --s1, jumps to exit_loop
At exit_loop the core values are [13, 0, 4, 27], code will display 27 as series sum.

converting a C for loop to MIPS

I'm trying to make this C code translated directly to mips, without modifying any instructions, to make it run better:
for(i = 0; i != j; i += 2)
b[i] = a[i] - a[i + 1]
I'm not really going to be coding in mips, I'm just trying to understand some things. Here's what I have so far (not much):
#t5 = i
$t6 = j
#t1 = a
#t2 = b
#t3 = c
#t10, t11, t12 = free
add $t5, $zero, $zero # initialize i = 0
loop:
bne $t5, $t6 # check if i is not equal to j
addi $t5, $t5, 2 # i += 2
add $t10, $t5, $t11 # temp reg $t10 = address of b[i]
lw $t2, 0($t10) # temp reg $t2 = b[i]
add $t10, $t5, $t12 # temp reg $t10 = address of a[i]
lw $t1, 0($t10) # temp reg $t1 = a[i]
Not sure if the bne is right, since I didn't specify anywhere to branch to. I've read up on arrays in mips but it confuses me. I know I need to use the proper offset for byte addressing when putting the arrays in the registers. Would it be the same with a variable instead of a number in the array? Any direction or tips would be nice. Thank you!
You guessed right, bne needs a location to branch to. So you need at least one more tag in your program. In the example below, that new tag is called "exit".
As far as the addressing in loading and storing, I agree with you; it can get a little confusing at first (especially if you're used to c style array indexing). If your offset is not a constant, then you have to perform an add (or subtract) operation to get the address. Let's use the address of a[i + 1] as an example: first you need to add the address of a to i and store it somewhere, then you can load (or store) to the true address by using the constant offset. I rewrote your example so that you could see what I'm talking about; it's one of those things that's easier to see by example than by explanation :)
#t5 = i
#t6 = j
#t1 = address of a
#t2 = address of b
#t10, t11, t12 = free
#START
move $t5,$0 #set $t5 to zero
loop:
bne $t5,$t6,exit #if $t5 not equal to $t6 branch to exit
addi $t10,$t1,$t5 #temp reg $t10 = address of a[i]
lw $t11,1($t10) #temp reg $t11 = a[i + 1]
lw $t12,0($t10) #temp reg $t12 = a[i]
sub $t10,$t12,$t11 #temp reg $t10 = a[i] - a[i + 1]
addi $t11,$t2,$t5 #temp reg $t11 = address of b[i]
sw $t10,0($t11) #store word b[i] = a[i] - a[i + 2]
addi $t5,$t5,2 #i+=2
j loop #jump to start of loop
exit:
Don't forget that the memory addressing is offset by 4 bits for word reading.
According to the text Computer Organization and Architecture, the correct way to move through the array indexed by i is to do:
sll $t10,$t5,2 #$t10=i*4
add $t10,$t10,$t1 #$t10 = i*4 + addr(a)
lw $t11,4($t10) #temp reg $t11 = a[i + 1]
lw $t12,0($t10) #temp reg $t12 = a[i]
Notice that i must be multiplied by 4 and the offset for the lw should be in multiples of 4. If this is not done, the addressing will not progress properly because the addressing is bytewise, but we are using wordwise data manipulation. The correct implementation would look like this.
#t5 = i
#t6 = j
#t1 = address of a
#t2 = address of b
#t10, t11, t12 = free
#START
move $t5,$0 #set $t5 to zero
loop:
bne $t5,$t6,exit #if $t5 not equal to $t6 branch to exit
sll $t10,$t5,2 #temp reg $t10 = i*4
add $t10,$t10,$t1 #temp reg $t10 = address of a[i]
lw $t11,4($t10) #temp reg $t11 = a[i + 1]
lw $t12,0($t10) #temp reg $t12 = a[i]
sub $t10,$t12,$t11 #temp reg $t10 = a[i] - a[i + 1]
sll $t11,$t5,2 #temp reg $t11 = i*4
add $t11,$t11,$t2 #temp reg $t11 = address of b[i]
sw $t10,0($t11) #store word b[i] = a[i] - a[i + 2]
addi $t5,$t5,2 #i+=2
j loop #jump to start of loop
exit

Resources