Error Accessing Array in MIPS assembly - arrays

I made this code for finding LCM of two numbers. It is the starting chunk which is having problems. I tried to find the problem but couldn't figure it out. It is giving me error of unaligned address and other exceptions when I try to Load word or Store word. Here is the code:
.data
user: .asciiz "enter first number\n"
user2: .asciiz "enter second number\n"
array1: .space 500
array2: .space 500
array3: .space 500
.text
main:
la $a0,user
li $v0,4
syscall
li $v0,5
syscall
move $s0,$v0
la $a0,user2
li $v0,4
syscall
li $v0,5
syscall
move $s1,$v0
li $t0,0
li $t1,0
li $t2,2
li $t3,3
li $t4,0
li $t5,5
li $t6,7
li $t7,0
li $t8,0
li $t9,0
li $s8,0
la $t8,array1
la $t9,array2
j Loop1
Loop1:
div $s0,$t2
mflo $s2
mfhi $s3 # remainder
beq $s2,1,Loop2
xor $s5,$s3,$0
beq $s5,1,Odd3
add $t4,$t7,$t8
sw $t2,0($t4) # error
addi $t7,$t7,4
j Loop1
Regards

If it complains about unaligned address, then you should go look why it's unaligned. Assemblers are typically smart enough to align data as appropriate, but you are using the .space directive which doesn't have any type (and hence alignment) information. By chance your strings make the arrays unaligned. You can fix this by manually adding a .align 2 directive before array1.

Related

Printing string array in MIPS

I want to print out an array in MIPS. This is what I did
.globl main
.data
hello: .asciiz "Hello, the string is:\n"
names:
.align 3
.asciiz "MIPS"
.align 3
.asciiz "IS"
.align 3
.asciiz "CRAZY"
.align 3
.text
main:
la $a0, hello
li $v0, 4
syscall
#print the first member of the names array
la $t0, names
lw $a0, 0($t0)
li $v0, 4
syscall
#exit
li $v0, 10
syscall
But when I assemble and run, MARS report there is an address out of range. I doubt that what I did wrong is taking the first element out of the array. Could someone help me explain what is wrong in my code?
You need to load the address of the String that you need to print and not the string itself
la $t0, names
lw $a0, 0($t0)
instead of this write the below
la $a0,names
This would print "MIPS IS CRAZY"
The problem is that syscall 4 requires $a0 to be the address of the string to be displayed, but you are loading garbage to $a0 (either 0 or the contents of the first characters of the string to be displayed).
Don't know why you are aligning the strings either.
I'd modify the code to look like this:
.globl main
.data
hello: .asciiz "Hello, the string is:\n"
names1:
.asciiz "MIPS"
names2:
.asciiz "IS"
names3:
.asciiz "CRAZY"
.text
main:
la $a0, hello
li $v0, 4
syscall
#print the first member of the names array
la $a0, names1
syscall
#print the second member of the names array
la $a0, names2
syscall
#exit
li $v0, 10
syscall
li $t0,0
addi $t0,$t0,16 #->porque al usar aling va de 8 en 8 (0,8,16...)
la $a0,names($t0)

MIPS Assembly Program Not Performing Lines

I am currently using MIPS Assembly. I have recently learned how to do both macros and arrays (of a sort), so I promptly wrote a fairly simple program to test them out. However, between getting the data and displaying it again, I wish to output a new message. For some reason, my program doesn't appear to do this, even though when running through it step by step it DOES, in fact, go through those lines - it just simply doesn't have any output. Is there any particular reason in MIPS Assembly why this isn't working, or is it a glitch in the MARS assembler?
.data
testlist: .word 50
request: .asciiz "Enter pi up to 50 digits: 3."
out: .asciiz "\nPi: 3."
.text
.macro arraygetword(%initaddress,%offset,%storeto)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetword(%initaddress,%offset,%value)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
sw %value,($a0)
.end_macro
.macro arraygetbyte(%initaddress,%offset,%storeto)
la $a1,%initaddress
add $a0,%offset,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetbyte(%initaddress,%offset,%value)
la $a1,%initaddress
add $a0,%offset,$a1
sw %value,($a0)
.end_macro
main:
la $a0,request
li $v0,4
syscall
li $t0,0
li $t1,50
forloop:
li $v0,12
syscall
arraysetword(testlist,$t0,$v0)# testlist[$t0]=$v0
addi $t0,$t0,1
blt $t0,$t1,forloop
li $t0,0
li $t1,50
la $a0,out# This is the part not working.
li $v0,4# Why doth this not output anything?
syscall# I need some sort of line break. It's awkward otherwise.
output:
arraygetword(testlist,$t0,$a0)# $a0=testlist[$t0]
li $v0,11
syscall
addi $t0,$t0,1
blt $t0,$t1,output
li $v0,10
syscall
testlist: .word 50 does not allocate 50 words, it allocates a single word with value 50. As such, your program is overwriting the memory after it, which contains your strings to print. Of course by that time you have already printed the request so that is not affected.

MIPS: Storing integer input into memory using sw causes address out of range error

I am trying to store a dynamic array into a program using a stack, by first reading an input n and then creating a stack with [n] inputs. However, when I try to store word, it creates an error that I don't understand.
.data
ask_for_size: .asciiz "\nInsert the array size\n"
ask_for_int: .asciiz "\nInput number\n"
input: .space 16
.text
Main:
li $v0,4
la $a0,ask_for_size
syscall
li $v0,5
la $a0,input
syscall
add $t0,$v0,$zero
li $sp,0x00001000 #stack pointer
li $s0,0x00001000 #base pointer
la $a0,ask_for_int
Loop1:
li $v0,4
syscall
li $v0,5
syscall
sw $v0,0($sp)
addi $sp,$sp,-4
addi $t0,$t0,-1
bne $t0,$zero,Loop1
j Loop2
Loop2:
Shouldn't you add -4 to $sp before you sw $v0 into it?
addi $sp,$sp,-4
sw $v0,0($sp)
It seems to me that at this time you're overwriting past the end of $sp allocated for your process.
Also you load $a0 only once. Are you sure it does not get modified? Otherwise, maybe that would work better?
Loop1:
li $v0,4
la $a0,ask_for_int
syscall
...

Simple yes/no loop to repeat/end - MIPS assembly (MARS)

bI'm not so sure why it's not reading the input and deciding to repeat or end.. Here is my code, help would be appreciated!
.data
again:
.asciiz "Again (y or n)? "
answer:
.asciiz " "
.text
.globl main
main:
li $v0, 4
la $a0, again
syscall
la $s4, answer
jal get
beq $v0, 'y', main
beq $v0, 'Y', main
li $v0, 10
syscall
get:
li $v0, 12
li $a1, 2
syscall
jr $ra
Consider this:
.data
again:
.asciiz "Again (y or n)? "
answer:
.space 256
.text
.globl main
main:
li $v0, 4
la $a0, again
syscall
la $a0, answer
li $a1, 3
li $v0, 8
syscall
lb $t4, 0($a0)
beq $t4, 'y', main
beq $t4, 'Y', main
li $v0, 10
syscall
Firstly, in your code, you seem to misunderstand the way the syscalls work and how they ought to interact with functions (some docs here). Because your get routine basically just called a syscall, I took it out as adding a routine for something that basic is probably adding complexity rather than reducing it.
Next, the main problem of your code was a misunderstanding of the way input buffering works. In your code, you allocated exactly 2 bytes of space for answer, and then use syscalls to get no more than 2 bytes at a time. This will not work for stdin, because on most systems, stdin is line buffered, meaning that the user must press ENTER in order to flush the stream. This means that when the user types 'y', a syscall actually returns "y\n\0".
To fix this I expanded the syscall to read 3 characters and answer to store up to 256. Expanding this to be safe for any size is an excersize left to the reader.

Can't print contents of array

I am doing my homework and it says that I have to ask user for how many members they want to be present in the array. Then the user should enter the number in their array and then the program prints the array. I cannot print contents from my array in the console window.
Here is my code:
.data
max: .word -9999
array: .space 12
message1: .asciiz "Enter an integer:\n"
message2: .asciiz "Specify how many numbers should be stored in the array (atmost 8): \n"
message3: .asciiz "The array content is: \n"
message4: .asciiz "The maximum is: \n"
message5: .asciiz "They have the same maximum.\n"
message6: .asciiz "The first array has a larger maximum.\n"
message7: .asciiz "The second array has a larger maximum.\n"
.text
.globl main
main:
lw $s1, max
la $s3, array
li $s2, 3
la $a0, message2
li $v0, 4
syscall
li $v0, 5
syscall
move $t0, $v0
blt $t0, $s2, Read
Read:
la $a0, message1
li $v0, 4
syscall
li $v0, 5
syscall
move $t1, $v0
sw $t1, 0($s3)
addi $s3, $s3, 4
addi $t0, $t0, -1
bgt $t0, $zero, Read
j Print
#blt $t0, $s2, Print
Print:
la $a0, message3,
li $v0, 4
syscall
jr $ra
Thanks for the help.
When you enter Print you've got the end of the array plus 4 in $s3, so you could do something like this:
$s2 = ADDRESSOF(array)
while ($s2 != $s3) do
print_int($s2[0]) // syscall 1
print_character(' ') // syscall 11
$s2 += 4
end while
This is pseudo-code to illustrate the logic; I'll leave the actual assembly implementation to you since it's your assignment.
(By the way, this: la $a0, message3, is a typo. There shouldn't be a comma at the end of that line)

Resources