2012-01-04 8 views
5

me encontré con un código similar al siguiente día de hoy y estoy curioso en cuanto a lo que realmente está sucediendo:¿Qué es la sobrealineación de las regiones de ejecución y las secciones de entrada?

#pragma pack(1) 
__align(2) static unsigned char multi_array[7][24] = { 0 }; 
__align(2) static unsigned char another_multi_array[7][24] = { 0 }; 
#pragma pack() 

Durante la búsqueda de una referencia a la palabra clave __align en el compilador Keil, me encontré con esto:

Overalignment de regiones de ejecución y secciones de entrada Hay situaciones en las que desea sobrealinear código y secciones de datos ... Si tiene acceso al código fuente original, puede hacerlo en tiempo de compilación con __align (n) palabra clave ...

No entiendo lo que significa "código de sobrealimentación de secciones de datos y datos". ¿Alguien puede ayudar a aclarar cómo se produce esta sobrealineación?

+1

Overalighment puede ser útil en ARM. La instrucción "load immediate" (MOV) no puede cargar un valor completo de 32 bits. En cambio, puede cargar 8 bits a la vez, rotar a cualquier posición. Por este motivo, es posible que el código intente hacer que la dirección finalice en más bits cero, lo que facilita o agiliza que el código compilado le cargue el valor del puntero. –

Respuesta

6

El compilador naturalmente "alineará" los datos según las necesidades del sistema. Por ejemplo, en un sistema típico de 32 bits, un entero de 32 bits siempre debe ser una sola palabra de 4 bytes (en lugar de estar parcialmente en una palabra y en parte en la siguiente), por lo que siempre comenzará en un 4 límite de palabra byte. (Esto tiene que ver principalmente con las instrucciones disponibles en el procesador. Es muy probable que un sistema tenga una instrucción para cargar una sola palabra de la memoria en un registro, y mucho menos probable que tenga una sola instrucción para cargar una secuencia arbitraria de cuatro bytes adyacentes en un registro.)

El compilador normalmente hace esto al introducir espacios en los datos; por ejemplo, un struct con un char seguido de un 32-bit int, en un sistema tal, requeriría ocho bytes: un byte para el char, tres bytes de relleno de modo que el int está alineado a la derecha, y cuatro bytes para el int sí .

Para "sobrealinear" los datos es para solicitar una mayor alineación de la que el compilador proporcionaría naturalmente. Por ejemplo, puede solicitar que un entero de 32 bits comience en un límite de 8 bytes, incluso en un sistema que usa palabras de 4 bytes. (Una razón importante para hacer esto sería si está buscando la interoperabilidad a nivel de bytes con un sistema que usa palabras de 8 bytes: si pasa struct s de un sistema a otro, quiere los mismos espacios en ambos sistemas.)

+0

Entonces, en el caso de una matriz multidimensional declarada como char sin signo (como en el ejemplo anterior), ¿cada elemento se alineará con dos bytes? –

+0

@embedded_guy: No, solo la variable, es decir, la matriz como un todo; dado que es una matriz de elementos de un byte, normalmente no requerirá ninguna alineación, pero el '__align (2)' solicita que comience en un límite de dos bytes. No es posible alinear cada elemento a dos bytes, porque cualquier cliente que use la matriz debería saberlo. (Al declarar un tipo 'struct', puede alinear campos individuales porque cualquier persona que use una' struct' siempre necesita todos los 'offsetof's, pero para las matrices, se usa la aritmética del puntero). – ruakh

+0

@downvoter: ¿Le importa explicar? – ruakh

5

Por sobrealineación, Keil no significa nada más complejo que alinear un objeto a un límite de alineación mayor que el que requiere el tipo de datos.

Consulte la documentación para __align: "Solo puede sobrealinear. Es decir, puede hacer que un objeto de dos bytes esté alineado con cuatro bytes, pero no puede alinear un objeto de cuatro bytes con 2 bytes".

En el caso del vinculador, puede forzar una alineación adicional en secciones dentro de otros módulos binarios mediante las directivas ALIGNALL o OVERALIGN. Esto puede ser útil por razones de rendimiento, pero no es un escenario común.

4

La sobrealineación es cuando los datos están alineados con algo más que su alineación predeterminada. Por ejemplo, un 4-byte int generalmente tiene una alineación predeterminada de 4 bytes. (lo que significa que la dirección será divisible por 4)

La alineación predeterminada de un tipo de datos es muy a menudo (pero no siempre) el tamaño del tipo de datos.

La alineación adicional le permite aumentar esta alineación a algo mayor que el valor predeterminado.


En cuanto a por qué querría hacer esto:

Una razón para esto es ser capaz de acceder a los datos con un tipo de datos más grande (que tiene una alineación más grande).

Por ejemplo:

char buffer[16]; 

int *ptr = (int*)&buffer; 

ptr[0] = 1; 
ptr[1] = 2; 

Por defecto, tampón solamente se alinearán con 1 byte. Sin embargo, int requiere una alineación de 4 bytes. Si buffer no está alineado a 4 bytes, obtendrá una excepción de desalineación. (Que yo sepa, ARM no permite acceso a la memoria desalineadas ... 86/64 generalmente lo hace, pero con penalización de rendimiento)

__align() le permitirá forzar la alineación más alta para hacer que funcione:

__align(4) char buffer[16]; 

Aparece una situación similar cuando se usan las instrucciones SIMD. Accederá a un tipo de datos más pequeño con un tipo de datos SIMD grande, lo que probablemente requerirá una mayor alineación.

+0

¿Le importa explicar el voto a la baja? ¿Qué dije mal? – Mysticial

+0

No estoy seguro de quién votó en contra. Encontré tu respuesta útil y le di un voto positivo. –

+0

+1 para el buen ejemplo con 'int * ptr = (int *) & buffer'. (Y para cancelar el downvoter anónimo). – ruakh

Cuestiones relacionadas