assemblypowerpcxbox360

(PowerPC) Do not understand why the code stores contents of registers in the same address


I recently started reversing the game for the Xbox 360, and I really don’t understand why the contents of %r11 and %r10 are stored in the addresses [%r8] and [%r9] that have the same address (0x00010000).

This code generated by IDA.

.globl _start
_start:

.set var_1F0, -0x1F0

.long_zero: .long 0
.long_zero_1: .long 0

mflr    %r12            # Move from link register
bl      sub_831A8168    # Branch
addi    %r31, %sp, var_1F0 # Add Immediate
stwu    %sp, -0x1F0(%sp) # Store Word with Update
nop                     # No Operation
# -------------------------------------------------------------|
mr      %r8, %r8        # Move Register
mr      %r8, %r8        # Move Register
lis     %r9, ((long_zero+0x10000)@h) # Load Immediate Shifted
lis     %r8, ((long_zero_1+0x10000)@h) # Load Immediate Shifted
li      %r11, -1        # Load Immediate
li      %r10, -1        # Load Immediate
stw     %r11, long_zero@l(%r9) # Store Word
stw     %r10, long_zero_1@l(%r8) # Store Word
# -------------------------------------------------------------|

Solution

  • As far as I undestand you correctly, your problem are the following two lines:

    lis     %r9, ((long_zero+0x10000)@h)
    ...
    stw     %r11, long_zero@l(%r9)
    

    Let's assume that the word long_zero is located at the address 0x1234ABCD:

    (xxx)@h means: The high 16 bits of (xxx).

    0x1234ABCD + 0x10000 is 0x1235ABCD and the high 16 bits of this number are 0x1235.

    Therefore, the instruction lis %r9, ((long_zero+0x10000)@h) is equal to lis %r9, 0x1235 and will load the value 0x12350000 into register r9.

    xxx@l means: The low 16 bits of xxx.

    For this reason stw %r11, long_zero@l(%r9) is equal to stw %r11, 0xABCD(%r9).

    This instruction will sign-extend 0xABCD (to 0xFFFFABCD) and add the sign-extended value to the value in register r9; the result is the address being written: 0x12350000 + 0xFFFFABCD = 0x1234ABCD.

    By the way: I assume that the first instruction was not lis %r9, ((long_zero+0x10000)@h) but lis %r9, long_zero@ha before being assembled.

    @ha assumes that the low 16 bits will be sign-extended and the result will be added to the register in a later (here: stw) instruction.

    This means that xxx@ha is equal to xxx@h if bit 15 of xxx is 0 (so the low 16 bits represent a positive number) and it is equal to (xxx+0x10000)@h if bit 15 is 1 (so the low 16 bits represent a negative number).