online emulador compiler assembler asm c++ gcc assembly x86-64

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 ?