I need to implement an instruction in MIPS assembly that jumps to a location stored in a register if its value is non-negative; otherwise, it jumps to a location stored in a second register.
I'm having an issue with how to check for negative values in registers and also need help understanding how to implement this.
Suppose you have in $t1 the test register (the one pointing to the address to jump if its contents is non-negative), and in $t2 the register which will hold the address of the jump if $t1 is negative.
Then, this snippet should do the trick:
bge $t1, $zero, is_positive
jr $t2
is_positive:
jr $t1
The first instruction branches to is_positive if $t0 is non-negative. The instruction at that label jumps to the address given by $t1. If the branch is not taken (i.e. $t0 is negative), then the following instruction is executed which will jump to the address given by $t2.
Related
I just started studying computer organization.
My question is similar to this article
How are the address of the memory and that of the register connected?(AddrConstant MIPS instruction)
lw $t0, AddrConstant4($s1)
The meaning of this instruction is $t0=constant 4
How I understand this instruction is adding 4 to the value of register $s1 and, load (4+value of register $s1) into $t0.
My question is that I don't know what value does $s1 already have.
If $s1 has 0, it makes sense.
However, if $s1 has 5, $t0 will have 4+5=9.
who knows what value is in $s1.
or what I understood is wrong?
As soon as I wrote this question, another idea came to me.
AddrConstant4($s1) means put 4 into the value of register $s1. (It doesn't matter what value $s1 had before.)
So lw $t0, AddrConstant4($s1) is same as $t0==4.
This is right?
Its a pseudo instruction, that may expand to two or more instructions.
lw $t0, label($t1)
Expands to something like:
la $at, label
addu $at, $at, $t1
lw $t0, 0($at)
Where la itself is a pseudo instruction involving lui and perhaps ori.
There are some optimizations possible, but for the best code, much better to use la to load the label address into a register for a longer duration, e.g. that can be done outside a loop. (OR change algorithm to use pointers.)
I just have this conceptual question but I can't really find sites that give clear explanation.
But for the temporary register, saved registers and floating point registers, do they contain address of the values we desire or just the values, say 100 or 200?
The answer is both. The register can contain an address when used with a lw instruction like this:
lw $t1, 0($t2) # loads the value at address 0+$t2 into $t1
Other instructions involve registers which contain values:
add $t1, $t2, $t3 # loads value of $t2 + value of $t3 into $t1
For example:
$t0 = A
$t1 = B
$t2 = C
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
As long as your temporary registers are next to each other in memory.
i.e.
Reference: $t1 $t2
Mem Blocks: [byte][byte][byte][byte][byte][byte][byte][byte]...
Programs like Logisim should have the registers packed tightly.
Helpful page here from UC Berkeley.
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
No, it would not. The lw instruction is used to load data from memory, not to copy the value of one register into another register. To quote from the MIPS manual:
LW rt, offset(base) MIPS32 (MIPS I)
Purpose:
To load a word from memory as a signed value
Description: rt ← memory[base+offset]
The contents of the 32-bit word at the memory location specified by the aligned effective address are fetched,
sign-extended to the GPR register length if necessary, and placed in GPR rt. The 16-bit signed offset is added to the
contents of GPR base to form the effective address.
In other words, what lw $t1, 4($t0) does is form an effective address by adding the value of $t0 with the value 4, and load a word (four bytes) from that address into register $t1.
How does 'alignment of memory operands' help MIPS to be pipelined?
The book says:
Fourth, as discussed in Chapter 2, operands must be aligned in memory. Hence,
we need not worry about a single data transfer instruction requiring two data
memory accesses; the requested data can be transferred between processor and
memory in a single pipeline stage.
I think I understand that one data transfer instruction does not require two or more data memory aaccesses.
However, I am not sure what does it have to do with the alignment of memory operands.
Thanks, in advance!
The lw instruction requires that the memory address be word aligned.
Therefore, to access an unaligned word, one would need to access the two word boundaries that the required word intersects and mask out the necessary bytes.
For example, suppose you desire to load a word stored at address 0x2. 0x2 is not word aligned, so you would need to load the half word stored at 0x2 and the half-word stored at 0x4.
To do so, one might write:
lh $t0 2($zero)
lh $t1 4($zero)
sll $t1 $t1 16
or $t2 $t0 $t1
This only gets more complicated if you want to load for example a word stored at address 0x3:
# load first byte
lb $t0 3($zero)
# load second word, mask out first 3 bytes
lw $t1 4($zero)
lui $t2 0x0000FFFF
ori $t2 $t2 0xFFFFFFFF
or $t1 $t1 $t2
# combine
sll $t1 $t1 8
or $t2 $t0 $t1
So, it can be seen that the requirement for word alignment doesn't help MIPS to be pipelined, but rather that access to unaligned words requires excess memory accesses — this is a limitation of the ISA.
How to write the following into MIPS instructions?
$t0=$t1
if ($t6<$t7) go to Label.
$t0 is not reserved for zero. $t0 is a temporary register that can store any value. The register $zero is reserved/hard-wired to zero. We would want to "branch" to "Label" if $t6 is "less than" $t7, so use the branch on less than instruction blt. The code would look like:
add $t0,$zero,$t1
blt $t6,$t7,Label
your following rubbish:
$t0=$t1
if ($t6 less than $t7) go to Label
would be converted to MIPS like:
move $t0,$t1 # or use instruction instead (add $t0,$zero,$t1)|(addi $t0,$t1,0)
slt $t2,$t6,$t7 # if $t6less than $t7 set $t2=1
bgtz $t2,foo # if $t2=0 goto foo, and foo is the label that you want to move to
Assuming that the registers are already loaded with the right data.
So for $t2 = $t3, adding $t3 to register zero and storing it in $t2 will work so this is how it would look like :
add $t2,$t3,$t0 - assuming $t0 is reserved for zero like most versions of mips.
for if $t4, we need a branch statement, not sure what you want to compare it to, but look at this guide - should give enough instructions about how to write it.