逆向工程数学函数

问题描述 投票:1回答:2

我正在将一些汇编代码转换为C代码,但是在以下代码上遇到了麻烦:

mov    $0x51eb851f,%edx
mov    %ecx,%eax
imul   %edx
sar    $0x5,%edx
mov    %edx,%edi
mov    %ecx,%eax
sar    $0x1f,%eax
sub    %eax,%edi
imul   $0x64,%edi,%eax
sub    %eax,%ecx

%ecx存储我们的参数,它是一个int类型(我们可以称其为x)。我知道前三个步骤实际上是在执行x / 100。但是我在以下步骤中感到困惑。

一些帮助,将不胜感激。

assembly x86 reverse-engineering
2个回答
2
投票

x86的gcc 9.3.1 gcc -O3 -S -m32转换以下C代码:

int foo(int x)
{
  return x%100;
}

进入以下程序集:

foo:
    movl    4(%esp), %ecx
    movl    $1374389535, %edx
    movl    %ecx, %eax
    imull   %edx
    movl    %edx, %eax
    movl    %ecx, %edx
    sarl    $5, %eax
    sarl    $31, %edx
    subl    %edx, %eax
    imull   $100, %eax, %eax
    subl    %eax, %ecx
    movl    %ecx, %eax
    ret

实际上是相同的,除了一些小的重新排序和对整个功能符合x86 ABI的要求。


0
投票

是的,前三个步骤在做[[x / 100 –或多或少地乘以1/100-but除法直到sub %eax, %edi之后才完成。] >所以,要回答关于前三个步骤的问题,下面是带注释的代码片段:

mov $0x51eb851f,%edx # magic multiplier for signed divide by 100 mov %ecx,%eax # %ecx = x imul %edx # first step of division signed x / 100 sar $0x5,%edx # q = %edx:%eax / 2^(32+5) mov %edx,%edi # %edi = q (so far) mov %ecx,%eax sar $0x1f,%eax # %eax = (x < 0) ? -1 : 0 sub %eax,%edi # %edi = x / 100 -- finally imul $0x64,%edi,%eax # %eax = q * 100 sub %eax,%ecx # %ecx = x - ((x / 100) * 100)

注意:

  • [通常,在此用于乘除的技术中,乘产生的结果按

    2 ^(32 + n)

    放大(对于32位除法)。在这种情况下,n = 5。乘法的总结果为%edx:%eax,而丢弃%eax的结果除以2 ^ 32sar $05, %edx除以​​2 ^ n-由于这是有符号除法,因此需要进行算术移位。
  • 不幸的是,对于有符号除法,移位后的%edx并不是商。如果被除数为-ve(并且除数为+ ve),则需要加1以获得商。因此,如果

    x <0

  • sar $0x1f, %eax则为-1,否则为0。 sub %eax, %edi完成除法。此步骤同样可以通过shr $0x1f, %eaxadd %eax, %edi实现。或add %eax, %eaxadc $0, %edi。或cmp $0x80000000, %ecxsbb $-1, %edi-这是我的最爱,但是不幸的是,保存mov %ecx, %eax如今并没有节省任何费用,无论如何,cmp $0x80000000, %ecx是一条很长的指令:-(

  • 尚不清楚为什么将商

    q

  • 改组为%edi-如果将其留在%edx中,在imul $0x64,%edx,%eax之后仍会存在。
© www.soinside.com 2019 - 2024. All rights reserved.