SRL Archive - General

Help with Assembly assignment


Recursive

2013-01-23 21:57:06

I have to implement the following in MIPS assembly language:

#Write,and test using spim, and assembly language program
that inputs a positive integer 'N' from the user, followed by 'N' integers.
Your program should output how many of the 'N' integers have
a value greater than or equal to 80 but less than 100.


Here is what I have so far:


#Author: Banana Colada

#MIPS Code


.data #Let processor know we will be submitting data to our program

Ask_Input:

.asciiz "\Please enter the size of the array\n"
#This will get a number from the user and store int unsed memory with Ask_Input

Tell_Input:

.asciiz "\Numbers greater than or equal to 80 but less than 100: "
#This will print all numbers in our array that is greater than 80

NumArray:

.space Ask_Input//This doesn't look right


.text #enables text input / output. Start of code

main: #main function. Program starts here


la $a0, Ask_Input
#load address Ask_Input from memory and store it into arguement register 0

li $v0, 4 #Load the value 4 into register $v0
syscall #reads register $v0 for op code, sees 4 and prints the string located in $a0

li $s0, NumArray #Load the address of start of array into address $s0

loop:

My problem is, how do I use the input from the user to declare the size of the array?

E: If possible, I would also like to output the values to the user so where do I store the values that are in the range I am looking for and How?

CynicRus

2013-01-23 22:46:17

I think you should use test assembly command(test eax, 100b) or test equalent in Mips.

Recursive

2013-01-23 23:06:41

Is that a command or program? And how do I use it?

CynicRus

2013-01-24 00:43:18

Ok, small assembly example: validate the input numbers.


;C naming conv: console - get unsigned long
_cgetul: xor edx, edx
mov cx, 10 ; ???-?? ??????
next: xor ax, ax ;
int 16h ;
cmp ah, 1 ; <ESC>?
jz cancel
cmp ah, 1Ch ; <Enter>?
jz done
cmp al, 30h
jb next
cmp al, 39h
ja next
movzx eax,al ; ??????? ?? eax ??????
lea edx,[edx*4+edx] ; EDX = EDX * 5
lea edx,[edx*2+eax-48] ; EDX = EDX * 2 + ?????? ?? AL - '0'
int 29h ; ??????? ?? ?????
loop next
done: mov eax, edx ;
ret
cancel: xor eax, eax
dec eax ; EAX = -1
stc ;
ret

Recursive

2013-01-24 01:49:19

From: CynicRus
Ok, small assembly example: validate the input numbers.


I mean no offence CynicRus, but that code did not make much sense to me, partly because it has only been 3 weeks since I first set eye on assembly code and I don't even know where to start reading yours from. Here is what I have so far. I decided not to go with the array approach after all. However this one is not working. Infact I am getting no output at all. Help please!:

#Write,and test using spim, and assembly language program that inputs a positive integer 'N' from the user, followed by 'N' integers. Your program should output how many of the 'N' integers have a value greater than or equal to 80 but less than 100.

#Author: Banana Colada

#MIPS Code


.data
#Let processor know we will be submitting data to our program

Ask_Input:

.asciiz "\tPlease enter number of values\n\t"
#This will get a number from the user and store int unsed memory with Ask_Input

Tell_Input:

.asciiz "\n\tNumbers greater than or equal to 80 but less than 100: "
#This will get a number from the user and store int unsed memory with Tell_Input

Ask_Num:

.asciiz "\tEnter a number:\n\t"
#Prompts user for a number


.text #enables text input / output. Start of code
main: #Program starts here

li $v0, 4
la $a0, Ask_Input#load address Ask_Input from memory and store it into arguement register $a0
li $v1, 5 #Get size of array
syscall #Get size of the array

li $s3, 0 #Will keep track of how many numbers x satisfy (80 <= x < 100)
loop1: #loop start
li $v0, 4
la $a0, Ask_Num #Loads address Ask_Num from memory and store it into arguement register 1

li $v0, 5
syscall #Get number from user
addi $v1, $v1, -1 #decrease counter
bnez $v1, GetSom #if size is not zero
blez $v1, end
syscall



end:
move $t1, $s3
li $v0, 4
la $a0, Tell_Input
lw $t0, ($t1)
syscall



loop2:
addi $s3, $s3, 1
bnez $v1, loop1
beq $v1, $zero, end
syscall




GetSom:
bge $v0, 100, loop1
bge $v0, 80, loop2
syscall





li $v0, 10
syscall

CynicRus

2013-01-24 01:58:13

Unfortunately I'm here I can not help you, because the only familiar with the assembler from Intel(x86).Srry:(

Recursive

2013-01-24 11:07:34

From: CynicRus
Unfortunately I'm here I can not help you, because the only familiar with the assembler from Intel(x86).Srry:(


Np, thanks anyway for trying. Thing I hate about assembler is how every processor is different and depending on the architecture, one can't apply their knowledge across all assembler lang

Brandon

2013-01-25 01:48:35

Can Assemble this using FASM.. It's not exactly what you want, but it should get you started. It shouldn't be too hard to translate between different Assemblers. I'm not used to MIPS, but I've used it once or twice.. Not enough to be able to translate this but I'm hoping the comments in the code below might give you clues or help in some way..



format PE console ;Format PE OUT GUI 4.0
entry main

include 'macro/import32.inc'

section '.idata' import data readable ;Import Section.
library msvcrt,'msvcrt.dll'
import msvcrt, printf, 'printf',\
exit,'exit', getchar, 'getchar', scanf, 'scanf'

section '.data' data readable writeable ;Constants/Static Section. This section can store variables.
Size dd 0 ;Array Size. A Dword Initialized to 0
PromptValue db "Enter A Number: ", 13, 10, 0 ;Prompt User For A Number.
FuncPrint db 13, 10, 13, 10, "Calling Function: %s", 13, 10, 0 ;Statement For Function.
Response db 13, 10, 13, 10, "You Entered: %d", 13, 10, 0 ;Statement For Number.
InputFormat db "%d", 0 ;Format Data
IntArray dd 0 ;Declare Dword Initialized to 0
Index dd 0


section '.code' code readable executable
main:
push ebp
mov ebp,esp

push PromptValue ;Ask the user to Enter a number.
call [printf]
add esp, 4

push Size
push InputFormat
call [scanf] ;Call scanf with the "%d" and the variable to hold the integer.
add esp, 8

push [Size]
push Response
call [printf] ;Print the value the user entered with "%d".
add esp, 8

mov ecx, [Size] ;Store the Array Size/Number in the count register.
mov [Index], 0 ;Set the Index variable to 0.

ASSIGN: ;The beginning of a loop.
push ecx ;Backup our count because printf discards it.
mov ecx, [Index] ;Move our index to the new count register.
inc [Index] ;Increment the index.
mov [IntArray + 4 * ecx], ecx ;Change the value at the array's index to the current count.
pop ecx ;Restore our old count.
loop ASSIGN ;Loop if Count is > 0.. else break.


;TODO: Add Loop to print array..


mov [Index], 65 ;Store the character A in variable called Index.
push Index ;Pass Index to the function as a parameter by pushing it onto the stack.
call Function ;Call the function.
add esp, 4 ;Restore the stack pointer..


mov esp, ebp
pop ebx

call [getchar] ;Wait until the user presses a key before we exit.
call [getchar]

mov eax, 0 ;Return 0.
ret


Function:
push ebp
mov ebp, esp
mov eax, [ebp + 8] ;Function Parameter

push eax
push FuncPrint
call [printf] ;Print the Parameter Passed..
add esp, 8

mov esp, ebp
pop ebp
ret

Recursive

2013-01-25 01:53:37

Yo Brandon, can you please look at my code and tell me why it is not working. All it does it print out the prompt and then it stops. I didn't know you knew some assembly otherwise I would be pm'ing you this question

Brandon

2013-01-25 02:30:41

From: [Re]cUrSivE
Yo Brandon, can you please look at my code and tell me why it is not working. All it does it print out the prompt and then it stops. I didn't know you knew some assembly otherwise I would be pm'ing you this question


I know a lot of languages; I learn very fast. Just C++ is my favourite. x86 ASM is my second favourite. Though.. It's very tedious.

Uhh.. I tried.. I of course had to download that hideous MIPS simulator? Thing.. came in a jar file.. and I used this site to help:

http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm


It gets the input but I can't seem to figure out why it won't print it back.. I'll try again, run it and see if it works though.

EDIT.. Solved the stupid printing.. I accidentally put an extra System Call after the move $t0, $a0.. Removed it below.. I'll comment the line so you can see..

I have to say.. I HATED writing this.. It sucks.. I've never seen a Java/.jar assembler in my life.. Had the hardest time figuring out how to use it -__-
You might have a hard time convincing me to write "MIPS ASM" in future posts :l Interesting though, so I might.


To get strings from the user (I'm really really really tired.. So, I'll comment it in the morning.. If I don't, just tag me or msg me or something.. Iunno.. Good night):

.data #Data Section.

Input: .space 1024
Prompt: .asciiz "Enter A String:\n"
Notice: .asciiz "You Entered: "
Space: .asciiz " "
NewLine: .asciiz "\n"




.text

main:
li $v0, 4 #4 means to print string.
la $a0, Prompt #Pass the value to print on screen. Similar to pushing stuff into eax.
syscall #Perform the system call for printing string.

li $v0, 8 #8 means to read string.
la $a0, Input #Point To The Variable Which will hold our User Input.
la $a1, 1024 #That Variable is a size of 1024. That way, we don't overflow.
syscall #Get the user input via the system call to read string.

la $a0 Input #Point to our string.
move $t0, $a0 #Save/Copy Input-String into $t0.
#syscall #Commented out for reasons explained in my post..

la $a0, Notice #Point to our Notice string which tells the user what they entered.
li $v0, 4 #4 means to print string.
syscall #Carry out the print via system call.

la $a0, Input #Point to our Input-String.
move $a0, $t0 #Move/Copy the saved Input string to the loaded address/register.
li $v0, 4 #4 means to print. Here we are going to print the user input after telling them our Notice.
syscall #Invoke the print via System call.

li $v0, 10 #Exit the program.
syscall #Invoke exiting via System call.



Your assignment (Getting integers from the user):


.data #Data Section.

Input: .word 0
Prompt: .asciiz "\nEnter An Array Length:\n"
Prompt_Two: .asciiz "\nEnter Another Number:\n"
Notice: .asciiz " Is >= 80 AND < 100"
Space: .asciiz " "
NewLine: .asciiz "\n"




.text

main:
li $v0, 4 #4 means to print string.
la $a0, Prompt #Pass the value to print on screen.
syscall #Perform the system call for printing string.

li $v0, 5 #5 means to read input. This reads the length from the user.
syscall #Get the user input via the system call to read string.
move $s3, $v0 #Store the length of the array.. Similar to ECX register in x86.


GetNumbers: #Beginning of the loop.

subi $s3, $s3, 1 #Decrease the count.. This determines whether we break out of the loop or not.
beqz $s3, EndNumbers #if our count = 0, break out of the loop.

li $v0, 4 #Ask the user to enter another number.
la $a0, Prompt_Two
syscall

li $v0, 5 #wait for user input.
syscall
move $a0, $v0 #store their number in the $a0 register. Similar to eax

blt $v0, 80, GetNumbers #if the number is less than 80, don't bother printing it.
bge $v0, 100, GetNumbers #or.. if it is greater than 100, don't print it either..

li $v0, 1 #print integer.. this will print the number..
syscall
li $v0, 4 #print string.. this will print the Notice.. thus, it prints: SOmeNumber: Is >= 80 && < 100.
la $a0, Notice
syscall

b GetNumbers #continue the loop.. The loop only breaks when count reaches 0.

EndNumbers:



li $v0, 10 #Exit the program.
syscall #Invoke exiting via System call.



EDIT:

I added comments to the code so you can see how the code works.. Surprised I learned mips so quickly. :l

Recursive

2013-01-25 04:15:13

@Brandon

Thanks Brandon. Would your solution work if I was trying also to do some arithmetic with the value I got? Assuming the user only enters numbers, how would I take that number and add it to something then print the sum?

Brandon

2013-01-25 10:43:02

Yeah just add the register the number is in with whatever else you want to add it with.

I added the comments to the code above so you can see what is stored where and what it does.


If you want to add numbers the user enters, according to the code above, the number the user entered is stored in $a0 and $v0. Let me know if you can follow the comments I added. Hopefully I wrote them properly.


What you can do is:


addi $a0, $a0, 500 #adds 500 + $a0 to a0.
addi $a0, $v0, 500 #adds 500 + $v0 to $a0.

mov $v0, 0 #Set $v0 register to hold a value of 0.
addi $a0, $v0, 500 #add 500 to $a0 because $v0 is = to 0.

#etc.. etc..

Recursive

2013-01-25 14:49:18

Thanks Brandon. I noticed you did this:

subi $s3, $s3, 1        #Decrease the count.. This determines whether we break out of the loop or

I learned today that there really is no subtract in MIPS. So what it actually does is to add the negative of the number to value in the register and store in the register specified.

So it does this instead:

addi $s3, $s3, -1        #Decrease the count.. This determines whether we break out of the loop or


What does mean?
b GetNumbers             #continue the loop.. The loop only breaks when count reaches 0.

what does the b do?


EDIT: Works now!

#Write,and test using spim, and assembly language 
#program that inputs a positive integer 'N' from
#the user, followed by 'N' integers. Your program
#should output how many of the 'N' integers have a
#value greater than or equal to 80 but less than 100.

#Author: Banana Colada

#MIPS Code


.data
#Let processor know we will be submitting data to our program

Ask_Input: .asciiz "\tPlease enter number of values\n\t"
#This will get a number from the user and store int unsed memory with Ask_Input

Tell_Input: .asciiz "\tNumbers greater than or equal to 80 but less than 100:\n\t "
#This will get a number from the user and store int unsed memory with Tell_Input

Ask_Num: .asciiz "\tEnter a number:\n\t"
#Prompts user for a number







.text #enables text input / output. Start of code

main: #Program starts here

li $v0, 4 #4 means to print string
la $a0, Ask_Input #load address Ask_Input from memory and store it into arguement register $a0
syscall #Perform system call for printing string


li $v0, 5 #5 means to read in a number
syscall #Get user input using syscall
move $s3, $v0 #Store length of array in register $s3

li $s0, 0 #Load the number 0 into address s0, this will be our counter
GetNum: #Get numbers loop

blez $s3, Exit #First we check that the length of the array is greater than zero
li $v0, 4 #4 means to print a string
la $a0, Ask_Num
syscall #Ask for another number

li $v0, 5
syscall #Get a number from the user
move $s1, $v0 #Store the number in register $s1

addi $s3, $s3, -1 #Decrease count of numbers
bgez $s3, CheckNum #Check our numbers
syscall



CheckNum:
blt $v0, 80, GetNum #If the number is less than 80, loop again
bge $v0, 100, GetNum #If number is greater than or equal to 100, go back to loop

addi $s0, $s0, 1 #Add a one to the sum of numbers that meet requirement
b GetNum #branch to the start of the loop



Exit:

li $v0, 4 #4 means to read in a string
la $a0, Tell_Input
syscall #Print our string

move $a0, $s0 #move the value in $s0 to $a0
li $v0, 1 #1 means to print a number
syscall #print the number

li $v0, 10 #Exit code
syscall

Why is it only while using $a0 that it prints the correct output?

Brandon

2013-01-25 16:06:32

From: [Re]cUrSivE
Thanks Brandon. I noticed you did this:

subi $s3, $s3, 1        #Decrease the count.. This determines whether we break out of the loop or

I learned today that there really is no subtract in MIPS. So what it actually does is to add the negative of the number to value in the register and store in the register specified.

So it does this instead:

addi $s3, $s3, -1        #Decrease the count.. This determines whether we break out of the loop or


What does mean?
b GetNumbers             #continue the loop.. The loop only breaks when count reaches 0.

what does the b do?



be means branch if equal.. it's like je which means jump if equal in x86. AKA if (condition) goto Label in C/C++.
bnez means branch if not equal to zero.
b means to branch unconditionally. Aka jmp in x86 or goto Label in C/C++


Thus:

b GetNumbers will jump directly to the GetNumbers Label.. This just so happens to be the beginning of the loop.
be $a0, 50, GetNumbers will jump to GetNumbers if $a0 register contains the value 50.

etc..


it's like this:


for (int I = 10; I > 0; --I) //This is 4 instructions.. (move $s3, 10).. (beqz $s3, EndLabel), (Addi $s3, $s3, -1), (b LoopAgain)
{
//Do something.
}

Which is equivalent to:


move $s3, 10 ;Set I as 10.. Every loop, we can decrease I by 1.

For: ;The beginning of the for-loop.
beqz $s3, Break ;If I == 0, break out of the loop. Jump to the break label.
;Do Something..
addi $s3, $s3, -1 ;Decrease I by 1 every time we loop. Remember? The for-loop decrements at the end of the loop. AKA Last Instruction.
b For ;Loop again by jumping to the For label.


Break:


To be fair to any mathematician/physicist/programmer, addition and subtraction are the exact same really..

-5 + 3

is the same as

3 - 5

So saying there is no subtraction(just add negative value) can easily be worded the other way by saying there is no addition(just subtract negative value)..

Bedmas says other-wise though but in assembly it doesn't matter.

Recursive

2013-01-25 17:43:00

From: Brandon


To be fair to any mathematician/physicist/programmer, addition and subtraction are the exact same really..

-5 + 3

is the same as

3 - 5

So saying there is no subtraction(just add negative value) can easily be worded the other way by saying there is no addition(just subtract negative value)..

Bedmas says other-wise though but in assembly it doesn't matter.


I wasn't saying that there is no subtraction. I am saying that in the way it is implemented in MIPS, subtraction calls add and adds the negative of the number. Hence there is no code (so to speak) for sub because it just calls another function (add)