Assembly 在汇编代码中查找循环或数字
我已经将C++代码转换成具有高优化级别的程序集。Assembly 在汇编代码中查找循环或数字,assembly,floating-point,x86,g++,x86-64,Assembly,Floating Point,X86,G++,X86 64,我已经将C++代码转换成具有高优化级别的程序集。 #include <iostream> using namespace std; int main() { float sum=0; for(int i = 0; i < 10; i++) sum += 1.0f/float(i+1); cout<<sum<<endl; return 0; } 结果是 2.92897 但当我把它转换成汇编时,我不知道这个
#include <iostream>
using namespace std;
int main()
{
float sum=0;
for(int i = 0; i < 10; i++)
sum += 1.0f/float(i+1);
cout<<sum<<endl;
return 0;
}
结果是
2.92897
但当我把它转换成汇编时,我不知道这个号码在哪里。应该有一个循环或(如果展开)最终结果,即2.92897
。但我在以下代码中找不到它:
.file "main.cpp"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB1561:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZSt4cout, %edi
movsd .LC0(%rip), %xmm0
call _ZNSo9_M_insertIdEERSoT_
movq %rax, %rdi
call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1561:
.size main, .-main
.p2align 4,,15
.type _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2048:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZStL8__ioinit, %edi
call _ZNSt8ios_base4InitC1Ev
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp __cxa_atexit
.cfi_endproc
.LFE2048:
.size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_main
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1074228871
.hidden __dso_handle
.ident "GCC: (Ubuntu 7.2.0-1ubuntu1~16.04) 7.2.0"
.section .note.GNU-stack,"",@progbits
我被怀疑.LC0
和1074228871
。但这样的转换通过给我2.11612,这是一个不同的数字
那么,汇编代码中的计算或结果在哪里?循环不仅仅是展开的,它还通过不断的传播完全优化了。这就是为什么
main
除了call
之外没有分支
movsd.LC0(%rip),%xmm0
(MOV Scalar Double)将8字节FP arg加载到cout@ar2015:即使使用gcc,指针转换(至少在理论上)也是不安全的。使用memcpy(&d,&i,8)
将位模式从uint64\u t
复制到double
。这仍然优化为零。或者(使用ISO C99或GNU C++)使用联合。这种投球方式肯定被认为是“错误的”;如果它起作用,那只是一种“碰巧起作用”的情况。根据本书第9.5节,似乎连工会都不安全。还提到:“在一个联合中,最多一个非静态数据成员可以在任何时候处于活动状态,也就是说,最多一个非静态数据成员的值可以在任何时候存储在一个联合中。”@ar2015:它们在构造函数/析构函数语义方面很奇怪。但是对于带有默认构造函数/析构函数的“简单”类型,IDK为什么写一个和读另一个是未定义的。但他们并不是“放弃”支持;C++从不支持联合类型双关。在C99标准化联合型双标前,C++从“C”叉“叉”。(C++中其他代码的使用<代码>联合/代码>当然是合法的;你可以覆盖不同的类型,UB的唯一一个读不匹配先前的写)。e、 g.有符号整数溢出。IDK如果ISO标准维护人员同意编译器开发人员的意见,即大多数事情都应该留待UB处理,并将其视为优化机会,即使是在可以轻松定义行为的目标体系结构上。相关:@ AR2015:IMO,C++应该添加对代码的支持。这将是一种表达类型双关语的干净方式,对于人类读者来说,它具有完全正确的语义,加上简洁明了的语法。使用并集意味着您必须声明额外的变量。如果类型大小不匹配,编译器可能会发出警告,因为您只会将其用于类型双关。事实上,ISO标准可以声明只有当
和(arg)
具有相同的大小时它才有效。
.file "main.cpp"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB1561:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZSt4cout, %edi
movsd .LC0(%rip), %xmm0
call _ZNSo9_M_insertIdEERSoT_
movq %rax, %rdi
call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1561:
.size main, .-main
.p2align 4,,15
.type _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2048:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZStL8__ioinit, %edi
call _ZNSt8ios_base4InitC1Ev
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp __cxa_atexit
.cfi_endproc
.LFE2048:
.size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_main
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1074228871
.hidden __dso_handle
.ident "GCC: (Ubuntu 7.2.0-1ubuntu1~16.04) 7.2.0"
.section .note.GNU-stack,"",@progbits
.LC0:
.long 0
.long 1074228871
.LCPI0_0:
.quad 4613777869364002816 # double 2.9289684295654297
# exactly equivalent to what gcc emits,
# just different syntax for the same 8 bytes