汇编代码 - %4在哪里实施?

时间:2014-04-03 00:21:53

标签: assembly

我试图在C函数的disas中找到它实现%4的位置。这是一个没有优化编译的程序。这是C中的函数:

uint function (uint len, int*   intArray) {   
   uint i;   uint sum = 0;

  for  (i = 0;  i < len-2;  i++)
    switch  (i % 4)
    {
    case 0 :
      sum += countPairsUpTo(len-2,intArray,8,6);
      break;

    case 1 :
      sum += countPairsUpTo(len-2,intArray,0,0);
      break;

    case 2 :
      sum += countPairsUpTo(len-2,intArray,15,0);
      break;

    case 3 :
      sum += countPairsUpTo(len-2,intArray,7,9);
      break;
    }

  return(sum); }

这是集会:

0x08048607 <funkyFunction+0>:   push   %ebp
0x08048608 <funkyFunction+1>:   mov    %esp,%ebp
0x0804860a <funkyFunction+3>:   sub    $0x24,%esp
0x0804860d <funkyFunction+6>:   call   0x8048418 <mcount@plt>
0x08048612 <funkyFunction+11>:  movl   $0x0,-0x4(%ebp)
0x08048619 <funkyFunction+18>:  movl   $0x0,-0x8(%ebp)
0x08048620 <funkyFunction+25>:  jmp    0x8048704 <funkyFunction+253>
0x08048625 <funkyFunction+30>:  mov    -0x8(%ebp),%eax
0x08048628 <funkyFunction+33>:  and    $0x3,%eax
0x0804862b <funkyFunction+36>:  mov    %eax,-0x14(%ebp)
0x0804862e <funkyFunction+39>:  cmpl   $0x1,-0x14(%ebp)
0x08048632 <funkyFunction+43>:  je     0x804867e <funkyFunction+119>
0x08048634 <funkyFunction+45>:  cmpl   $0x1,-0x14(%ebp)
0x08048638 <funkyFunction+49>:  jb     0x804864f <funkyFunction+72>
0x0804863a <funkyFunction+51>:  cmpl   $0x2,-0x14(%ebp)
0x0804863e <funkyFunction+55>:  je     0x80486aa <funkyFunction+163>
0x08048640 <funkyFunction+57>:  cmpl   $0x3,-0x14(%ebp)
0x08048644 <funkyFunction+61>:  je     0x80486d6 <funkyFunction+207>
0x0804864a <funkyFunction+67>:  jmp    0x8048700 <funkyFunction+249>
0x0804864f <funkyFunction+72>:  mov    0x8(%ebp),%eax
0x08048652 <funkyFunction+75>:  sub    $0x2,%eax
0x08048655 <funkyFunction+78>:  mov    %eax,%edx
0x08048657 <funkyFunction+80>:  movl   $0x6,0xc(%esp)
0x0804865f <funkyFunction+88>:  movl   $0x8,0x8(%esp)
0x08048667 <funkyFunction+96>:  mov    0xc(%ebp),%eax
0x0804866a <funkyFunction+99>:  mov    %eax,0x4(%esp)
0x0804866e <funkyFunction+103>: mov    %edx,(%esp)
0x08048671 <funkyFunction+106>: call   0x80485b1 <countPairsUpTo>
0x08048676 <funkyFunction+111>: add    %eax,-0x4(%ebp)
0x08048679 <funkyFunction+114>: jmp    0x8048700 <funkyFunction+249>
0x0804867e <funkyFunction+119>: mov    0x8(%ebp),%eax
0x08048681 <funkyFunction+122>: sub    $0x2,%eax
0x08048684 <funkyFunction+125>: mov    %eax,%edx
0x08048686 <funkyFunction+127>: movl   $0x0,0xc(%esp)
0x0804868e <funkyFunction+135>: movl   $0x0,0x8(%esp)
0x08048696 <funkyFunction+143>: mov    0xc(%ebp),%eax
0x08048699 <funkyFunction+146>: mov    %eax,0x4(%esp)
0x0804869d <funkyFunction+150>: mov    %edx,(%esp)
---Type <return> to continue, or q <return> to quit---
0x080486a0 <funkyFunction+153>: call   0x80485b1 <countPairsUpTo>
0x080486a5 <funkyFunction+158>: add    %eax,-0x4(%ebp)
0x080486a8 <funkyFunction+161>: jmp    0x8048700 <funkyFunction+249>
0x080486aa <funkyFunction+163>: mov    0x8(%ebp),%eax
0x080486ad <funkyFunction+166>: sub    $0x2,%eax
0x080486b0 <funkyFunction+169>: mov    %eax,%edx
0x080486b2 <funkyFunction+171>: movl   $0x0,0xc(%esp)
0x080486ba <funkyFunction+179>: movl   $0xf,0x8(%esp)
0x080486c2 <funkyFunction+187>: mov    0xc(%ebp),%eax
0x080486c5 <funkyFunction+190>: mov    %eax,0x4(%esp)
0x080486c9 <funkyFunction+194>: mov    %edx,(%esp)
0x080486cc <funkyFunction+197>: call   0x80485b1 <countPairsUpTo>
0x080486d1 <funkyFunction+202>: add    %eax,-0x4(%ebp)
0x080486d4 <funkyFunction+205>: jmp    0x8048700 <funkyFunction+249>
0x080486d6 <funkyFunction+207>: mov    0x8(%ebp),%eax
0x080486d9 <funkyFunction+210>: sub    $0x2,%eax
0x080486dc <funkyFunction+213>: mov    %eax,%edx
0x080486de <funkyFunction+215>: movl   $0x9,0xc(%esp)
0x080486e6 <funkyFunction+223>: movl   $0x7,0x8(%esp)
0x080486ee <funkyFunction+231>: mov    0xc(%ebp),%eax
0x080486f1 <funkyFunction+234>: mov    %eax,0x4(%esp)
0x080486f5 <funkyFunction+238>: mov    %edx,(%esp)
0x080486f8 <funkyFunction+241>: call   0x80485b1 <countPairsUpTo>
0x080486fd <funkyFunction+246>: add    %eax,-0x4(%ebp)
0x08048700 <funkyFunction+249>: addl   $0x1,-0x8(%ebp)
0x08048704 <funkyFunction+253>: mov    0x8(%ebp),%eax
0x08048707 <funkyFunction+256>: sub    $0x2,%eax
0x0804870a <funkyFunction+259>: cmp    -0x8(%ebp),%eax
0x0804870d <funkyFunction+262>: ja     0x8048625 <funkyFunction+30>
0x08048713 <funkyFunction+268>: mov    -0x4(%ebp),%eax
0x08048716 <funkyFunction+271>: leave  
0x08048717 <funkyFunction+272>: ret    

我在第30行看到的是它在哪里。 在第253行,它正在变为len。在第256行,它计算len-2。在第259行,它将len-2与i进行比较。然后,如果我&lt; len-2,它回到第30行。它是如何执行%4部分的?

1 个答案:

答案 0 :(得分:2)

编译器足够智能,可以意识到如果你采用一个数字mod 4(% 4),它在逻辑上与3的逻辑和数字相同,并且速度更快。这将是汇编语言列表中的第9行。它可以肯定地知道这一点,因为4是一个常量,因此它可以遵循算术“规则”。

你也会在其他方面看到这种翻译。例如,如果乘以(或除以)4,编译器可以选择向左(或右)生成2位的算术移位,相当于乘以(或除以){{1} ,但可能比乘法(或除法)指令更快,具体取决于CPU和场景。

编译器可以在算术领域内外进行其他几种常见的优化,它们可以破坏C指令流和汇编语言指令流之间的直观对应,超出了这个特定问题的范围。