How to convert a three address code to MIPS Assembly language? - c++

I am doing a project in which I have to create a translator that would generate a MIPS assembly code for a C code. The programming language that am using is C++ and I have done till generation of three address code and am really confused about how to proceed further.

As already stated, it's a direct translation. There's really nothing to clarify. As an example, take the following three-address code:
i := 0 ; assignment
L1: if i >= 10 goto L2 ; conditional jump
t0 := i*i
t1 := &b ; address-of operation
t2 := t1 + i ; t2 holds the address of b[i]
*t2 := t0 ; store through pointer
i := i + 1
goto L1
L2:
The MIPS translation is:
li $t0, 0 #allocator assigned i to t0
L1: bge $t0, 10, L2
mult $t1, $t0, $t0
la $t2, b
add $t3, $t2, $t0
sw $t1, ($t3)
addi $t0, $t0, 1
j L1
L2:
If your lucky enough to have three-address like that, you barely have to do anything. Find the corresponding opcode to go with the instruction. The register allocation has already been done. If the three-address code is literally a bunch a strings, I'd consider writing a small parser (using a generator) instead of trying to extract information from the strings.

Related

MIPS if greater or equals to

if ($t4 >= $5)
$t8 = $t8+1
Given that pseudo-code, I put this attempt together based on various sources. Seems simple but i am still learning the foundations. Not too sure if this is correct.
slt $t1, $t5, $t4
beq $t0, $zero, endLoop
addi $8, $8, 1
Main reference: Greater than, less than equal, greater than equal in MIPS
You have some typos:
Your branch instruction is testing $t0, but the target of the slt is $t1 so that is a mismatch.
You have a conditional branch instruction with a label, but don't define the label.
Your label name is endLoop, but this is just an if, not a while or other loop condition, and the the statement controlled by the if isn't a break.
Otherwise looks like you have the right idea.  But this is tricky stuff to get right.
To be clear, you are aware that we have to reverse (negate re: boolean logic) the sense of the condition for assembly language's if-goto style, as compared with structured programming's if-then construct.
if (t4 >= t5)
t8++;
becomes
if (t4 < t5) goto skip; // !(a >= b) ---> a < b
t8++;
skip: ;
Now, I would have written the above more directly in assembly:
slt $t1, $t4 $t5 # let's see if t4 < t5
bne $t1, $zero, skip # yes? goto skip
addi $t8,$t8,1
skip:
Instead you have reversed the operands $t4 and $t5, and then also reversed the branch condition: beq vs. my bne.  This is very close to a triple negation of the (structured style) C (and this would have worked), but there is a subtle difference.
So, what you have written is:
if (!(t5 < t4)) goto skip;
t8++;
skip: ;
which — translated to structure programming — is:
if (t5 < t4) // logically: remove the negation and incorporate then
t8++;
and we can see that if we reverse the operands but also switch the relation, we have:
if (t4 > t5) // same exact logical condition as immediately above
t8++;
So, your code does not produce the same condition test as the C code, since the operation under equality is different from the original.
You assembly code is doing t4 > t5, and the C code is doing t4 >= t5.  See the difference?
This stuff is tricky because:
We have to reverse (negate) the condition when going between structured statement and if-goto style, and,
MIPS provides only one of the ordered relational operations (it has < but not <=, >, >=), and so, that means when we need what would have been sge we have to simulate it (via slt by reversing operands and/or reversing the branch on true vs. branch false).
Related:
Mutiple conditions in if in MIPS - if( x<y && x<z ) or similar. One way is to compare into booleans and AND or OR them together, instead of short-circuiting by doing multiple branches.
How can I implement if(condition1 && condition2) in MIPS? - if (x < 10 && x > 5) or similar: with two branches, or with the range-check trick.
How to do less than or equal in Assembly Language(MIPS)? - compare into boolean integer for conditions other than slt

How to write if-else in assembly?

How do you write the if else statement below in assembly languange?
C Code:
If ( input < WaterLevel)
{
MC = 1;
}
else if ( input == WaterLevel)
{
MC = 0;
}
Pseudocode
If input < Water Level
Send 1 to microcontroller
Turn Motor On
Else if input == Water Level
Send 0 to microcontroller
Turn Motor Off
Incomplete Assembly: (MC- Microcontroller)
CMP Input, WaterLevel
MOV word[MC], 1
MOV word[MC], 2
If we want to do something in C like:
if (ax < bx)
{
X = -1;
}
else
{
X = 1;
}
it would look in Assembly like this:
cmp ax, bx
jl Less
mov word [X], 1
jmp Both
Less:
mov word [X], -1
Both:
Not knowing the particular assembly language you are using, I'll write this out in pseudocode:
compare input to waterlevel
if less, jump to A
if equal, jump to B
jump to C
A:
send 1 to microcontroller
turn motor on
jump to C
B:
send 0 to microcontroller
turn motor off
C:
...
For the first three commands: most assembly languages have conditional branch commands to test the value of the zero or sign bit and jump or not according to whether the bit is set.

If-Else with nested If in MIPS assembly

I am trying to code something that continually takes in an integer from the user and stores the minimum value into $s2.
This is a C code representation of what I am trying to do
if ( $s2 == 0 )
$s2 = $t0
else {
if ( $t0 < $s2 )
$s2 = $t0
}
Basically, I loaded $s2 with zero outside of the input loop. This checks if $s2 has zero, and sets it to the current (first) user input ($t0) since that is the minimum value. If $s2 no longer contains zero then it checks the new user input against what is already in $s2 and if it is less than it becomes the new minimum value.
How can I implement this in MIPS assembly?
I have this so far (this is the end piece of a loop called read) but all it does is when I press the first int, it skips to the end and prints the min without looping over.
read:
...
beq $s2, $zero, LOAD
slt $s6, $t0, $s2
bne $s6, $zero, LOAD
j read
LOAD:
li $s2, 0
addu $s2, $s2, $t0
The main problem is that you need a jump at the bottom of your code because you're [probably] "falling off the edge of the world":
read:
...
beq $s2,$zero,LOAD
slt $s6,$t0,$s2
bne $s6,$zero,LOAD
j read
LOAD:
# NOTE: you could use $zero as you did above to eliminate the "li" here
li $s2,0
addu $s2,$s2,$t0
# NOTE/BUG: need to jump back to read loop
j read
The code can be shortened a bit.
From the slt (vs. sltu) we know that the values are signed. So, if we prefill $s0 with the maximum positive value (i.e. 0x7FFFFFFF) instead of zero, we can remove the first beq from the loop.
Also, if we reverse the sense of the branch after the slt, we can eliminate an extra j instruction.
We can change the addu to use $zero and eliminate the li
li $s2,0x7FFFFFFF # load maximum positive value
read:
...
slt $s6,$t0,$s2 # is new value < minimum?
beq $s6,$zero,read # if no, loop
addu $s2,$zero,$t0 # save new minimum value
j read # restart input loop

how can you translate the statement if(isalpha(c)) from C++ to MIPS? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to translate the statement if(isalpha(c)), where c is a char variable, from C++ to MIPS assembly. I tried to google it, but I could not find an answer. Does anyone have any idea? Thanks for your time.
I'm just going to demonstrate one possible way, which is not efficient or "cool", but it's simple.
So, you want an equivalent of this C block:
if (isalpha(c))
{
/* Do stuff... */
}
Which is like this, considering how isalpha() works:
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
/* Do stuff... */
}
But there are no "block" structures in assembly. Everything is a jump (or a goto in C, which you should never use.) So, to get closer to the assembly version, we might modify our C code to use a jump:
if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
goto AfterStuff;
/* Do stuff... */
AfterStuff:
Note that we are jumping over the "Do stuff" part if the reverse of our condition was true.
Now, assuming we know that 'A' < 'Z' < 'a' < 'z' (the ASCII codes are, respectively: 65, 90, 97, 122,) then we can rewrite the above code like this:
if (c < 65)
goto AfterStuff;
if (c <= 90)
goto DoStuff;
if (c < 97)
goto AfterStuff;
if (c > 122)
goto AfterStuff;
DoStuff:
/* Do stuff... */
AfterStuff:
Note that if c is less than 'A', we jump after the stuff. But if after comparing c and 'A', we find out that c is not only greater or equal to 'A' (because we didn't jump away,) but it's also less than or equal to 'Z', we jump directly to the "stuff" and don't check anything else. Also, the operands of the last blt instruction are reversed.
The assembly gets a little complicated, because we have to load the required immediates into registers and whatnot. Here's the code:
lb $t0, ($s0) # assuming address of c is in s0 register
addi $t1, $zero, 65 # set t1 = 'A'
blt $t0, $t1, AfterStuff # if (c < 'A') goto AfterStuff
addi $t1, $zero, 90 # set t1 = 'Z'
ble $t0, $t1, DoStuff # if (c <= 'Z') goto DoStuff
addi $t1, $zero, 97 # set t1 = 'a'
blt $t0, $t1, AfterStuff # if (c < 'a') goto AfterStuff
addi $t1, $zero, 122 # set t1 = 'z'
blt $t1, $t0, AfterStuff # if ('z' < c) goto AfterStuff
DoStuff:
# Do whatever you want to do
AfterStuff:
I believe the above works, but I absolutely can't be sure. It has been more than a decade since I wrote any MIPS assembly code (or any other code for a MIPS) and I was never very proficient anyways.

C++ to MIPS - Small issue with if statements

C++ Program:
int main()
{
char string[256];
int i=0;
char *result = NULL; // NULL pointer
// Obtain string from user
scanf("%255s", string);
// Search string for letter t.
// Result is pointer to first t (if it exists)
// or NULL pointer if it does not exist
while(string[i] != '\0')
{
if(string[i] == 't')
{
result = &string[i];
break; // exit from while loop early
}
i++;
}
if(result != NULL)
printf("Matching character is %c\n", *result);
else
printf("No match found\n");
}
MIPS code that I have:
.globl main
.text
# main
main:
li $v0,4 # Load value 4
la $a0, msg0 # Load array
syscall
li $v0,8 # Load value 8
la $a0,string # Load array
syscall # Syscall
li $v0,4 # Load immediate value 4
la $a0, string # Load array
syscall # Syscall
la $t0, string # array
la $t1, result # array
lb $t2, result # array
while:
lb $t3, 0($t0)
beq $t3, $0, if2 # if !=0
beq $t3, 't', if # If = "t"
addi $t0, $t0,1 # i++
j while # Jump to While
if:
sw $t3, result # Save result to memory
li $v0,4 # Load value 4
la $a0, found # Load array
syscall # Syscall
j exit
j if2 # Jump to if2
if2:
li $v0,4 # Load value 4
la $a0, notfound # Load array
syscall # Syscall
j exit
exit:
li $v0, 10
syscall # Exit
.data
msg0: .asciiz "Enter Word: "
string: .byte 0:256
i: .word 0
result: .word 0
found: .asciiz "Found!"
notfound: .asciiz "Not Found"
The MIPS code I wrote seems to be working but I think its not following the C++ code structure above. I also think that I have messed up something with if statements but can't figure out what and how to fix it. Any suggestion how I can improve it?
Thanks
I think that the mips code follows the C code quite closely. The main difference is that it practically inlined the the test at the end of the function into the branch to optimize a branch away. While loops have a tendency to look unintuitive in assembly. They are usually compiled to something that looks more like:
if(test) {
do {
body;
} while(test);
}
Like #user2229152 said, you've removed the final check (if(result != NULL)) and moved the prints to your if and if2 blocks.
So your assembly code essentially corresponds to this:
while(string[i] != '\0')
{
if(string[i] != 't')
{
i++;
} else
{
result = &string[i];
printf("Found!");
goto exit;
}
}
printf("Not found");
exit: