1

I am reading Chapter 2.12 of Computer Organization and Design, trying to understand the logic of a MIPS-32 linker. I understand the concept of linking two object files and absolute reference linking. What I don't understand is the quoted paragraph below explaining the logic for calculating absolute addresses.

The load and store addresses are harder because they are relative to a base register. This example uses the global pointer as the base register. Figure 2.13 shows that $gp is initialized to 1000 8000hex. To get the address 1000 0000hex (the address of word X), we place 8000hex in the address field of lw at address 40 0000hex. Similarly, we place 8020hex in the address field of sw at address 40 0100hex to get the address 1000 0020hex (the address of word Y).
Page 128

According to the MIPS-32 instruction set for instructions lw and sw, the immediate offset operand is added to the register operand.

But
1000 8000hex + 8000hex = 1001 0000hex != 1000 0000hex
1000 8000hex + 8020hex = 1001 0020hex != 1000 0020hex

So maybe I am misunderstanding something and the offsets are being subtracted? Even if that was the case:

1000 8000hex - 8000hex = 1000 0000hex == 1000 0000hex
1000 8000hex - 8020hex = FFFF FE0hex != 1000 0020hex

What is happening here?

Figure 2.13:

MIPS-32 Memory Allocation

Jordan
  • 902
  • 2
  • 10
  • 37

1 Answers1

2

The 16-bit offsets found in the instruction words are sign-extended to 32 bits before being added to the base address.

So if the offset found in the instruction word is 0x8000, you get 0x10008000 + 0xFFFF8000 == 0x10000000 (when the result is truncated to 32 bits). And similarly for the second example.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • So it takes advantage of an overflow? Is that a common way of subtracting two numbers? – Jordan Sep 11 '19 at 19:48
  • You can view 0xFFFF8000 as -32768 if you want to. They're just different ways of describing the same bit pattern. – Michael Sep 11 '19 at 20:14
  • As for whether it's common; that depends on whether there's a dedicated subtraction operation available. In this case (for MIPS address calculations) there isn't, so you achieve the same thing by adding a negative value instead. – Michael Sep 11 '19 at 20:18
  • Okay, I understand the math now. So why is the `$gp` register not just set to 0x1000 0000? Would you not be able to access the same range of addresses without having to sign-extend? – Jordan Sep 11 '19 at 20:25
  • 1
    My guess would be that the data section of this imaginary system starts at 0x10000000. So by setting `$gp = 0x10008000` you can easily address anything within the first 64kB of the data section. – Michael Sep 11 '19 at 20:29
  • What do you mean by "easily address"? Why set `$gp` to the middle of the 64kB region and access +-32kB instead of setting it to the beginning of the region and indexing forward into the 64kB as well as not having to sign-extend? Wouldn't that be "easier"? – Jordan Sep 11 '19 at 22:07
  • 1
    But offsets _are_ sign-extended. So if you wanted to be able to do `$gp`-relative addressing of 0x10000000..0x1000FFFF, that's how you would do it. – Michael Sep 12 '19 at 05:23