Hi everybody! :U
I am using PCSpim and I have to do an exercise which really drives me crazy:
"Translate the following program fragment into MIPS code ($t0 must contain the variable a).
IF (a < 0) OR (a > 99) THEN
a := a - 10;
ELSE
a := a - 1;
END;
Please note: the expression a > 99 will be only analysed in case a < 0 is false."
Since I am totally new to SPIM, I have no idea how to implement this exercise.
I think a XOR construction is necessary and they don't ask for a whole working program, but only for a specific fragment. So I would write:
main: xor (bltz a), (bgt a, 99)
then:
But the compiler gives me a syntax error right after xor.
Can you please help me?
I really appreciate that.
Regards,
Herakles.
From what I remember of MIPS conditionals can be implemented by comparing a register to the zero register then doing conditional branching based on that. So subtract the two things you want to test for equality and compare the result. If you have problems later I'll write some code for you. Give it a go and post up here :)
You don't need a XOR. Just test the first condition. If true, branch to the IF code. If not, test the second condition. If that one is true, branch to the IF code again. Else, fall through to the ELSE code. Simple as that ^_^
Do you need a 'template' for a SPIM program at all ? A fully working program is not hard to produce at all.
In MIPs you do not put operands in brackets. Also you can not xor two instructions either.. Instructions are performed one at a time. Try to implement it as I described.
Quote from: Slugsnack on May 02, 2010, 02:19:33 PM
From what I remember of MIPS conditionals can be implemented by comparing a register to the zero register then doing conditional branching based on that. So subtract the two things you want to test for equality and compare the result. If you have problems later I'll write some code for you. Give it a go and post up here :)
Thx Slugsnack.
I am a completely layman to Assembler...
Do you think it's wrong using xor?
Yes sorry, edited my post just before you replied. Try and follow the method I described. Oh yeah.. forgot about BLTZ, that will work too. Just try and make something, post it up here and I'll tell you what's wrong with it.
Quote from: Slugsnack on May 02, 2010, 02:38:43 PM
Yes sorry, edited my post just before you replied. Try and follow the method I described.
Thanks, Slugsnack for the amazing support. :U
.text
main: li $t0, 15
if: bltz $t0, then
bgt $t0, 99, then
b else
then: sub $t0, $t0, 10
else: sub $t0, $t0, 1
I hope, this code is correct...
EDIT:
Do you think its OK that I have initialised $t0 with 15?
In case I initialise it with a, it certainly doesn't work...
Your 'then' code falls through to your 'else' code so you want to put an unconditional branch after it to some exit at the end which the else code could fall through to.
Realistically, a variable is probably in memory so you wouldn't be loading an immediate, so maybe consider using 'lw' instead of 'li'. To solve the falling through problem, just define a label after the 'else' and have it so after your 'then' 'sub', it branches to that label. I don't remember precisely, but I'm not sure SUB can take an immediate value for its parameters. I think you'd have to load those constants into another register and do the sub like that. I'm not 100% sure since last time I programmed MIPS was a while ago. Your best bet is to check the documentation or try to assemble it in SPIM and see if you get any errors.
If I was doing this for an assignment, I would not initialise 'a' as 15. At least not as an immediate. I would declare it in the data section, initialising it to some value and then put a comment explaining.
My problem is, that I am a beginner, so I don't have the feeling, how the compiler behaves...
Does it check, if lw $t0, a is true and if yes, it jumps to then, or does it afterwards automatically check if bltz $t0, then is true, before it jumps to then?
I really have problems fixing this code with your suggestions, because this OR still irritates me (without this OR, this would be the easiest exercise)...
.data
a: .word 15
.text
main: lw $t0, a
bltz $t0, then
bgt $t0, 99, then
b else
then: sub $t0, $t0, 10
else: sub $t0, $t0, 1
'lw $t0, a' can't be true or false. It is merely instructing the CPU to load the word at label 'a' into register $t0. It is completely independent of any other instruction. At runtime, this happens. Then afterwards, the instruction 'bltz $t0, then' is evaluated. That means at runtime, the compiler checks the value of $t0 and IF it is less than zero, it will branch to 'then'. If not, it just falls through to the next instruction.
For the sub, I wonder if you can use ADDI with a negative third operand. Try and assemble your code and see if it is at least syntactically correct. You have also yet to add the code to stop the 'then' code falling through to the 'else' code.
You should not worry too much about the OR. What I have advised you to do can be described as 'lazy evaluation'. You are evaluating each condition only when necessary. Another way, less efficiently would be to evaluate both, storing the results in different registers. Then you would OR those registers and branch conditionally on that. I hope you can understand why the current method is better.
Welllll if I get bored later, I'll SSH into school and use the SPIM there to test your proggy. Lazy to install it on my box..
// edit : Couldn't resist.. got bored. Found the source for the compiler I wrote last term and generated some code.
http://img413.imageshack.us/img413/1644/77138900.png
Hope you get the idea now. And btw, bad variable names is because they are auto-generated by my compiler code. You'll notice my compiler generated a 'sw' and 'li' instruction. That sort of really depends on your situation and how you wish to define a variable as..
Here's a different piece of code I compiled that you also may be interested in :]
http://img146.imageshack.us/img146/2/25116878.png
Can't find the final version of my source so there are some optimisations missing. For example.. in the second screenshot, there is not really a need to use $v1, we can just operate straight on $v0. Hope you get the idea..
Thanks again Slugsnack, especially for the excellent explanation! :U
.data
a: .word 15
.text
main: lw $t0, a # $t0 := a
bltz $t0, then # IF a < 0
bgt $t0, 99, then # IF a > 99
b else
then: sub $t0, $t0, 10 # THEN $t0 := $t0 - 10
b endif
else: sub $t0, $t0, 1 # ELSE $t0 := $t0 - 1
endif: # END;(*IF*)
QuoteFor the sub, I wonder if you can use ADDI with a negative third operand. Try and assemble your code and see if it is at least syntactically correct.
What do you mean with ADDI?
I didn't get any error messages.
Yeah sorry.. haven't messed with MIPS for a while.. so uhh duhhhh moment. Anyway check out the images I posted above.
Amazing. I wish I had your program skills...
Thanks for the pics, but as I said: I am raw recruit. :red
BTW: I don't think they expect us to become good programmers. They want us more to be able to read code and to create small programms...
Would you say that this is acceptable as a solution to the exercise?
.data
a: .word 15
.text
main: lw $t0, a # $t0 := a
bltz $t0, then # IF a < 0
bgt $t0, 99, then # IF a > 99
b else
then: sub $t0, $t0, 10 # THEN $t0 := $t0 - 10
b endif
else: sub $t0, $t0, 1 # ELSE $t0 := $t0 - 1
endif: # END;(*IF*)
Don't know, looks fine to me if they're not expecting a full solution :] As you can see, it's pretty much identical to the first code generated by my compiler.
I don't think they want a full solution... At least they didn't ask for it in the task. I will see when I get the exercise back in few days. :green
Thank you very much for your help.
Cya
Btw since you seemed to have some problems understanding the concepts of assembly a bit earlier let me use an analogy. We can take a 'context' of a program at any given time. This context consists of things that represent its current state. This could include next instruction to be executed, register values, stack values, etc. Each time an instruction is executed, we modify this state and this context changes. So you have an initial state and as we do each instruction, a part of the context is changed. When we get onto conditional branches, depending on the definition of the instruction, the computer looks at this context and does something based on it. Sometimes, like in your case, we can know what this context will actually be. Sometimes, we have true variables, like the second code I generated which gets user input. The flow of the program is then completely non-deterministic.
Damn.. I suck at explaining. I'll just stick to playing Street Fighter from now on..
Your explanation (and of course all your other explanations) is very good and helpful! :U
Many people tend to become sarcastic in case a new member is searching for help in the forums. So I really do appreciate your no-nonsense work.
I'll give you the results when they have finished the correction, but I guess it will take a couple of days...
Regards,
Herakles.
Going back to your original attempt, it might very well be more efficient to lose the branch and drop through
then: sub $t0, $t0, 9 # THEN $t0 := $t0 - 10 (-9 followed by -1)
else: sub $t0, $t0, 1 # ELSE $t0 := $t0 - 1
Quote from: clive on May 03, 2010, 05:46:47 PM
Going back to your original attempt, it might very well be more efficient to lose the branch and drop through
then: sub $t0, $t0, 9 # THEN $t0 := $t0 - 10 (-9 followed by -1)
else: sub $t0, $t0, 1 # ELSE $t0 := $t0 - 1
I thought of this but figured because of the dependency, the data hazard would stall the pipeline and cause a bubble so didn't bother suggesting it.
Would be a problem in implementations without register forwarding. Adding a NOPs would still be cheaper than a branch with an empty slot.
Something along the lines of this might also be viable, but assumes negative numbers are larger than 100 in unsigned space.
sltu $t2,$t0,100 ; MIPS IV
addiu $t1,$t0,-10
addiu $t0,$t0,-1
nop
movz $t0,$t1,$t2
Here is the result, as promised:
No mistakes, full points.
Thank you so much for your help! :U
For us, SPIM is part of "computer architecture" and it makes up only about 25% of the course.
We have to do another exercise and I'll post it later on, since it seems to be difficult (sth. like write a programme, that reads in a string and changes the small letters to capital ones).
Quote from: Herakles on May 17, 2010, 02:29:41 PM
We have to do another exercise and I'll post it later on, since it seems to be difficult (sth. like write a programme, that reads in a string and changes the small letters to capital ones).
changing from uppercase to lowercase and vice-versa is a very simple exercise (assuming you're using the ascii charset)
A = 01000001
a = 01100001
as you can see changing between upper/lowercase is just a case of toggling a single bit
Quote from: brethren on May 17, 2010, 03:22:05 PMchanging from uppercase to lowercase and vice-versa is a very simple exercise (assuming you're using the ascii charset)
A = 01000001
a = 01100001
as you can see changing between upper/lowercase is just a case of toggling a single bit
I have to make myself familiar with the new aspects so I'll hopefully be able to write a working programme.
I've started a new thread containing the current exercise.