Quick question. I'm looking to translate this C code into MIPS assembly language:
f=g-A[B[4]]
I can use any registers to place the variables so I used the following:
$s1=f, $s2=g, $s3=A, $s4=B, $t0=B[4], $t1=A[B[4]]
Here is the code I have tried so far but I am not sure if it is correct or not:
lw $t0, 16($s4)
add $t0, $t0, $s3
lw $t1, 0($t0)
sub $s1, $s2, $t1
Can you guys help me edit this? Thank you in advance.
Looks like you didn't scale the index of A by the size of the A elements. You probably want to multiply $t0 by 4 before adding $s3.
If you have some C code you can compile it to assembly using gcc
gcc-mipsel-linux-gnu -save-temps program.c
cat program.S
this assumes you have a mipsel [cross-]compiler installed, get one from
http://www.emdebian.org/crosstools.html
or
https://wiki.debian.org/BuildingCrossCompilers
Related
I just started to learn the basics of MIPS. While reading a book about MIPS I thought about the next question:
I have the following code:
while (x) {...}
What's between brackets isn't important (just put dots on the right place on the code). It is know that x contains a Boolean statement. Let reg $t0 contain x. I am trying to convert this C while loop into a MIPS code. How to do so?
You can do it with a branch and a label. For example, the statement
while (n>0) { .... }
can be translated to MIPS using a branch and a label:
.data
n: .word 100
.text
main:
la $t0, n
lw $t1, 0($t0)
li $s0, 0
Loop:
bgt $t1, $zero, EXIT
add $t1, $s0, $t1
addi $t1, $t1, -1
j Loop
EXIT:
I've got a project for a class in which we have to transform a picture using sobel operators in assembly, and I'm having a bit of a problem understanding some example code.
In the data segment and in the main function is everything that's need to make the function work (The code works, I just don't understand why).
The bit I don't understand is the use of the li command to change the values of the $aregisters.
read_rgb_image:
# Place file and size in register,
move $s0, $a0 #file name
move $s1, $a1 #buffer
move $s2, $a2 #buffersize
# Open file
move $a0, $s0 # File's directory/name
li $a1, 0 #THIS LI ARE THE COMMANDS I DON'T UNDERSTAND
li $a2, 0 # Read life
li $v0, 13 # Option for opening file
syscall
# Read file
move $a0, $v0 # File descriptor
move $a1, $s1 # Buffer with result
move $a2, $s2 # Space of information to read
li $v0, 14 # Read file
syscall
# Store read buffer
move $s1, $v0
# Close file
li $v0, 16 # Close file
syscall
# Return
move $v0, $s1 # Make return
jr $ra
nop
Can somebody please explain this to me?!
The LI instruction loads an numeric value into a register. Before you make a system call, you need to load the $v0 register with the number assigned to the system service. You also need to load argument registers with system service specific parameters. Without the documentation, we can only guess (beyond the comments in the code) why the specific values being loaded into the registers. However, that is what is going on.
We can guess that you are calling the 4-paremeter version of the open function and that your specifing the file name, mode=0, and flags=0 using the argument registers.
MIPS defines pseudoinstructions that are not actually part
of the instruction set but are commonly used by programmers and compilers.
load immediate li is a pseudoinstruction it loads a 32-bit constant using a combination of lui and ori instructions.
The following instructions are equivalent.
MIPS instruction
lui $s0, 0x1234
ori $s0, 0xAA77
pseudoinstruction
li $s0, 0x1234AA77
I am currently using MIPS Assembly. I have recently learned how to do both macros and arrays (of a sort), so I promptly wrote a fairly simple program to test them out. However, between getting the data and displaying it again, I wish to output a new message. For some reason, my program doesn't appear to do this, even though when running through it step by step it DOES, in fact, go through those lines - it just simply doesn't have any output. Is there any particular reason in MIPS Assembly why this isn't working, or is it a glitch in the MARS assembler?
.data
testlist: .word 50
request: .asciiz "Enter pi up to 50 digits: 3."
out: .asciiz "\nPi: 3."
.text
.macro arraygetword(%initaddress,%offset,%storeto)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetword(%initaddress,%offset,%value)
la $a1,%initaddress
mul $a0,%offset,4
add $a0,$a0,$a1
sw %value,($a0)
.end_macro
.macro arraygetbyte(%initaddress,%offset,%storeto)
la $a1,%initaddress
add $a0,%offset,$a1
lw %storeto,($a0)
.end_macro
.macro arraysetbyte(%initaddress,%offset,%value)
la $a1,%initaddress
add $a0,%offset,$a1
sw %value,($a0)
.end_macro
main:
la $a0,request
li $v0,4
syscall
li $t0,0
li $t1,50
forloop:
li $v0,12
syscall
arraysetword(testlist,$t0,$v0)# testlist[$t0]=$v0
addi $t0,$t0,1
blt $t0,$t1,forloop
li $t0,0
li $t1,50
la $a0,out# This is the part not working.
li $v0,4# Why doth this not output anything?
syscall# I need some sort of line break. It's awkward otherwise.
output:
arraygetword(testlist,$t0,$a0)# $a0=testlist[$t0]
li $v0,11
syscall
addi $t0,$t0,1
blt $t0,$t1,output
li $v0,10
syscall
testlist: .word 50 does not allocate 50 words, it allocates a single word with value 50. As such, your program is overwriting the memory after it, which contains your strings to print. Of course by that time you have already printed the request so that is not affected.
How would I convert this code into Mips?
int n = 100; int sum = 0; while (n>0) {
sum = sum + n;
n--; }
I have this so far and am not sure what to do to finish this.
.data
n: .word 100
.text
main:
la $t0, n
lw $t1, 0(t0)
li $so, 0
Loop:
bgt $t1, $zero, EXIT
add $t1, $s0, $t1
addi $t1, $t1, -1
j Loop
exit:
Change the line:
add $t1, $s0, $t1
To:
add $s0, $s0, $t1
Also, there is no need for use of the data segment. Just set $t1 using:
li $t1, 100
"Mips" isn't a language. MIPS an Instruction Set Architecture (ISA). Are you trying to figure out how to turn the C code into MIPS assembly code?
This looks like a homework assignment from the Patterson and Hennessy textbook. If so, you should go to your professor's office hours to get help. Almost every university includes in its academic handbook a statement that it's unethical to ask for homework help online.
If your request isn't a homework assignment, then the best way to convert that C code into MIPS assembly code is with a compiler. For simple loops, the compiler will generate more effective code than you can generate by hand. For example, "gcc -march=native -O3" will generate code that optimizes for the exact CPU on which you're compiling, taking into account pipeline depth and cache latencies.
If you absolutely need to see the assembly code, use "gcc -S" to produce an assembly file.
Mips doesn't have loops per-say, instead what your going to do is use a jump statement with conditions and loop with that.
I think bgt $t1, $zero, EXIT is the opposite of what you want. It seems like you want to convert while(n > 100), it would help if you make another method to do the codes inside of the while loop, then bgt $t1, $zero, . Correct me if I'm wrong.
Hello and thanks in advance,
My question is if it is possible to go through registers like having a pointer in one ($t0) and moving the pointer to another one ($t1).
What i actually want to do is in one loop read 8 integers and store them in ($s0-$s7)
You could try changing the bits in the sw opcode to point to increasing registers, but that's a terrible idea. I think your best bet is to just write your unrolled loop yourself:
lw $s0, $t0
addi $t0, $t0, 4
lw $s1, $t0
...
Rearrange things to minimize stalls, but that's about as good as you're going to get.
You want to have a register number be variable? I don't know MIPS inside and out, but I doubt it's possible. The only ISAs I know of that have anything like that are SPARC (register windows, not usable for what you want) and IA64 ("rotating registers", could be used for what you want, but only with floating point).
I'm not aware of an existing MIPS architecture that supports referencing a register by the contents of a register, which would allow the type of thing you suggest, like:
move $t0, $zero
mover $t0, $s0 # $s0 = register($t0) = register(0)
addi $t0, 1
mover $t0, $s1 # $s1 = register($t0) = register(1)
addi $t0, 1
...
Although in any case it's not a good idea in my opinion, for a few reasons. Firstly, you're dealing with a very small number of registers anyway, so there is a small upper bound on the loop in any case, making the direct approach not much less flexible.
More importantly, a loop like that would be horribly inefficient. It would initialise, increment, perform a move and a branch check (at least) for every iteration. Even without taking branch stalls into account this is at least 3x slower than simply:
move $t0, $s0
move $t1, $s1
...
move $t8, $s8