Create an array of size n from user input n - arrays

For this assignment i need to be able to make an array of size n based on a user inputed value from zero to fifty. So far this is what ive done below. If you have any advice for the question overall that would be very helpful too.
a) Prompt the user for an integer in the range of 0 to 50. If the user inputs 0 the program stops.
b) Otherwise, the program stores the numbers from 0 up to the input value into an array of words in memory, i.e. initializes the array with values from 0 up to N where N is the value that user has inputted.
c) The program then adds the value of all items of the array together (up to N) by loading them from the main memory then add them up, then prints out the sum with the message "The sum of integers from 0 to N is:". For example, if the user gave 5 as the input the program prints out "The sum of integers from 0 to 5 is 15".
Submit your work as a zip file as specified in the syllabus to eLearning by the due date.
.data
userPrompt : .asciiz "enter in an integer from zero to fifty "
zeroMessage : .asciiz " you have entered a zero , the program will close "
incorrectEntry : .asciiz " you have entered in a value greater than 50 ,
this is an incorrect value"
InputVal : .word
upperLim : .word 50
Array : .space InputVal
.text
main:
addi $t7 , $zero , 50
li $v0, 4 # load for printing of strings
la $a0, userPrompt
syscall
# take in user input and move the read in number to a temp
li $v0, 5
la $t0 , InputVal
syscall
# Store int A into memory
move $t0 , $v0
beq $t0 , $0 , numbersEqual
la $t1 , upperLim
li $v0 , 1
move $a0 , $t1
syscall
slt $t3 ,$t0 , $t1
sw $t0 , InputVal
#beq $t3 , $0 , ELSE
ELSE :
li $v0 , 4
la $a0 , incorrectEntry
syscall
li $v0 , 10
syscall
numbersEqual:
li $v0 , 4
la $a0 , zeroMessage
syscall
li $v0 , 10
syscall

The assembly language is symbolic language for machine code, and machine code is what your CPU can execute.
After you run assembler to compile your source, you get machine code, which is sort of final. Then you execute that machine code.
The .word 0x12345678 is not instruction of CPU, but directive of your assembler, it tells it to reserve whole word of memory at that place of machine code, and store value of 0x12345678 there. I'm not sure what .word without value does, whether it will reserve at least one word, you should rather do InputVal: .word 0 to be sure.
In the final machine code there is no ".word", that's not CPU instruction, there will be just those 4 bytes with their respective values forming word value, at some address, which was known to the assembler as symbol InputVal (that's also not part of machine code any more in this textual form, any instruction using this memory address has only the proper address encoded in it as numeric value, and the executable binary may contain some sort of relocation table for OS to patch addresses properly after loading the machine code to target memory before execution).
Now this may sounds like stating the obvious, but it's important for you to understand the difference, what is available when the CPU is already executing your machine code, and what is available during compilation by assembler (code not running yet).
Array : .space InputVal will not work as you wish, because InputVal is symbol of memory address. So the directive .space will either reserve bazillion bytes (value of memory address of InputVal), or more likely the compilation will fail. What you want is content of memory at InputVal, but that's not known yet, because the code didn't run, user didn't enter anything, it's still just assembly step. So the value is not know, you may just as write Array: .space 0. But that will reserve no space.
Unless you want to delve into dynamic memory allocation, there's simple trick to resolve such situation, which will work in your particular case. If you will read the task, the N is valid only when inputted value is from 0 to 50 (anything else is user error and you can exit). So for maximum N=50 you will need array of 51 values, and you will never need more.
So you can avoid all the dynamic memory allocation (at runtime) by simply doing:
.align 4 # make sure the reserved space is word-aligned
Array: .space (51*4)
This will reserve 204 bytes (51 words) of memory in the data area for your machine code, with symbol Array pointing at the first byte of it.
Now you have memory reserved, and you can store values into it, and use it. If you would want during runtime to change your mind, and use 52 words of memory, you are out of luck with such code. Then you need either to code dynamic allocation, or increment the hard-sized fixed buffer during compilation time.
Also your code has always 51 words available in that Array, so it's up to your code to use only the inputted N+1 values out of them. If user enters N=5, then you should work only over 6 words (24 bytes), ignoring the remaining reserved words).
So each loop in your code will be like for (i = 0; i <= N; ++i) Array[i] = i;, where N is the value entered by user during runtime (store it to InputVal reserved memory, so you can access it whenever you need it), not known during compilation.

Related

from java to MIPS assembly for a simple while loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 25 days ago.
Improve this question
i need to convert a code from java to assembly, but it only prints the first message. but the last two message dosent print neither the message nor the numbers of the result.
the two code in java and assembly are that i wrote as follow :
the code in java:
/**
* this program count how many 10s can be in a givin number the return the extra or the remain that less than 10
*/
Scanner input=new Scanner(System.in);
System.out.println("enter num: ");//print input message
int num=input.nextInt();// user input
int numOf10=0;//counter
while(num>9){ //start of while loop
num-=10;//subtruct 10 from the input number
numOf10++;//add one to the counter
}
System.out.println("number of 10 is: "+numOf10);//print message contain
System.out.println("the remain: "+num);//print message contain
////////////////////////////////////////////////////////////////////////////////////
the code in assembly:
.data
EnterMessage: .asciiz"Enter the number:\n "
ResultMessage: .asciiz"number of 10 is:\n"
remainMessage: .asciiz"the remain:\n "
.text
main:
#ask user to enter input
li $v0,4
la $a0,EnterMessage
syscall
#read user input
li $v0,5
syscall
#save input
move $t0,$v0
#creat variables
#$t2=9
addi $t2,$zero,9
#counter=$t3=0
addi $t3,$zero,0
#jal loop
#while loop
loop:
ble $t1,$t2,exit
subi $t0,$t0,10
addi $t3,$t3,1
j loop
print:
#print ResultMessage num
li $v0,1
move $a0,$t3
syscall
#print ResultMessage
li $v0,4
la $a0,ResultMessage
syscall
#print remainMessage num
li $v0,1
move $a0,$t0
syscall
#print remainMessage
li $v0,4
la $a0,remainMessage
syscall
#close the program
exit:
#end
li $v0,10
syscall
Your problem is here:
ble $t1,$t2,exit
There are a couple of problems here. First, exit leads to:
#close the program
exit:
#end
li $v0,10
syscall
So you've jumped to the end without doing anything.
Second, you've chosen $t1 as one of your registers for the compare, which you never set up. So its value is currently unknown (most likely the kernel or OS or whatever zeroed all your registers prior to main but it's not a good practice to assume that.)
Let's think about what's being asked:
while(num>9){ //start of while loop
num-=10;//subtruct 10 from the input number
numOf10++;//add one to the counter
}
When translating a high-level language to assembly we don't have to do everything the same way it was written in the source language. In terms of goto we can think of this as:
loop_begin:
if (num <= 9) goto loop_exit;
num -= 10;
numOf10++;
goto loop_begin;
loop_exit:
You've got the right idea for the most part. The nice thing about MIPS is that the branching syntax isn't nearly as obtuse as other assembly languages, since you don't have to remember whether carry clear means less than or greater than etc.
loop:
ble $t0,$t2,print # if $t0 (num) <= 9 goto print
subi $t0,$t0,10 # num = num - 10
addi $t3,$t3,1 # counter++
j loop # goto loop
Edit: Fixed typo in comments in last section

MIPS assembly code - trying to find out what this code's about

I'm learning assembly code, and given this code, I need to find what this code is about. However I am trying to debug using qtspim. I know what the value inside each register, but I still don't get what is this code about.
If you find the pattern and what this code about, can you tell me how can you do it, and in what line you know the pattern? thanks!
.text
.globl main
.text
main:
li $s0, 0x00BEEF00 ##given $s0= 0x00BEEF00
Init:
li $t0, 0x55555555
li $t1,0x33333333
li $t2,0x0f0f0f0f
li $t3,0x00ff00ff
li $t4,0x0000ffff
Step1: and $s1, $s0, $t0
srl $s0,$s0,1
and $s2,$s0,$t0
add $s0,$s1,$s2
Step2: and $s1,$s0,$t1
srl $s0,$s0,2
and $s2,$s0,$t1
add $s0,$s1,$s2
Step3: and $s1,$s0,$t2
srl $s0,$s0,4
and $s2,$s0,$t2
add $s0,$s1,$s2
Step4: and $s1,$s0,$t3
srl $s0,$s0,8
and $s2,$s0,$t3
add $s0,$s1,$s2
Step5:
and $s1,$s0,$t4
srl $s0,$s0,16
and $s2,$s0,$t4
add $s0,$s1,$s2
End:
andi $s0,$s0,0x003f
enter image description here
enter image description here
mips explain
This is a population count, aka popcount, aka Hamming Weight. The final result in $s0 is the number of 1 bits in the input. This is an optimized implementation that gives the same result as shifting each bit separately to the bottom of a register and adding it to a total. See https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
This implementation works by building up from 2-bit accumulators to 4-bit, 8-bit, and 16-bit using SWAR to do multiple narrow adds that don't carry into each other with one add instruction.
Notice how it masks every other bit, then every pair of bits, then every group of 4 bits. And uses a shift to bring the other pair down to line up for an add. Like C
(x & mask) + ((x>>1) & mask)
Repeating this with a larger shift and a different mask eventually gives you the sum of all the bits (treating them all as having place-value of 1), i.e. the number of set bits in the input.
So the GNU C representation of this is __builtin_popcnt(x).
(Except that compilers will actually use a more efficient popcnt: either a byte lookup table for each byte separately, or a bithack that starts this way, but uses a multiply by a number like 0x01010101 to horizontal sum 4 bytes into the high byte of the result. Because multiply is a shift-and-add instruction. How to count the number of set bits in a 32-bit integer?)
But this is broken: it needs to use addu to avoid faulting; if you try to popcnt 0x80000000, the first add will have both inputs = 0x40000000, thus producing signed overflow and faulting.
IDK why anyone uses the add instruction on MIPS. The normal binary add instruction is called addu.
The add-with-trapping-on-signed-overflow instruction is add, which is rarely what you want even if your numbers are signed. You might as well just forget it exists and use addu / addui

How do I get an INTEGER and turn that into an ARRAY of separate single digit integers in MIPS?

Okay so I have an issue. I want to get an integer and turn it into an array of single-digit integers in MIPS but I'm not sure how to go about that.
Can you guys help me? I know how to do this in every other language except this one...
Example:
I want to the integer 32325
to be an array where A[0] = 3, A[1] = 2, A[2] = 3, ...
Can you please help me? I've been stumped for a while!
This is what I have so far...
.data
prompt: .asciiz
msg: .asciiz
array: .space 24 #6 digit number
.text
li $v0, 4 #print out
la $a0, prompt1
syscall
li $v0, 5 #take in int
syscall
la $a0, array# Set address t0 to be the array
I have no idea about MIPS, but the algorithm is quite simple
Divide the number by 10, as long as it is != 0 ... the reminders (in reverse order) are the digits. easiest way to store them would be the stack, since pop'ing them will bring them into correct order again:
counter=0
while (number !=0) {
push number%10
number /= 10
counter++
}
while (counter>0) {
pop number
store/display it
counter--
}

MIPS - Accessing an array

So i have an array, that is filled previously with 1's or 0's, whenever i try to compile this code MIPS gives me a syntax error, could someone explain what this syntax error is? I'm having trouble understanding why you can't access the array like that, of course $t1 is a counter for the index, which increments up through 100
slti $t7, prim_flag($t1), 1 # checks if prim_flag ($t1) < 1 stores 1 if so stores 0 if not
beq $t7, 0, print_numbers # checks if the value in $t7 is 0, if so jump to end_game
and the array:
.data
test: .asciiz "Printing numbers:"
test_2: .asciiz "Before loop"
space: .asciiz " "
done: .asciiz "\n Done printing the array"
numbers:
.word 0:210
numbers_size:
.word 210
prim_flag:
.word 1:210
The only valid operand combination for slti is register,register,immediate. You're trying to use register,memory,immediate, and there's simply no such version of slti in the MIPS instruction set.
Practically every time you need to perform an operation on some data in memory in MIPS assembly, you first have to load that data into a register using lb/lh/lw; then you can perform the operation you need on that register; and finally write some result back to memory if necessary.
Also note that the constant to the left of the parentheses in prim_flag($t1) is an offset, not the base address. The base address is the part that's inside the parentheses, and has to be a register. And since the offset has to fit in 16 bits due to how MIPS instructions are encoded, it's possible that prim_flag won't fit. So you might have to load the address of prim_flag into some register, then add that register plus $t1 and store the sum in a third register, and then read from memory using that last register as the base address.

MIPS Assembly creating character checker

I am looking for help on how to take a string from the user and then output the number of times each letter was used in the string.
Pseudo code
string "Please enter a string:"
take string and save into an array,
check for ascii duplicates of character values and then output when corresponding letter is output.
example: Hello World
A:
B:
C:
D: 1
E: 1
...
H: 1
...
W: 1
code
.data
intro: .asciiz "Letter Checker Program"
question: .asciiz "\nPlease enter a string for evaluation: "
string: .space 1024
alphabet: .space 26
.text
main:
jal setup
#jal analyze
#jal results
li $v0, 10
syscall
setup:
li $v0, 4 # outputing name and program information
la $a0, intro
syscall
li $v0, 4 # asksing for string input
la $a0, question
syscall
li $v0, 8
la $a0, string
li $a1, 1024
syscall
jr $ra # return
analyze:
loop:
loop:
results:
What you want to do is:
Create some space (26 * 4 bytes) to store the results and fill with 0
Loop over every letter in the string and load with lb
Determine the numerical value of the letter, and thus the memory location (of step 1). Don't forget about lower and upper case letters.
Load that memory location (4 bytes, use lw), increase the value with 1, and store again with sw
Stop when you encounter 0 (not the letter '0')
In analyze, loop over every letter in the alphabet, load the corresponding memory location from step 1, and print results

Resources