C/C++;:&引用;模块2“;不产生与“相同的说明”;和1“;(gcc-O3)
当使用gcc和最大优化(gcc 11.1.0,C/C++;:&引用;模块2“;不产生与“相同的说明”;和1“;(gcc-O3),c,assembly,gcc,compiler-optimization,C,Assembly,Gcc,Compiler Optimization,当使用gcc和最大优化(gcc 11.1.0,gcc-std=c11-O3)编译这两个代码段时,我希望得到完全相同的可执行文件,因为%2和&1操作是等价的。但是,在使用objdump进行反汇编之后,这两个对象文件有所不同。输出如下所示 及 int main(int argc,char**argv){ 返回argc&1; } 0000000000001020: 1020:89 fa mov%edi,%edx 1022:c1 ea 1f shr$0x1f,%edx 1025:8d 04 17 le
gcc-std=c11-O3
)编译这两个代码段时,我希望得到完全相同的可执行文件,因为%2
和&1
操作是等价的。但是,在使用objdump
进行反汇编之后,这两个对象文件有所不同。输出如下所示
及
int main(int argc,char**argv){
返回argc&1;
}
0000000000001020:
1020:89 fa mov%edi,%edx
1022:c1 ea 1f shr$0x1f,%edx
1025:8d 04 17 lea(%rdi,%rdx,1),%eax
1028:83 e0 01和$0x1,%eax
102b:29 d0子%edx,%eax
102d:c3 ret
102e:66 90 xchg%ax,%ax
我理解第一个程序中的指令,但我不太明白第二个程序中某些行的目的
应表示“右移31位shr$0x1f,%edx
”%edx
lea(%rdi,%rdx,1),%eax应表示“保存在
地址%eax
处保存的值”%rdi+%rdx*1
为什么这两个项目不同?为什么编译器没有将
%2
优化为&1
,这据说更快,使用的指令更少?val%2
如果val
为负值,则可能为负值val&1
将仅具有正值(或零)。因此,这些操作不相同-因此编译代码不同。您使用了有符号整数,其中%2
不等同于&1
,如果将其强制转换为无符号
,编译器将(可能)生成相同的代码。在锁紧螺栓上是这样。%2
和&1
对于负数不等效x%2
与x&1
不同,因为x%2
如果x是负数和奇数,则为-1。编译器必须知道argc
不能是负数。您对lea
的解释似乎是错误的。它的意思是“加载有效地址”,在%eax
中加载%rdi
和%rdx
的总和。shr指令的目的是隔离符号位,以便在值为负值时获得不同的行为。好的,没错,我尝试使用无符号int
,它实际上生成了正确的代码。非常感谢。
0000000000001020 <main>:
1020: 89 f8 mov %edi,%eax
1022: 83 e0 01 and $0x1,%eax
1025: c3 ret
1026: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
0000000000001020 <main>:
1020: 89 fa mov %edi,%edx
1022: c1 ea 1f shr $0x1f,%edx
1025: 8d 04 17 lea (%rdi,%rdx,1),%eax
1028: 83 e0 01 and $0x1,%eax
102b: 29 d0 sub %edx,%eax
102d: c3 ret
102e: 66 90 xchg %ax,%ax