关于li指令的问题

逆向工程 艾达 米普 编码
2021-07-06 20:36:48

使用 IDA Pro 反转 MIPS 二进制文件时,我有两个问题。源代码如下。

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

艾达亲

.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    
.text:00080530

(1) 我知道偏移量 0x0008051c 处li指令实际上lw其编码格式为1000 11ss ssst tttt iiii iiii iiii iiii。所以我知道 sssss = (111100)2 = 28 = $gp, ttttt = (00100)2 = 4 = $a0。但我不知道如何计算 0x80000。

(2)在偏移0x00080510 instrution需要8个字节,但另一个在偏移0x0008051C指令需要4个字节?第一个li指令是伪指令吗?

1个回答

MIPS 指令的大小为 4 字节(32 位)。因此,不可能使用单个指令加载 32 位常量。

li $gp, 0x18B00指令确实是伪指令。它由两条指令组成。

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

在线反汇编器的截图

在此处输入图片说明

lui(负载上即时)指令加载一个16位常数到寄存器(的高16位$gp在这里)。

addiu指令将一个 16 位整数添加到寄存器中。in 的最终值$gp可以计算为:

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

IDA pro 和其他反汇编程序会自动执行此计算,并使用单个伪指令显示最终结果。

另一li $a0, 0x80000条指令0008051C实际上是lw(加载字)指令。lw指令将一个字从内存加载到寄存器中。0x80000因此,该值位于内存中,[$gp - 32740]而不是指令本身的一部分。

然而,IDA 简化并将其显示为li $a0, 0x80000最终结果是将值0x80000复制到寄存器。