You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

逆向分析x86汇编mystery函数:解析LEA指令及对应C实现

拆解x86汇编,还原mystery函数的C实现

咱们一步步来分析这段汇编代码,先解决你疑惑的LEA指令,再还原出完整的C逻辑:

先整理清晰的汇编代码格式

首先把你给出的汇编代码拆分成函数块,看起来更清楚:

mystery:
    mov %edi, %eax          ; 把输入参数n(存在%edi)复制到%eax
    lea 0x0(,%rdi, 8), %edi ; 重点:用LEA计算8*n,存入%edi
    sub %eax, %edi          ; %edi = 8n - n = 7n
    add $0x4, %edi          ; %edi = 7n + 4
    callq <mystery_util>    ; 调用mystery_util(7n+4)
    repz retq               ; 返回调用结果(repz是冗余指令,不影响功能)

mystery_util:
    mov %edi, %eax          ; 把参数m复制到%eax
    shr %eax                ; %eax = m >> 1(逻辑右移,相当于整数除以2)
    and $0x1, %edi          ; %edi = m & 1(取m的最低位,判断奇偶)
    and %edi, %eax          ; %eax = (m>>1) & (m&1)
    retq                    ; 返回%eax的值

解释LEA指令的作用

你问的lea 0x0(,%rdi, 8), %edi是x86里非常实用的有效地址加载指令,它的本质是做算术计算,语法是lea 位移基址,变址,比例), 目标寄存器,计算规则是:基址 + 变址*比例 + 位移。

这里的基址是0,变址是%rdi(也就是输入参数n),比例是8,位移是0,所以计算结果就是0 + n*8 + 0 = 8n,然后把这个值存到%edi里。

LEA经常被用来做快速乘法,因为它比mul/imul指令效率更高,而且不会影响CPU的标志位——这里就是用它来快速计算8*n,而不是用乘法指令。

逐行还原成C逻辑

先看mystery函数的逻辑

x86-64的System V调用约定里,第一个整数参数存在%edi寄存器,所以mystery的输入参数是int n,咱们把每条指令转换成C步骤:

  1. mov %edi, %eax → 保存原始参数n到临时变量:int temp = n;
  2. lea 0x0(,%rdi,8), %edi → 计算8*n,覆盖原参数的存储位置:n = 8 * n;
  3. sub %eax, %edi → 用8n减去原始n,得到7n:n = 8*n - temp;
  4. add $0x4, %edi → 加上4,得到7n+4:n = 7*n + 4;
  5. 调用mystery_util(7n+4),并返回这个调用的结果。

再看mystery_util函数的逻辑

它的输入参数是int m(也就是上面的7n+4),指令对应的C逻辑:

  1. mov %edi, %eax → 复制参数m到结果寄存器:int res = m;
  2. shr %eax → 逻辑右移一位,等价于整数除以2:res = res >> 1;
  3. and $0x1, %edi → 取m的最低位,判断m是否为奇数:m = m & 1;(结果为1则是奇数,0则是偶数)
  4. and %edi, %eax → 只有当m是奇数时,保留res的值;偶数时结果为0:res = res & m;
  5. 返回res。

把mystery_util简化成C代码的话,就是:

int mystery_util(int m) {
    return (m >> 1) & (m & 1);
}

或者用更易懂的条件判断写法:

int mystery_util(int m) {
    if (m % 2 == 1) { // 如果m是奇数
        return (m - 1) / 2;
    } else { // 如果m是偶数
        return 0;
    }
}

合并成完整的mystery函数

把上面的逻辑整合起来,mystery的完整C实现就是:

int mystery_util(int m) {
    return (m >> 1) & (m & 1);
}

int mystery(int n) {
    int m = 7 * n + 4;
    return mystery_util(m);
}

总结函数功能

简单来说,这个函数的作用是:
接收一个整数n,计算7*n +4的值:

  • 如果这个值是偶数,返回0;
  • 如果这个值是奇数,返回(7n+3)/2(因为7n+4是奇数的话,减1再除以2就是(7n+3)/2)。

你可以拿几个测试用例验证:

  • n=1时,7*1+4=11(奇数),返回(11-1)/2=5,符合汇编计算结果;
  • n=2时,7*2+4=18(偶数),返回0;
  • n=-1时,7*(-1)+4=-3(奇数),汇编里shr逻辑右移后,-3>>1是-2,-3&1是1,-2&1=0,所以返回0。

内容的提问来源于stack exchange,提问作者user9473612

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:35:10