you take the address register used in the instruction, add the immediate offset (this 16 bit offset you are talking about) and that sum is the address used for the load or store. The value in the register and the offset can be pretty much anything so long as the sum is aligned to the size of the load or store.
Commented Apr 16, 2013 at 13:42But basically it's guaranteed that offsets from different registers won't collide, right? I'm not sure if the loaded value from the register is the value held in that memory address or is the address itself.
Commented Apr 16, 2013 at 14:37the address comes from the sum of the value in the register plus the offset. That address is in memory space, ram and peripherals, the (general purpose) registers cannot be reached through an address in memory space. A few bits in the instruction are used to choose which register contains one part of the address.
Commented Apr 16, 2013 at 17:48Does that mean that all registers' addresses are spaced 8192 words apart from each other?
No. Registers don't have addresses.
Also, does it mean that the whole available memory for operating is 32 * 8192 = 262144 words?
No. These immediates are offsets to the base address used for the load/store. It allows you do specify addresses within -32768..+32767 bytes from the base address. 32768/sizeof(word) == 8192. You can simply change the value of the base register if you want to move beyond that range.
The amount of registers has nothing to do with the amount of memory you can address.
li $a0,0 # set $a0 to 0 lw $t0,0($a0) # load a word from address 0 lw $t0,8($a0) # load a word from address 8 lui $a0,0xffff # set the upper half-word of $a0 to 0xffff lw $t0,4($a0) # load a word from address 0xffff0004