MIPS syscall on MARS: "address out of range" - mips

I'm a newbie with MIPS & MARS. As a part of my program, I want to read a string from the user.
I have a simple code as follows
.globl test
.data 0x10010000
foo: .asciiz "Input a string"
.data 0x10020000
in: .asciiz "xyz"
.text 0x00400000
test:
li $v0, 54
add $a0, $zero, 0x1001
add $a1, $zero, 0x1002
add $a2, $zero, 3
syscall
The idea is to read a string of say length at most 3 into memory at 0x1002. Running the code gives me "Runtime exception at 0x00400010: address out of range 0x00001001".
Why does this happen? How do I fix it? I suspect I'm doing something very silly, but cannot figure it out.

I think you're mixed up with addressing. You've defined your buffer space at 0x10020000 but you're using an address of 0x1002 for the syscall. Same thing with the dialog string.
Your $a0 should be the address of the string that gets shown in the dialog; I suspect this should be foo:
la $a0, foo
And your buffer should be in:
la $a1, in
Edit: these are replacements for the adds, so in the end it should look like:
test:
li $v0, 54
la $a0, foo
la $a1, in
li $a2, 3
syscall
I've also replaced the $a2 line with something simpler. Try to see how they're equivalent.

Related

MIPS: Runtime exception

.data
string: .ascii "String"
.text
main:
lb $t0, string
lb $a0, 1($t0)
li $v0, 11
syscall
li $v0, 10
syscall
I'm trying to run a code to print the first letter of "String", but I'm getting this:
line 8: Runtime exception at 0x00400008: address out of range 0x00000054
Try this:
.data
string: .ascii "String"
.text main:
la $t0, string ;gets the address of the string into $t0
lb $a0, 1($t0) ;loads the "t" in "String" into $a0
li $v0, 11
syscall
li $v0, 10
syscall
lb $t0,string isn't valid MIPS, since the CPU isn't able to load a byte from a constant memory address. (I'm surprised you didn't get an error message for that, actually.)

Can anyone tell what mistake i'm doing in this MIPS code?

.data
array: .space 10
prompt: .asciiz "Enter an integer (0 to quit) :"
text: .asciiz "After sorting, the list of integers is:"
.text
.globl main
main:
la $a1, array
read_numbers:
# Rest of code omitted for brevity...
beqz $v0, sort
j read_numbers
sort:
la $a1, $array
li $v0, 4
la $a0, text
syscall
loop:
lw $t0, 0($a1)
addiu $a1, $a1, 4
beqz $t0, done
li $v0, 1
move $a0, $t0
syscall
j loop
Assuming that the code above is formatted correctly in the file rather than all on one line, and ignoring that you are missing code at
# Rest of code omitted for brevity
And ignoring that you haven't said what it is supposed to do, or what it does do ….
The first thing I see if that you are branching in main:
read_numbers: # Rest of code omitted for brevity...
beqz $v0, sort
j read_numbers
But since you didn't set v0 to anything, it is set to whatever value it was set to before your code (and when I go to run it, non zero)
So, it never branched to the sort routine, and jumps to read_numbers and does an endless loop.
If it was in the 'sort', it will grab the first number from array, which is 0 (unless you had populated the array somehow), see that it was 0 and attempt to branch to 'done' which also isn't in your code.

How can I achieve my expected result?

I want my program to do the following:
test $t0 and $t1. If they are equal print "Equal". If not, print "not Equal". Then test which one of them is Greater and which one of them is Lesser. Finally, print a message accordingly.
The problem with this code is, it doesn't strop after printing "Greater Than". It continues further to print "Lesser Than".
How can I achieve my expected result?
.data
equals: .asciiz "\nEqual"
notEquals: .asciiz "\nnot Equal"
greaterThans: .asciiz "\nGreater Than"
lessThans: .asciiz "\nLesser Than"
.text
main:
li $t0, 5
li $t1, 125
beq $t0, $t1, messageEqual
bne $t0, $t1, messageNotEqual
bgt $t0, $t1, messageGreaterThan
blt $t0, $t1, messageLessThan
#Declare the end of the program
li $v0, 10
syscall
messageEqual:
la $a0, equals
li $v0, 4
syscall
messageNotEqual:
la $a0, notEquals
li $v0, 4
syscall
messageGreaterThan:
la $a0, greaterThans
li $v0, 4
syscall
messageLessThan:
la $a0, lessThans
li $v0, 4
syscall
it doesn't stop after printing "Greater Than". It continues further to print "Lesser Than".
Of course it does, since the code for printing "Lesser Than" directly follows the code for printing "Greater Than", and you haven't put any code in between to divert the flow of execution. A label isn't some kind of magic barrier, it's just a covenient name for a specific location in the program.
If you're running your program in SPIM/MARS and want to terminate it after printing a message you should use syscall 10 (exit). You've got one after all of your conditional jumps, but there's nothing in your code that will jump back to that location.
So instead you could do this:
messageGreaterThan:
la $a0, greaterThans
li $v0, 4
syscall
li $v0, 10
syscall # exit
You should do the same thing at all the other places where you're printing messages.
Slightly cleaner would be to do something like this:
# ...
messageNotEqual:
# code for printing string omitted
j exit
messageGreaterThan:
# code for printing string omitted
j exit
exit:
li $v0, 10
syscall # exit

Can anyone help to print hello world? With using basic instructions only here what I did

Here is what I have:
.data
.asciiz "c"
.asciiz "hello world\n"
.globl main
.text
main:
lui $a0, 0x1002 # set $a0 to start of string
addi $v0, $0, 4 # set command to print
syscall
Use a label (e.g, mylabel:) to let the assembler know the address of the string you want to print, and then reference it with la pseudoinstruction:
.data
.asciiz "c"
mylabel:
.asciiz "hello world\n"
.globl main
.text
main:
la $a0, mylabel
addi $v0, $0, 4 # set command to print
syscall
Otherwise you should know the location where your string if located.
If you want to know how the assembler translates la, you can look at the code generated and translate it again yourself (it should be an lui followed by an ori). Mars simulator lets you see how the la is translated.

accessing first character of an string and comparing it with an char MIPS

I want to compare a first character of a string with '#' char. If these are equal I want to print "they're equal" in mips. To do this, I've written a piece of code as below.However it does not give me an output even if they're equal. Is there anyone to help me ?
Thanks in advance.
.data
input: .space 201
string2: .asciiz "they're equal.\n"
finish: .byte '#'
.text
main:
la $a0,input
li $a1,201 #read 200 char
li $v0,8 #read string
syscall
jal evaluate
evaluate:
lw $t1, 0($a0)
lw $t2,finish
beq $t1,$t2,testi
testi:
la $a0,string2
li $v0,4
syscall
li $v0, 10
syscall
Yes, you have placed the branch in such a way that the next instruction is the same regardless of whether or not the branch is taken.
Consider changing it to something like this:
evaluate:
lw $t1, 0($a0)
lw $t2,finish
bne $t1,$t2,testi
la $a0,string2
li $v0,4
syscall
test1:
li $v0, 10
syscall