Ben*_*oît 56 c++ assembly gcc x86-64
使用GCC 6.3,以下C++代码:
#include <cmath>
#include <iostream>
void norm(double r, double i)
{
double n = std::sqrt(r * r + i * i);
std::cout << "norm = " << n;
}
Run Code Online (Sandbox Code Playgroud)
生成以下x86-64程序集:
norm(double, double):
mulsd %xmm1, %xmm1
subq $24, %rsp
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
pxor %xmm1, %xmm1
ucomisd %xmm0, %xmm1
sqrtsd %xmm0, %xmm2
movsd %xmm2, 8(%rsp)
jbe .L2
call sqrt
.L2:
movl std::cout, %edi
movl $7, %edx
movl $.LC1, %esi
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
movsd 8(%rsp), %xmm0
movl std::cout, %edi
addq $24, %rsp
jmp std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
Run Code Online (Sandbox Code Playgroud)
对于调用std::sqrt,GCC首先使用sqrtsd并将结果保存到堆栈中.如果它溢出,则调用libc sqrt函数.但它永远不会保存xmm0之后,在第二次调用之前operator<<,它会从堆栈中恢复值(因为xmm0第一次调用时丢失了operator<<).
更简单std::cout << n;,它更加明显:
subq $24, %rsp
movsd %xmm1, 8(%rsp)
call sqrt
movsd 8(%rsp), %xmm1
movl std::cout, %edi
addq $24, %rsp
movapd %xmm1, %xmm0
jmp std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
Run Code Online (Sandbox Code Playgroud)
为什么GCC不使用xmm0libc计算的值sqrt?
Ros*_*dge 76
它不需要调用sqrt来计算结果; 它已经由SQRTSD指令计算出来.sqrt当传递负数时sqrt(例如,设置errno和/或引发浮点异常),它调用根据标准生成所需行为.PXOR,UCOMISD和JBE指令测试参数是否小于0并跳过调用,sqrt如果不是这样.
| 归档时间: |
|
| 查看次数: |
3106 次 |
| 最近记录: |