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:
Related
How do I use multiple if-else statements or the switch operator from C/C++ in Assembly?
Something like this in C:
if ( number == 2 )
printf("TWO");
else if ( number == 3 )
printf("THREE");
else if ( number == 4 )
printf("FOUR");
Or using switch:
switch (i)
{
case 2:
printf("TWO"); break;
case 3:
printf("THREE"); break;
case 4:
printf("FOUR"); break;
}
Thanks.
Architecture is critical for specifics but here's some psuedo code which does what you want.
... # your code
jmp SWITCH
OPTION1:
... # do option 1
jmp DONE
OPTION2:
... # do option 2
jmp DONE
Option3:
... # do option 3
jmp DONE
SWITCH:
if opt1:
jmp OPTION1
if opt2:
jmp OPTION2
if opt3:
jmp OPTION3
DONE:
... #continue your program
A detailed answer will depend upon the particular machine instruction set for which you are writing the assembly language. Basically you write assembly code to perform the C language series of tests (if statements) and branches.
In pseudo-assembly it might look like this:
load r1, number // load the value of number into register 1
cmpi r1, 2 // compare register 1 to the immediate value 2
bne test_for_3 // branch to label "test_for_3" if the compare results is not equal
call printf // I am ignoring the parameter passing here
... // but this is where the code goes to handle
... // the case where number == 2
branch the_end // branch to the label "the_end"
test_for_3: // labels the instruction location (program counter)
// such that branch instructions can reference it
cmpi r1, 3 // compare register 1 to immediate value 3
bne test_for_4 // branch if not equal to label "test_for_4"
... // perform printf "THREE"
branch the_end // branch to the label "the_end"
test_for_4: // labels the instruction location for above branch
cmpi r1, 4 // compare register 1 to immediate value 4
bne the_end // branch if not equal to label "the_end"
... // perform printf "FOUR"
the_end: // labels the instruction location following your 3 test for the value of number
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.
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
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.
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.