When reversing a MIPS binary using IDA Pro, I have 2 questions. The source code is as follows.

int main(int argc, char* argv[])
    int m = 1;
    int n = 5;
    printf("sum = %d\n", m+n);

ida pro

.text:00080510  # int __cdecl main(int argc, const char **argv, const char **envp)

.text:00080510  .globl main    
.text:00080510  main:    
.text:00080510      # __unwind {    
.text:00080510 02 00 1C 3C 00 8B 9C 27  li      $gp, 0x18B00    
.text:00080518 21 E0 99 03              addu    $gp, $t9    
.text:0008051C 1C 80 84 8F              li      $a0, 0x80000    
.text:00080520 44 80 99 8F              la      $t9, printf    
.text:00080524 A4 08 84 24              addiu   $a0, (aSumD - 0x80000)  # "sum = %d\n"    
.text:00080528 08 00 20 03              jr      $t9 ; printf    
.text:0008052C 06 00 05 24              li      $a1, 6    
.text:0008052C                  # } // starts at 80510    

(1) I know the li instruction at offset 0x0008051c is lw actually. And its encoding format is 1000 11ss ssst tttt iiii iiii iiii iiii. So I konw sssss = (111100)2 = 28 = $gp, ttttt = (00100)2 = 4 = $a0. But I don't know how to calculate 0x80000.

(2) The li instrution at offset 0x00080510 takes 8 bytes, but another li instruction at offset 0x0008051C takes 4 bytes? Is the first li instruction a pseudoinstruction?


MIPS instructions are 4 bytes (32 bit) in size. Hence it's not possible to load a 32 bit constant using a single instruction.

The li $gp, 0x18B00 instruction is indeed a pseudo instruction. It's composed of two instructions.

lui     gp, 0x2
addiu   gp,gp,-29952

Screenshot from Online Disassembler

enter image description here

The lui (Load Upper Immediate) instruction loads a 16-bit constant into the upper 16 bits of a register ($gp here).

The addiu instruction adds a 16 bit integer to a register. The final value in $gp can be calculated as:

$gp = (2 << 16) + (-29952) = 0x18B00

IDA pro and other disassemblers does this calculation automatically and displays the final result using a single pseudo instruction.

The other li $a0, 0x80000 instruction at 0008051C is actually a lw (Load Word) instruction. The lw instruction loads a word from memory into a register. The value 0x80000 is thus located in memory at [$gp - 32740] and not a part of the instruction itself.

IDA however simplifies and shows it as li $a0, 0x80000 as the net result is the value 0x80000 is copied to the register.

  • Thank you very much! in question (1), how to calculate the 0x80000? – user6903 Mar 25 '20 at 10:31
  • @user6903 Check update – 0xec Mar 25 '20 at 10:50
  • Now is static analysis, how does IDA calculate the value of the $gp register, that is, how to calculate $gp - 32740 ? – user6903 Mar 25 '20 at 11:14
  • 1
    The very first instruction sets the value of the $gp register li $gp, 0x18B00 – 0xec Mar 25 '20 at 11:40
  • 1
    There's a way to turn off IDA simplifying gp references. Check this – 0xec Mar 25 '20 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.