es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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,>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Respuestas a las preguntas

    1. Sí, la computadora puede cambiar fácilmente entre registros de 32 y 64 bits siempre y cuando los valores en los que se opera se ajusten en los bits disponibles de los registros. En este caso, dado que los valores de entrada son enteros de 32 bits, pueden ser almacenados en registros de 32 bits y manipulados como tales.
    2. No, el uso de shr no resulta en que el primer entero sea sumado dos veces. La instrucción shr desplaza el valor de rax hacia la derecha en 32 bits, descartando así los 32 bits superiores del registro de 64 bits. Los 32 bits inferiores de rdi se suman luego a los 32 bits restantes en eax. A continuación, se suma el segundo entero en esi a eax, que contiene la suma del primer y segundo entero. Finalmente, se suma el tercer entero a eax, lo cual resulta en la suma deseada de los tres enteros. Esto no tiene nada que ver con el endianness, que se refiere a la forma en que se almacenan los bytes en la memoria.

Comments are closed.