%hi() operator on MIPS
Richard Sandiford
rsandifo@redhat.com
Sat Aug 21 15:56:00 GMT 2004
Shinpei Kato <shinpei@rt.k2.keio.ac.jp> writes:
> If we assemble the following codes with -d option, we want to expect the following output. But the actual output is like below.
>
> [code]
> lui $8, %hi(0x87f0c000)
> ori $8, $8, %lo(0x87f0c000)
>
> [expected output]
> lui t0, 0x87f0
> ori t0, 0xc000
>
> [actual output]
> lui t0, 0x87f1
> ori t0, 0xc000
>
> Why 0x87f0 is changed to 0x87f1?
Because %lo() is a _signed_ 16-bit number, not an unsigned number,
and because (for a 32-bit X) %hi(X) = X - %lo(X). You want to use
addiu instead of ori:
lui $8, %hi(0x87f0c000)
addiu $8, $8, %lo(0x87f0c000)
The idea behind %lo() being signed is that you can use it as an offset
in memory accesses. E.g.:
lui $8, %hi(0x87f0c000)
lw $8, %lo(0x87f0c000)($8)
> If we use la instead of lui/ori/%hi/%lo, it's expanded as follows and works.
>
> [code]
> la $8, 0x87f0c000
>
> [output]
> lui t0, 0x87f0
> ori t0, t0, 0xc000
That's because gas isn't using %hi/%lo internally in this case.
Richard
More information about the Binutils
mailing list