c++ - compiler - emulador 8086 online
¿Por qué GCC llama a sqc() de libc sin usar su resultado? (1)
No necesita llamar a
sqrt
para calcular el resultado;
ya ha sido calculado por la instrucción SQRTSD.
Llama a
sqrt
para generar el comportamiento requerido de acuerdo con el estándar cuando se pasa un número negativo a
sqrt
(por ejemplo, establecer
errno
y / o generar una excepción de punto flotante).
Las instrucciones PXOR, UCOMISD y JBE prueban si el argumento es menor que 0 y omiten la llamada a
sqrt
si esto no es cierto.
Usando GCC 6.3, el siguiente código C ++:
#include <cmath>
#include <iostream>
void norm(double r, double i)
{
double n = std::sqrt(r * r + i * i);
std::cout << "norm = " << n;
}
genera el siguiente ensamblado 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)
Para la llamada a
std::sqrt
, GCC primero lo hace usando
sqrtsd
y guarda el resultado en la pila.
Si se desborda, llama a la función libc
sqrt
.
Pero nunca guarda el
xmm0
después de eso y antes de la segunda llamada al
operator<<
, restaura el valor de la pila (porque
xmm0
se perdió con la primera llamada al
operator<<
).
Con un
std::cout << n;
más simple
std::cout << n;
, es aún más obvio:
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)
¿Por qué GCC no utiliza el valor
xmm0
calculado por libc
sqrt
?