I have this code that goes through an array of 5000 ASCII values of characters and then counts the number of each character and stores it into an array in alphabetical order.
.text
la $s7,results
array1 is the array of 5000 ASCII characters
la $s6,array1
main:
addi $s0,$zero, 5000
addi $s3, $zero,96
addi $s4, $zero,65
loop:lw $s2,0($s6)
addi,$t1,$zero,0
addi $s6,$s6,4
addi, $s5,$zero, 0
addi $s0,$s0, -1
bge $s2, $s3, convert
The substaction of of $s2, - $s4($s4 is # )is to get the positon of where the count needs to be stored
ex F - # = 6
sub $s5, $s2, $s4
I was wondering if this was right for it getting to the correct position and to increment the count?
addi $t1, $t1, 1
loop2: addi $s7, $s7, 4
lw $t0,($s7)
add $t0, $t0, $t1
sw $t0,($s7)
addi, $s5,$s5, -1
beq $s5, $zero, loop2
bne $s0,$zero, loop
This converts the character to an upper case ASCII value.
convert: subi $s2,$s2, 32
addi $s5, $s5, 0
sub $s5, $s2, $s4
j loop2
.data
results: .space 128 # Words to be used to store results
Related
Here is some relevant code. I extracted these ints from a .txt file into buffer, and then use extractInts to format them into an array (intArray). Then I use printArray to loop through it and print. The ints in intArray are stored in a .space of 80 bytes, each in their own word.
My current output:
The array: 14385 57 14130 53 14388 13873 50 13109 13366 14393
My expected output:
The array: 18 9 27 5 48 16 2 53 64 98
# put ints into array
extractInts:
la $s0, buffer # $s0 points to buffer
la $s1, intArray # $s1 points to intArray
li $t0, 0 # i = 0
li $t1, 3 # intLoop max = 3
li $t3, 4 # nextWord max = 4
# loop to place each int within its own word boundary in intArray
intLoop:
beq $t0, $t1, exitLoop # exit loop if i = end of word
lb $t2, ($s0) # $t2 = intArray[]
beq $t2, '\n', nextWord # if $t2 = \n, go to nextWord
beq $t2, '\0', exitLoop # if $t2 = \0, go to exitLoop
sb $t2, ($s1) # save byte in $t2 to intArray[]
addi $t0, $t0, 1 # i++
addi $s0, $s0, 1 # increment buffer
addi $s1, $s1, 1 # increment intArray
j intLoop
# skip to next word
nextWord:
sub $t4, $t3, $t0 # $t4 = 4 - i
add $s1, $s1, $t4 # increment intArray by $t4
li $t0, 0 # restore i to 0
addi $s0, $s0, 1 # increment buffer
j intLoop
printArray:
li $t0, 0 # i = 0
while:
beq $t0, 80, exit # exit if i = end of array
lw $t1, intArray($t0) # $t1 = intArray[$t0]
addi $t0, $t0, 4 # move to next word in intArray
# print current int
li $v0, 1
move $a0, $t1
syscall
# print space
li $v0, 11
li $a0, 32
syscall
j while
I'm currently working on a palindrome function in MIPS that takes a char array and returns 0 if it is not a palindrome, else 1. I've got everything seemingly working except for the part where I find data at index i and array.length-i-1. If someone could lead me in the right direction I'd really appreciate it.
Here's the java code I'm going off of:
int Palindrome(char[] s) {
for(int i = 0; i < (s.length / 2); i++) {
if(s[i] != s[s.length - 1 - i])
return 0;
}
return 1;
}
Here's the Palindrome function:
palindrome:
# Get length of array and store it in $t1
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $a0, 4($sp)
li $t1, 0
lengthWhile:
lw $t2, 0($a0)
beq $t2, $zero, startPalindrome
addi $t1, $t1, 1
addi $a0, $a0, 4
j lengthWhile
startPalindrome:
div $t2, $t1, 2 # Stores a.length / 2 into $t2
add $t3, $t3, $zero # i value (0 - (a.length/2 - 1))
add $t4, $t4, $t1
subi $t4, $t4, 1 # a.length-1
# $t1 = a.length
# $t2 = a.length / 2
# $t3 = i
# $t4 = a.length - 1
palLoop:
bge $t3, $t2, exitLoop
sub $t4, $t4, $t3 # Puts a.length-1-i into $t4
sll $t5, $t3, 2
add $t6, $a0, $t5
lw $s1, 0($t6)
sll $s3, $t4, 2
add $t7, $a0, $s3
lw $s2, 0($t7)
bne $s1, $s2, return0
# Increase i and start loop again
addi $t3, $t3, 1
j palLoop
return0:
li $v0, 0
jr $ra
exitLoop:
li $v0, 1
jr $ra
Here's the main:
.data
charArray: .word 'a', 'b', 'c', 'd', 'c', 'w', 'a'
.text
main:
# Palindrom Function
la $a0, charArray
jal palindrome
move $a0, $v0
li $v0, 1
syscall
# Exit Program
li $v0, 10
syscall
Thank you in advance for any help. (To specify, palLoop is where I'm having trouble).
Not directly part of your question, but charArray: .word 'a', 'b', 'c', 'd', 'c', 'w', 'a' is really a word array containing a chatarter value, not a character array.
It looks like that will wok as you are using word array everywhere, however wont wok if you use a proper character array.
add $t3, $t3, $zero is t3 = t3 + 0 - what is t3 prior to that?
add $t4, $t4, $t1 - same comment
sub $t4, $t4, $t3 # Puts a.length-1-i into $t4 - will overwrite a.length-1 (t4) so is going not be right on the 2nd time through the loop.
This is a follow up of my previous question which I edited:
How to remove a comma from string input
I managed to fix the infinite loop, and found a way to increment through the string. My code now can, iterate through a string(eg. 123,456) find the address of the "," and stores in $t4.
But what I can't figure out is how to shift all the numbers towards the left to remove the "," from the string(should look like this in the memory 123,456 -> 123456)
I'm using native MIPS instructions. If you could help me out like that, I would really appreciate it.
.globl main
.globl main2
.globl main3
.globl firstNumCountChr
.globl firstNumIncrem
.globl secondNumCountChr
.globl secondNumIncrem
.globl thirdNumCountChr
.globl thirdNumInCrem
.data
prompt1: .asciiz "Enter first number:"
prompt2: .asciiz "Enter second number:"
prompt3: .asciiz "Enter third number:"
.text
# 0x10000000 will store first number
# 0x10000008 will store second number
# 0x10000010 will store third number
main:
#display prompt1
addi $v0, $0, 4
lui $a0, 0x1000
syscall
#Input first number
lui $a0, 0x1000
ori $a0, 0x0000 #reads number into memory(0x10000000)
addi $a1, $0, 8 #7 characters
addi $v0, $0, 8
syscall
#removing comma of first number
add $t1, $0, $0 #$t1 is the counter set to 0
add $t3, $0, 0x2c # 0x2c is acsii of "," in hex
firstNumCountChr:
lb $t2, 0($a0) #load first byte from address in $a0
beq $t2, $0, firstNumRemoveComma #if $t2 == 0 go to firstNumRemoveComma
or $0, $0, $0 #NOP
bne $t2, $t3, firstNumIncrem #branch if symbol doesn't equal ","
or $0, $0, $0
add $t4, $a0, $0 #$t4 will save position of ","
firstNumIncrem:
addi $a0, $a0, 1 #increment address
addi $t1, $t1, 1 #increment counter
j firstNumCountChr #loop
firstNumRemoveComma:
beq $t4, $0, main2 #branch if $t4 == 0 (no comma) to main2
or $0, $0, $0 #NOP
main2:
#display prompt2
addi $v0, $0, 4
lui $a0, 0x1000
addi $a0, $a0, 20
syscall
#inputing second number
lui $a0, 0x1000
ori $a0, 0x0008 #reads number into memory(0x10000008)
addi $a1,$0, 8 #7 characters
addi $v0, $0, 8
syscall
#removing comma of second number
addi $t1, 0 # $t1 is the counter set to 0
add $t3, 0x2c # 0x2c is acsii of "," in hex
secondNumCountChr:
lb $t2, 0($a0) # load first byte from address in $a0
beq $t2, $0, end # if $t2 == 0 go to end
or $0, $0, $0 # NOP
bne $t2, $t3, secondNumIncrem # branch if symbol doesn't equal ","
or $0, $0, $0 # NOP
add $t4, $a0, $0 # $t4 will save position of ","
secondNumIncrem:
addi $a0, $a0, 1 #increment address
addi $t1, $t1, 1 #increment counter
j secondNumCountChr #loop
main3:
#display prompt3
addi $v0, $0, 4
lui $a0, 0x1000
addi $a0, $a0, 41
syscall
#inputting third number
lui $a0, 0x1000
ori $a0, 0x0010 #reads number into memory(0x10000010)
addi $a1, $0, 8 #7 characters
addi $v0,$0, 8
syscall
#removing comma of third number
addi $t1, 0 #$t1 is the counter set to 0
add $t3, 0x2c # 0x2c is acsii of "," in hex
thirdNumCountChr:
lb $t2, 0($a0) #load first byte from address in $a0
beq $t2, $0, end # if $t2 == 0 go to end
or $0, $0, $0
bne $t2, $t3, thirdNumInCrem # branch if symbol doesn't equal ","
or $0, $0, $0
add $t4, $a0, $0 # $t4 will save position of ","
thirdNumInCrem:
addi $a0, $a0, 1 #increment address
addi $t1, $t1, 1 #increment counter
j thirdNumCountChr #loop
end:
add $0, $0, $0
This is the C code that i have been converted so far. it gives me some error that i have been included in the following code. i don't understand which part is wrong in this c to mips conversion?
char ch[10];
int i;
for (i = 0; i != 10; i++)
ch[i] = ch[i] – 32
.data
.text
li $v0 4
syscall
#$s1 = i, $s0 base address of ch
addi $s1, $0, 0 #i =0
addi $t0, $0, 10 #t0 = 10
loop: beq $t0, $s1, end
add $t1, $s1, $s0
lw $t2, 0($t1)
addi $t2, $t2, -32
sw $t2, 0($t1)
addi $s1, $s1, 1
j loop
end:
My output:
Runtime exception at 0x00400018: address out of range 0x00000000
From the C code you are converting a char type array and in MIPS you should use lb instead of lw.
In order to print out you need a main: label and also you should declare an array like .byte or .space
You should usesyscall 11 to print a character or syscall 4 to print
string.
I have added some of these mentioned above to your code hope it helps.
.data
#ch: .byte 'a','b','c','d','e'
ch: .space 10
.text
main:
li $v0, 8 #read character
li $a1, 10 #load the space
la $a0, ch
syscall
li $v0,11 #print character
syscall
li $v0,10 # exit program
syscall
addi $s1, $0, 0 #i = 0
addi $t0, $0, 10 # $t0 = 10
loop: beq $t0, $s1, end
add $t1, $s1, $s0
lb $t2, ch($t1)
addi $t2, $t2, -32
sb $t2, ch($t1)
addi $s1, $s1, 1
j loop
end:
I am trying to add numbers that are in base 5.
Im supposed to prompt the user for 2 separate base 5 number in the form XXXXXX.XXXXX, and then add them.
My current problem is that I am getting an error when I am loading the last digit into a register, so I can start the calculation.
please help! Thanks
.data
str: .space 13 # XXXXXX.XXXXX hold 12 chars + 0x00
str2: .space 13
sum: .space 14
printstr: .space 13
printstr2: .space 13
printsum: .space 14
message1: .asciiz "Enter a base 5 number A: "
message2: .asciiz "Enter a base 5 number B: "
message3: .asciiz "Sum of A and B: "
newline: .asciiz "\n"
.text
main:
#get number A
li $v0, 4
la $a0, message1
syscall
li $v0, 8
li $a1, 13
la $a0, str
syscall
li $v0, 4
la $a0, newline
syscall
#get number B
li $v0, 4
la $a0, message2
syscall
li $v0, 8
li $a1, 13
la $a0, str2
syscall
li $v0, 4
la $a0, newline
syscall
#pointer to input string A
la $s1, str
addi $s1, $s1, 12
#pointer to input string A
la $s2, str2
addi $s2, $s2, 12
#pointer to sum
la $s3, sum
addi $s3, $s3, 13
#other variables
li $t0, 0 # inital carry is 0
li $t1, 1 # counter for looping through string
li $t2, 5 # base 5
loop:
lb $t3, ($s1) ############################# PROBLEM HERE######
lb $t4, ($s2)
beq $t3, '.', next
beq $t4, '.', next
subi $t3, $t3, 0x30
subi $t4, $t4, 0x30
add $t5, $t3, $t4
add $t5, $t5, $t0
div $t5, $t2
mflo $t0
mfhi $t5
addi $t5, $t5, 0x30
sb $t5, ($s3)
subi $s1, $s1, 1
subi $s2, $s2, 1
subi $s3, $s3, 1
addi $t1, $t1, 1
ble $t1, 13, loop
addi $t0, $t0, 0x30
sb $t0, ($s3)
next:
subi $s1, $s1, 1
subi $s2, $s2, 1
#subi $s3, $s3, 1
addi $t1, $t1, 1
j loop
PRINT: #print the sum
exit:
li $v0, 10
syscall
You set up $s1 to point past str and decrement it backwards. Your loop: termination is the ble $t1,13,loop. When that completes, $s1 is pointing to the start of the .data section (i.e. 0x10010000).
But, then, you "fall through" to next: [probably wrong] and decrement $s1 so it has the value 0x1000ffff. Then, you do j loop so the fetch is now coming from an address one byte below the start of the .data segment (i.e. memory that does not exist)
That's the source of the crash. You probably need a jump inst after the ble to continue on to some other code.
But, also, when you do beq $t3,'.',next you go to next: and decrement both pointers. Unless you restrict your input there is no guarantee that both $s1 and $s2 both point to '.' at the same time, so you only want to decrement one of them. (e.g. suppose you had str: 12.3 and str2: 123.41)
So, you may need some code to align the two numbers with respect to their decimal points beforehand.