You were using the .word directive incorrectly:
myArray: .word 256
This does not define an array with 256 elements. It defines a single scalar word with initial value of 256. The size of the array is only 4 bytes.
So, after the first store into the array, you are writing past the end (i.e. undefined behavior in C parlance).
In your answer, you moved myArray to the end of the .data section. But, this is not a fix. It merely "papers over" the problem. And, if you have the order myArray | char, then the second element of myArray will contain garbage data.
The correct way to define an array is to use the .space directive. It reserves a given number of bytes. So, the correct definition for myArray would be:
myArray: .space 1024
The char array had a similar problem, but you "lucked out".
There were also a few more bugs as well. Particularly, the "-1" check was weak, if it worked at all.
I've created three versions of your program. A version with the bugs annotated. A second that is cleaned up and fixed. A third that is a bit simpler, more general, and more efficient because it uses a different syscall to get user input.
Here is the annotated version [please pardon the gratuitous style cleanup]:
# switch to the Data segment
.data
# global data is defined here
# NOTE/BUG: this defines a _single_ 32 bit word [with initial value of 256]
# and _not_ an array with 256 elements
# as it is, myArray is only 4 bytes long
myArray: .word 256
# NOTE/BUG: this has similar problems to above but you luck out because
# it defines an area of length 4 by virtue of the .word directive and _not_
# the 4
char: .word 4
sp: .asciiz " "
cr: .asciiz "\n"
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR."
array_input: .asciiz "\Please type a digit. Press enter after each. End array with -1 input.\n"
# NOTE/BUG: this string is incorrect for its intended use below
# NOTE/BUG: this isn't used
neg_one: .asciiz "\1-"
# switch to the Text segment
.text
.globl main
# the rest of the main program goes here
main:
# NOTE/BUG: this is a poor way to initialize this. use "li" or "lw" instead
# but also see below
# NOTE/BUG: manually compensating for little endian is tedious
lui $s7,0x000a # set first half of $s7
ori $s7,$s7,0x312d # set $s7 to compare with beq and exit input, $s7 = -1 now.
# NOTE/BUG: this has _no_ effect
addi $t3,$t3,0 # set counter for decrementing array later
la $s1,myArray # set base address of array to $s1
# NOTE/BUG: although not a bug, this should be part of the loop
la $a0,array_input
jal Print_string
input_loop:
la $a0,char
li $a1,4
jal Input # prompt user for digit input
lb $t1,char
# NOTE/BUG: this is a weak way to check for -1
lw $t2,char # store char from buffer into t1 (does this strip newline?)
beq $t2,$s7,begin_sort # branch if input is equivalent to -1
blt $t1,48,error # check if char is not a digit (ascii<'0')
bgt $t1,57,error # check if char is not a digit (ascii>'9')
addi $t1,$t1,-48
sw $t1,0($s1) # store char into array
move $a0,$t1
jal Print_integer # print number that was input
la $a0,cr
jal Print_string # print newline char
addi $s1,$s1,4 # increment array address
addi $t3,$t3,1 # increment array counter
j input_loop # jump back up when -1 not entered
begin_sort:
# NOTE/BUG: this _must_ be "jal" and _not_ "Jal"
# NOTE/BUG: this should just be "j" or just move the "Exit" code here
Jal Exit
error:
la $a0,error_string
li $v0,4
syscall
j input_loop
.globl Input
# gets a string from user into register
Input:
addi $v0,$zero,8
syscall # calls for input
jr $ra
.globl Print_integer
# print the integer in register a0. Loading one into $v0 from addi makes syscall print
Print_integer:
addi $v0,$zero,1
syscall
jr $ra
.globl Print_string
# print the string whose starting address is in register a0
Print_string:
addi $v0,$zero,4
syscall
jr $ra
.globl Exit
# end the program, no explicit return status
Exit:
addi $v0,$zero,10
syscall
jr $ra
Here is the cleaned up and working version. Note that the best way to do the "-1" check would be to strip the newline and implement a strcmp function, but I did something simpler
# switch to the Data segment
.data
# global data is defined here
myArray: .space 1024
eArray:
char: .space 80
echar:
sp: .asciiz " "
cr: .asciiz "\n"
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR."
array_input: .asciiz "\Please type a digit. Press enter after each. End array with -1 input.\n"
# switch to the Text segment
.text
.globl main
# the rest of the main program goes here
main:
la $s1,myArray # set base address of array to $s1
la $s2,eArray # get end of array
input_loop:
# prompt user
la $a0,array_input
jal Print_string
# read in user's response
# NOTE: unless you are _required_ to decode the number yourself, using
# syscall 5 (read integer) is _much_ simpler
la $a0,char
la $a1,echar
subu $a1,$a1,$a0
jal Input # prompt user for digit input
# check for -1 on input
lb $t2,0($a0) # is first char "-"?
bne $t2,0x2D,not_negone # no, fly
lb $t2,1($a0) # is second char "1"?
bne $t2,0x31,not_negone # no, fly
lb $t2,2($a0) # is third char "\n"?
beq $t2,0x0A,begin_sort # yes, fly
not_negone:
lb $t1,0($a0)
blt $t1,48,error # check if char is not a digit (ascii<'0')
bgt $t1,57,error # check if char is not a digit (ascii>'9')
addi $t1,$t1,-48
sw $t1,0($s1) # store char into array
move $a0,$t1
jal Print_integer # print number that was input
la $a0,cr
jal Print_string # print newline char
addi $s1,$s1,4 # increment array address -- over edge?
blt $s1,$s2,input_loop # no, loop
begin_sort:
j Exit
error:
la $a0,error_string
li $v0,4
syscall
j input_loop
# gets a string from user into register
Input:
li $v0,8
syscall # calls for input
jr $ra
# print the integer in register a0. Loading one into $v0 from addi makes syscall print
Print_integer:
li $v0,1
syscall
jr $ra
# print the string whose starting address is in register a0
Print_string:
li $v0,4
syscall
jr $ra
# end the program, no explicit return status
Exit:
li $v0,10
syscall
The above program still suffers from a limitation in that the numbers input can only be single digits. The general solution would be to implement the equivalent of atoi.
But, if you're not required to do your own number parsing, using syscall #5 [read integer] is much simpler, allows any integer, and is what most mips programs use.
# switch to the Data segment
.data
# global data is defined here
myArray: .space 1024
eArray:
sp: .asciiz " "
cr: .asciiz "\n"
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR."
array_input: .asciiz "\Please type a number. Press enter after each. End array with -1 input.\n"
# switch to the Text segment
.text
.globl main
# the rest of the main program goes here
main:
la $s1,myArray # set base address of array to $s1
la $s2,eArray # get end of array
input_loop:
# prompt user
la $a0,array_input
jal Print_string
# read in user's response
li $v0,5
syscall
move $t1,$v0
# check for -1 on input
bltz $t1,begin_sort
sw $t1,0($s1) # store char into array
move $a0,$t1
jal Print_integer # print number that was input
la $a0,cr
jal Print_string # print newline char
addi $s1,$s1,4 # increment array address -- over edge?
blt $s1,$s2,input_loop # no, loop
begin_sort:
j Exit
error:
la $a0,error_string
li $v0,4
syscall
j input_loop
# gets a string from user into register
Input:
li $v0,8
syscall # calls for input
jr $ra
# print the integer in register a0. Loading one into $v0 from addi makes syscall print
Print_integer:
li $v0,1
syscall
jr $ra
# print the string whose starting address is in register a0
Print_string:
li $v0,4
syscall
jr $ra
# end the program, no explicit return status
Exit:
li $v0,10
syscall