Comprender las instrucciones de ensamblaje para una función que suma tres enteros de un std::array.
Tengo la siguiente función de C++ que simplemente suma los tres elementos del array de entrada dado.
#include
using namespace std;
int square(array<int, 3=””> ar) {
int res = 0;
for(int idx = 0; idx < ar.size(); idx++){
res += ar[idx];
}
return res;
}
Este código compilado con Clang (gcc e icc producen el mismo código) y la bandera del compilador -O3 produce el siguiente ensamblaje x86-64:
sum(std::array<int, 3ul=””>):
mov rax, rdi
shr rax, 32
add eax, edi
add eax, esi
ret
Mi interpretación actual del ensamblaje es que ocurre lo siguiente:
64 bits se mueven del registro de entrada de 64 bits rdi al registro de salida de 64 bits rax. Esto corresponde a ints de 32 bits.
shr desplaza el contenido de rax en 32 bits, manteniendo solo el primer int de 32 bits contenido en rdi.
se le suma el contenido del registro de entrada de 32 bits edi al registro de salida de 32 bits eax.
se le suma el contenido del segundo registro de entrada de 32 bits esi a eax.
se devuelve eax.
Sin embargo, tengo algunas preguntas:
¿Puede el ordenador simplemente desplazarse entre registros de 32 y 64 bits como se hace en las dos primeras instrucciones?
¿No debería el uso de shr resultar en que el primer int se sume dos veces debido a que el segundo int se desplaza? (¿Tiene esto que ver con el orden de bytes?)
Como nota adicional: el compilador produce las mismas instrucciones de ensamblaje cuando se le proporciona un bucle for basado en rango.
#include
using namespace std;
int sum(array<int, 3=””> ar) {
int res = 0;
for(const auto& in: ar){
res += in;
}
return res;
}
Puedes encontrar el ejemplo aquí: https://godbolt.org/z/s3fera7ca</int,></int,></int,>
davy.ai
Respuestas a las preguntas