I found this exam question that I have to tell how the beq instruction is coded in machine code.
This is the code:
loop: addu $8, $9, $10
addiu $8, $8, 0x00FF7A01
beq $8, $0, loop
Although my first question would be 0x1100FFFD the correct answer is 0x1100FFFB.
I believe that this is because 0x00FF7A01 is bigger than 16 bit and addiu $8, $8, 0x00FF7A01 must be "decompiled" in more than one instruction.
So here are my questions.
Q1 - In what is addiu $8, $8, 0x00FF7A01 decomplided?
Q2 - And what if the immediate field on the beq instruction was bigger than 16 bits? Must I have to use jumps?
Q1)
For your first question, you mean assemble, not decompiled.
addiu $8, $8, 0x00FF7A01
Your assessment was correct, since the immediate value was bigger than what we can store in a single instruction, we would need to use multiple instructions. The assembler will use the $at (Assembler Temporary, which is $1) register for that.
lui $at, 0x00FF
ori $at, $at, 0x7A01
addu $t0, $t0, $at
Q2)
The branch instructions use what is called PC-relative addressing - the immediate value does not contain the actual address by rather the word offset. Since we know the instruction must be word (2^2) aligned, the low 2 bits are always zero. The actual address will be calculated on the fly by shifting the offset left by 2 and adding it to the address of the instruction following the branch. The final value will be our PC-relative effective address. So we actually have 17 bits to play with (technically 18, but the offset is signed).
When the offset exceeds that range, the assembler will use far branches - a branch followed by a jump.
beq $x, $y, label
will become
beq $x, $y, temp
# ...
j tskip
temp:
j tlabel
# ...
# ...
tskip:
Not sure how the assembler works here, but to allow addiu $8, $8, 0x00FF7A01 be assembled correctly, multiple instructions are necessary, as you have expected. Normally, addiu is a valid instruction that takes in 16-bit integer only.
The instruction addiu $8, $8, 0x00FF7A01 is minimally rewritten as these 3 instructions:
addiu $8, $8, 0x7A01
lui $11, 0x00FF // Assume nothing significant is stored in $11
addiu $8, $8, $11
Since there is now difference of 5 instructions from branch instruction, we need to put -5 in the immediate field of beq, which is 0xFFFB (detailed explanation here).
If the destination is outside the range of -217 to 217-1 bytes (or to the power of 15 in term of number of instructions), then jump instruction must be used.
Related
I need to make a mips program that when given an integer, will print all possible numbers with that number of bits. What is the best was to do this?
This might help get you started. It's a way to count the number of 1s in a binary number.
popcnt:
;input: $a0 = the 32-bit number you wish to check
;output: $v0 = the number of bits that equal 1.
move $v0,$zero
li $t0,32
loop_popcnt:
move $a1,$a0
andi $a1,$a1,1
beqz $a1,skip # if zero, the bit we tested was zero, so don't add 1 to the answer.
nop # branch delay slot. We don't want the next instruction to execute if we branch
addiu $v0,$v0,1
skip:
ror $a0,$a0,1 # next bit
addiu $t0,$t0,-1
bnez $t0,loop_popcnt
nop #branch delay slot.
jr $ra
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'm trying to crash problems in the book 'Computer organization and Design'.
I come across a sequence of instructions in solution of book.
But Qtspim, mips assembler, can't interpret them.
Here is instructions. (book 4th edition, problem 2.14.4 a)
add $t2, $t0, $0
srl $t2, $t2, 11
and $t2, $t2, 0x0000003f
and $t1, $t1, 0xffffffc0
ori $t1, $t1, $t2
Why ori has 3 registers? (I thought it is not r-type instruction)
Why and has 32bit immediate? (I thought instruction itself has 32bit wise.)
Thank you in advance.
The first two instructions look ok, but the following three do not. It's possible that those are typos, or that the author of the book was using a different MIPS assembler which accepts those instructions and converts them into valid ones.
For example:
and $t2,$t2,0x0000003f
=>
lui $t2,0 ; ANDing the upper halfword with 0x0000 would set it to 0
andi $t2,$t2,0x003f
and $t1,$t1,0xffffffc0
=>
andi $t1,$t1,0xffc0 ; ANDing the upper halfword with 0xffff would not change it
ori $t1,$t1,$t2
=>
or $t1,$t1,$t2
I am trying to branch to an address:
bne $t0, $0, 0x7813a21c
However, this is incorrect because bne only allocates 16-bits to the immediate
How can I branch to a direct 32-bit address? Is there a way to branch from a value in a register?
You have to use JR to jump to an address stored in a register.
To preform this type of operation you will need a jump statement. You have to tell the code to jump control context to the exact line you wish to specify. This is example syntax: j offset Where in your address is the offset.
Here is a link that better reviews what you have to do. Check out the section on jump. These are the types of jump available. One of them is what you need: j offset, jal offset, jr $rs, jalr $rs
Here is the link:
http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/jump.html
Good luck
We can load 32-bit addresss to the register (e.g. $t1) in 2 steps:
Load the upper 16 bits by lui (Load Upper Immediate).
Load the lower 16 bits by ori (Or Immediate).
NOTE: It is work because lui fills the lower 16 bits with 0s, so bitwise OR load the lower 16 bits (n | 0 = n);
In code below if $t0 is equal to 0 we do skip jr instruction.
Or if $t0 is not equal to 0 we do not skip jr instruction (or we do jump).
beq $t0, $0, SKIP
# load 0x7813a21c to $t0
lui $t1, 0x7813 # load the upper 16 bits
# Now $t1 = 0x78130000
ori $t1, $1, 0xa21c # load the lower 16 bits
# Now $t1 = 0x7813A21C
jr $t1 # as #Matt Eckert said
SKIP:
I am a bit stuck up with the following question,
Consider the following MIPS code and answer the questions that follow.
addi $t1, $s0, 400
loop: lw $s1, 0($s0)
add $s2, $s2, $s1
lw $s1, 4($s0)
add $s2, $s2, $s1
addi $s0, $s0, 8
bne $t1, $s0, loop
What value is the label loop translated to in the conditional branch
instruction?
Now I know the mathematical formula for Branch Target Address. But here as memory addressing is not done so I found out the offset by counting the lines between the target address and PC. This gives the answer to be 7 (word offset). Am I right with this approach?
A quick experiment with MARS simulator http://courses.missouristate.edu/KenVollmar/MARS/download.htm gave me the answer-6, -5 for number of lines difference and another -1 because PC is increased by 1 after the instruction.
AFAIK, I'm afraid not.
As MIPS instruction reference says:
An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
is added to the address of the instruction following the branch (not
the branch itself), in the branch delay slot, to form a PC-relative
effective target address.
So as I understand, the distance from the branch instruction to the loop label is negative (because the label is before the branch, thus the address is lower). The distance is calculated in number of words (hence the 2 bits left shift). As all MIPS instructions are 4 bytes, this would be 6 instructions before, hence -6 is the value that should appear in the branch instruction offset (lower half-word). In binary: 1111 1111 1111 1010 (two's complement). In hexadecimal: FFFA.
Checked with simulator and seems that my reasoning is correct since the instruction is coded as 0x1530FFFA.