Buscar..


Observaciones

El ensamblaje en línea es la práctica de agregar instrucciones de ensamblaje en medio del código fuente de C. Ninguna norma ISO C requiere soporte de montaje en línea. Como no es obligatorio, la sintaxis para el ensamblaje en línea varía de compilador a compilador. Aunque normalmente se admite, hay muy pocas razones para usar el ensamblaje en línea y muchas razones para no hacerlo.

Pros

  1. Rendimiento Al escribir las instrucciones de ensamblaje específicas para una operación, puede lograr un mejor rendimiento que el código de ensamblaje generado por el compilador. Tenga en cuenta que estas ganancias de rendimiento son raras. En la mayoría de los casos, puede lograr mejores ganancias de rendimiento simplemente reorganizando su código C para que el optimizador pueda hacer su trabajo.
  2. Interfaz de hardware El controlador de dispositivo o el código de inicio del procesador pueden necesitar algún código de ensamblaje para acceder a los registros correctos y garantizar que ciertas operaciones se realicen en un orden específico con un retraso específico entre las operaciones.

Contras

  1. No se garantiza que la sintaxis de portabilidad del compilador sea ​​el mismo de un compilador a otro. Si está escribiendo código con ensamblaje en línea que debe ser compatible con compiladores diferentes, use macros de preprocesador ( #ifdef ) para verificar qué compilador se está utilizando. Luego, escriba una sección de ensamblaje en línea por separado para cada compilador compatible.
  2. Portabilidad del procesador No puede escribir un ensamblaje en línea para un procesador x86 y esperar que funcione en un procesador ARM. El ensamblaje en línea está diseñado para ser escrito para un procesador específico o una familia de procesadores. Si tiene el ensamblaje en línea que desea que sea compatible con diferentes procesadores, use macros de preprocesador para verificar en qué procesador se está compilando el código y para seleccionar la sección de código de ensamblaje correspondiente.
  3. Cambios futuros de rendimiento El ensamblaje en línea se puede escribir esperando demoras basadas en una cierta velocidad de reloj del procesador. Si el programa se compila para un procesador con un reloj más rápido, es posible que el código de ensamblaje no funcione como se espera.

Soporte básico de asc gcc

El soporte de ensamblaje básico con gcc tiene la siguiente sintaxis:

asm [ volatile ] ( AssemblerInstructions )

donde AssemblerInstructions es el código de ensamblaje directo para el procesador dado. La palabra clave volátil es opcional y no tiene efecto, ya que gcc no optimiza el código dentro de una declaración básica de asm. AssemblerInstructions puede contener varias instrucciones de montaje. Se usa una declaración básica de asm si tiene una rutina de asm que debe existir fuera de una función de C. El siguiente ejemplo es del manual de GCC:

 /* Note that this code will not compile with -masm=intel */
 #define DebugBreak() asm("int $3")

En este ejemplo, podría usar DebugBreak() en otros lugares de su código y ejecutará la instrucción de ensamblaje int $3 . Tenga en cuenta que aunque gcc no modificará ningún código en una declaración básica de asm, el optimizador aún puede mover las declaraciones de asm consecutivas. Si tiene varias instrucciones de ensamblaje que deben ocurrir en un orden específico, inclúyalas en una declaración asm.

Soporte de asm gcc extendido

El soporte extendido de asm en gcc tiene la siguiente sintaxis:

asm [volatile] ( AssemblerTemplate
                  : OutputOperands
                  [ : InputOperands
                  [ : Clobbers ] ])
 
 asm [volatile] goto ( AssemblerTemplate
                       :
                       : InputOperands
                       : Clobbers
                       : GotoLabels)

donde AssemblerTemplate es la plantilla para la instrucción del ensamblador, OutputOperands son las variables C que pueden modificarse mediante el código de ensamblaje, InputOperands son las variables C utilizadas como parámetros de entrada, Clobbers son una lista o registros modificados por el código de ensamblaje y GotoLabels son las etiquetas de instrucciones goto que se pueden usar en el código de ensamblaje.

El formato extendido se usa dentro de las funciones C y es el uso más típico del ensamblaje en línea. A continuación se muestra un ejemplo del kernel de Linux para el intercambio de bytes de números de 16 y 32 bits por un procesador ARM:

/* From arch/arm/include/asm/swab.h in Linux kernel version 4.6.4 */
#if __LINUX_ARM_ARCH__ >= 6

static inline __attribute_const__ __u32 __arch_swahb32(__u32 x)
{
    __asm__ ("rev16 %0, %1" : "=r" (x) : "r" (x));
    return x;
}
#define __arch_swahb32 __arch_swahb32
#define __arch_swab16(x) ((__u16)__arch_swahb32(x))

static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
    __asm__ ("rev %0, %1" : "=r" (x) : "r" (x));
    return x;
}
#define __arch_swab32 __arch_swab32

#endif

Cada sección de asm usa la variable x como su parámetro de entrada y salida. La función C devuelve el resultado manipulado.

Con el formato extendido de asm, gcc puede optimizar las instrucciones de ensamblaje en un bloque de asm siguiendo las mismas reglas que utiliza para optimizar el código C. Si desea que su sección de asm permanezca intacta, use la palabra clave volatile para la sección de asm.

Gcc Inline Assembly en macros

Podemos colocar instrucciones de ensamblaje dentro de una macro y usar la macro como llamaríamos a una función.

#define mov(x,y) \
{ \
    __asm__ ("l.cmov %0,%1,%2" : "=r" (x) : "r" (y), "r" (0x0000000F)); \
}

/// some definition and assignment
unsigned char sbox[size][size];
unsigned char sbox[size][size];

///Using
mov(state[0][1], sbox[si][sj]);

El uso de instrucciones de ensamblaje integradas en el código C puede mejorar el tiempo de ejecución de un programa. Esto es muy útil en situaciones críticas como algoritmos criptográficos como AES. Por ejemplo, para una operación de cambio simple que se necesita en el algoritmo AES, podemos sustituir una instrucción de montaje directo Rotate Right con el operador de cambio C >> .

En una implementación de 'AES256', en la función 'AddRoundKey ()' tenemos algunas declaraciones como esta:

unsigned int w;          // 32-bit
unsigned char subkey[4]; // 8-bit, 4*8 = 32 

subkey[0] = w >> 24;     // hold 8 bit, MSB, leftmost group of 8-bits 
subkey[1] = w >> 16;     // hold 8 bit, second group of 8-bit from left    
subkey[2] = w >> 8;      // hold 8 bit, second group of 8-bit from right
subkey[3] = w;           // hold 8 bit, LSB, rightmost group of 8-bits

/// subkey <- w

Simplemente asignan el valor de bit de w a la matriz de subkey .

Podemos cambiar tres Mayús + asignar y una Asignar C expresión con solo un ensamblaje de operación Rotate Right .

__asm__ ("l.ror  %0,%1,%2" : "=r" (* (unsigned int *) subkey)  : "r" (w), "r" (0x10));

El resultado final es exactamente igual.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow