MIPS assembly a simple for loop (2) - loops

This is my 1st effort towards learning looping in MIPS.
.data
spc: .asciiz ", "
.globl main
main:
li $t0, 0
loop:
bgt $t0, 14, exit # branch if($t0 > 14)
addi $t0, $t0, 1 # $t0++ for loop increment
# print a comma
la $a0, spc # copy spc to $a0 for printing
li $v0, 4 # syscall value for strings
syscall
# repeat loop
j loop
exit:
li $v0, 10 # syscall value for program termination
syscall
Output:
-- program is finished running (dropped off bottom) --
This program is supposed to print 15 commas in the I/O console. That isn't taking place.
What could be the issue?
Ref: MIPS assembly for a simple for loop

You assembled all your code into the .data section; you never switched back to .text.
If you're using MARS, the GUI shows no asm instructions in the disassembly (after assembling). This is why.
Apparently instead of faulting on main being in a non-executable page, MARS simply decides that the program "dropped off the bottom" as soon as you start it.

Related

how to check for newline character in string input to an array in MIPS assembly

I am working on an assignment for MIPS assembly and this is my first time posting to stackoverflow and currently I am stuck on a part where I have to input string into an array and then terminate the input when I enter the newline character "\n". I am using memory mapped I/O and Polling.
.data
array: .word 0:10
.globl main
.text
main:
la $s2,array
li $t0, 0xffff0000 # Address of keyboard control register
li $t1, 0 # Initialize wait_counter = 0
li $s0,10
li $s1,0
wait_keyboard:
lw $t2, ($t0) # Read the keyboard control register
andi $t2, $t2, 1 # Extract ready bit
addiu $t1, $t1, 1 # wait_counter++ (counts iterations)
beqz $t2, wait_keyboard # loop back while not ready
lw $a0, 4($t0) # Get character from keyboard
addi $s1,$s1,1
li $v0,11
syscall
sw $a0,($s2)
addi $s2,$s2,4
beq $a0,'\n',end
bne $s1,$s0,wait_keyboard
end:
#End Program
li $v0,10
syscall
As you can see, I am checking for the newline character by using the beq $a0,'\n',end instruction which will end the loop after I enter the newline character .However this does not work as I enter the newline character for some reason. I would really appreciate it if you guys could tell me what I am doing wrong in this code.
I just need to know how exactly I can check for a newline character in input using memory mapped I/O and Polling.

Nested Loop Demonstration in MIPS

I have found a code snippet on this website as an answer to a question. The code uses nested loops in MIPS.
Here is the code :
.data
prompt: .asciiz "Please enter the edge length of the base of right
triangle: "
newLine: .asciiz "\n"
star: .asciiz "*"
.text
main:
li $v0, 4 # print the prompt
la $a0, prompt
syscall
li $v0,5 #take user input
syscall
move $s0, $v0 # move the input to $s0
li $t0, 0 # load 0 at t0
outerLoop:
beq $t0, $s0, end #(for i=0;i<=baseLength;i++)
#if t0=s0 branch to end
addi $t0, $t0, 1 # increment i
li $t1, 1 #load 1 at t1
jal changeLine #jump to changeLine
innerLoop:
bgt $t1, $t0, outerLoop #(for j=0;j<=i;j++)
# if t1=t0 branch to outerLoop
li $v0, 4 # print star
la $a0, star
syscall
addi $t1, $t1, 1 # increment j
j innerLoop # jump to innerLoop
changeLine:
li $v0, 4 # new line
la $a0, newLine
syscall
jr $ra # jump to after the call instruction
end:
li $v0, 10 # end of program
syscall
The code works perfectly but I could not understand how the outer loop iterates even though there is no an explicit command like j outerLoop.
Any help is appreciated.
The answer is the innerLoop's first statement:
innerLoop:
bgt $t1, $t0, outerLoop #(for j=0;j<=i;j++)
# if t1=t0 branch to outerLoop
When the total number of iterations for the innerLoop has ended, the code jumps back to the outerLoop label.
Here's the thing: the outer loop has been "optimized" and no longer directly reflects the for loop stated in comment.  The C equivalent looks more like this:
for ( i = 0; i <= baseLength; /* empty increment */ ) {
i++;
<loop-body> // includes inner loop
}
Normally a for loop such as this:
for ( i = 0; i < N; i++ ) { <loop-body> }
by definition of the for loop construct, would expand as follows:
i = 0;
while ( i < N ) {
<loop-body>
i++;
}
However, as you can see, in the code you're showing, the i++ increment has moved from after the loop-body to before the loop-body.
As a result, there is no increment code for the outer loop to perform after executing the inner loop — and thus, the inner loop's exit location can continue directly with the top of the outer loop.
However, when making these changes, we have to be careful b/c now loop-body executes with a 1 larger value of i than in the C code that this was translated from and now shown in comment.  If i is used inside loop-body this is an issue.
And here i is indeed used inside the loop body, as part of the inner loop iteration control.  Because i is one larger, this inner loop will iterate one more time than the C code that was written in comment.
If the "optimization" had not been applied, the inner loop would probably exit by jumping forward to an i++ increment that belongs to the outer loop, which would then j outerLoop (jump backwards) as you were expecting, to continue the outer loop.
Beginning assembly programmers are often keen to modify the C or pseudo code they're starting with during translation into assembly, but these changes are often done without the understanding that they are not logically or algorithmically equivalent.  For example, changing a while loop into a do-while loop; changing array references into pointer operations — in this case changing the order of operations.  Since C can express all of those (do-while, pointers, etc.) I advocate making optimizations in C first, then verify the equivalent behavior, and take that to assembly.
Yes, there are other optimizations that are only sensible in assembly (i.e. not possible or practical in C), though suggest to leave those for when efficiency is the primary topic and until then follow the C starting code rather literally.

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 char array indexing with counter

Overview of program: Input of a number 1-26, give the corresponding Capital letter too the number
My logic: Set up an Array type "structure" using .byte with chars. have a counter going through the array. once the counter is equivenlt to the input number print out the current point at the array.
This is a homework assignment so I'm not trying to "nudge" out the answer but guidance would be very helpful.
This is why where I think its going wrong. When I add 1 to the address it for some reason gives me a error. But when i add 4 it works fine? A char is supposed to take only 1 bit correct? I understand that when indexing address's of ints in an array it should be by 4.
.data
prompt: .asciiz "Enter the value of n here: "
larray: .byte 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
.globl main
.text
main:
la $t1, larray # Loads Array addresss into $t1
li $v0, 4 # System call for Print String
la $a0, prompt # Load address of prompt into $a0
syscall # Print the prompt message
li $v0, 5 # System call code for Read Integer
syscall # Read N into $v0
move $t3, $v0
li $t0, 0 # Loads int 0 into $t0
loop:
beq $t0, $t3, end # Break
lw $a0, ($t1) # Loads current pointer
addi $t0, $t0, 1 # Adds one to $t0 (Counting up +1)
addi $t1, $t1, 1 # Advances to next address in the array
j loop
end:
li $v0, 11 # Print at current index
syscall
li $v0, 10 # return control to system
syscall
I did do research on how to access the char a different way, but I don't think I can implement this way because you would need it hard coded?
Link:
This is the Stack Link that I found
There's no need for the array or the loop. If all you want to do is find the corresponding capital letter for a single number in the range 1-26, this would suffice:
li $v0, 5 # System call code for Read Integer
syscall # Read N into $v0
addiu $v0,$v0,'A'-1 # Convert the number 1-26 to the character 'A'-'Z'
A char is supposed to take only 1 bit correct?
One byte.
When I add 1 to the address it for some reason gives me a error. But when i add 4 it works fine?
You're using the lw instruction, which loads one word (4 bytes). To load a single byte, use the lb or lbu instruction (lb is for signed bytes, lbu for unsigned).

How can I store sequence in an array in MIPS?

I have this homework problem .
Write a program that produces the following sequence; 1,2,2,4,8, 32, 256,… and stores it in an array, depending on the number of terms chosen by the user. Each element in the sequence can be calculated by multiplying the two elements preceding it. In other words the nth sequence number Sn is calculated by the equation Sn=Sn-1×Sn-2.
I tried but it didn't run
My code
^
^
# UNTITLED PROGRAM
.data # Data declaration section
str1: .ascii "Please enter the number of terms to produce: "
arr: .space 40
.text
main: # Start of code section
li $v0, 4 # system call code for printing string = 4
la $a0, str1 # load address of string to be printed into $a0
syscall # call operating system to perform print operation
li $v0, 5 # get ready to read in integers
syscall # system waits for input
move $s0,$v0 # store the result of the read (returned in $v0) in num1
la $s1,arr
addi $t2,$zero,2 # i=2
addi $t0,$zero,1
add $t1,$t0,$t0
sw $t0,0($s1)
sw $t1,0($s1)
L1:
addi $t2,$t2,1 #i++
addi $s1,$s1,4
lw $t4,0($s1) #A[i-1]
lw $t5,4($s1)
mul $t3,$t4,$t5
sw $t3,8($s1)
beq $t2,$s0,print
j L1
print:
lw $t3,0($s1)
li $v0, 1 # system call code for print_int
move $a0, $t3 # integer to print
syscall # print it
addi $s1,$s1,4
beq $t2,$s0,Exit
j print
Exit:
li $v0, 10 # exits program
syscall
# END OF PROGRAM
MARS error message:
Error in line 26: Runtime exception at 0x00400030:
store address not aligned on word boundary 0x1001002d
The error message is telling you that you're trying to access memory with an illegal (non word-aligned) address at this instruction:
sw $t0,0($s1)
When you have problems like this, you need to use the debugger. First, set a break point at the instruction where the exception is thrown.
Run the program, and when it stops at the break point, check the address (in $s1) you're trying to access. You'll see that it's 268501037 or 0x1001002d, and since it ends with a 7, it's not word-aligned.
$s1 has the correct array address, but I think you're assuming that when you created the array in the data segment, that it would start at a word-aligned address. This is not the case. To resolve this, you need to align the data.
.data # Data declaration section
str1: .ascii "Please enter the number of terms to produce: "
.align 2
arr: .space 40

Resources