MIPS How to branch to a 32-bit address? - mips

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:

Related

Write into next byte of a register

I understand that registers in memory are 32 bits. I also understand that lb will load contents from memory into the lower 8 bits of a register, and that if I did
lb $t1, $a3
lb $t1, 4($a3)
The second lb command will overwrite the contents loaded in the first. However, is there a way to write into the second byte of a register (loading from a different part in memory, so not two bytes right next to each other) and preserve the information of the first byte?
I am assuming what you want to use here is lbu (load byte unsigned) and not lb because you don't want the register to be sign extended (e.g. copying the byte AA in the register will result in 000000AA, and not FFFFFFAA).
If you want to write to the second byte of a register you can first use lbu to load the byte from memory to another register, then shift left 8 bits, and addu it to the original register.
For example:
lbu $t1, $a3 # 0x000000AA
lbu $t2, 4($a3) # 0x000000BB
sll $t2, $t2, 8 # 0x000000BB -> 0x0000BB00
addu $t1, $t1, $t2 # 0x000000AA + 0x0000BB00 = 0x0000BBAA

Replacing left logical shifts with other instructions in MIPS

So let's say that we have two registers $s0 and $s1. Register $s0 can take values from 0 to 31 and is used to show how many bits register $s1 will be shifted left. How can i do this without using sll or srl. I know that left logical shift by n bits is the same as multiplying with 2^n. This exercise gives a hint that this can be done with 4 instructions only. Both registers are 32-bit.
You can add $s1 to itself $s0 times (each time it will multiply its value by 2 which shifts its bits left once).
The code would look like this:
beqz $s0, end
loop:
add $s1, $s1, $s1
subu $s0, $s0, 1
bnez $s0, loop
end:
The first conditional branch is to ensure no action is taken to $s1 when $s0 holds value zero.

What happens when I give an offset to a "temporary register" in MIPS

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.

Expand variable number of arguments in memory to argument space

I have a function that takes a memory address as $a0 and I access the (variable) number of words by using x($a0), where x is multiples of 8. I need to store these in the $sp register so I can use the $a0 register for passing arguments to other functions. Completely new to MIPS assembly, so any pointers here would help!
Multiples of 8 i assume you are using mips-64
first u make a loop and increment a0 by 8 each time:
loop: lw $t0, 0($a0) ;fetch data and store in t0
addi $sp,$sp,-8 ;increase stack
sw $t0, 0($sp) ;store data fetched
addi $a0,$a0,8 ;increment a0 to go to next entry
;here you check that you haven't reached x yet
;let's say 8*x+$a0(initial) is stored in $t1 (this is easy to do just use sll by 3 to multiply by 8 then add a0 before loop)
bne $a0,$t1,loop
;now you can use $a0

MIPS - loading individual bits

Fellow SO users,
If I have a value, say 1010 saved in memory, how do I load each of the bits starting from the MSB to the LSB one at a time? By this I mean,
while loop
load $t1 with 1
shift some number by the amount indicated by the value in $t1 (1)
load $t1 with 0
shift some number by the amount indicated by the value in $t1 (0)
do the same until you load the LSB which is 0
start again at MSB (rotate right?)
end loop
I need some tips on how to declare this value in memory in the .data segment first. Do I declare this as:
value: .byte 00001010
And how do I load the individual bits into registers?
Kind regards
You can do this with the SLT instruction described here. Here is some pseudocode:
lbu $s0, value # load the byte
sll $s0, $s0, 24 # shift it into the upper byte of $s0
for (i = 0; i < 8; i++) {
# $t0 is set to 1 if the sign bit (i.e. bit 31) of $s0 is set
slt $t0, $s0, $zero
# $t0 now holds the value of the ith bit of value
. . . . # do something with $t0
sll $s0, $s0, 1 # shift on to the next bit
}
Implementing the for loop in assembler is left as an exercise for the reader.