我试图在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部分的?
答案 0 :(得分:2)
编译器足够智能,可以意识到如果你采用一个数字mod 4(% 4
),它在逻辑上与3
的逻辑和数字相同,并且速度更快。这将是汇编语言列表中的第9行。它可以肯定地知道这一点,因为4
是一个常量,因此它可以遵循算术“规则”。
你也会在其他方面看到这种翻译。例如,如果乘以(或除以)4
,编译器可以选择向左(或右)生成2位的算术移位,相当于乘以(或除以){{1} ,但可能比乘法(或除法)指令更快,具体取决于CPU和场景。
编译器可以在算术领域内外进行其他几种常见的优化,它们可以破坏C指令流和汇编语言指令流之间的直观对应,超出了这个特定问题的范围。