Recherche…


Remarques

L'assemblage en ligne est la pratique consistant à ajouter des instructions d'assemblage au milieu du code source C. Aucune norme ISO C ne nécessite le support d'un assemblage en ligne. Comme il n'est pas requis, la syntaxe de l'assemblage en ligne varie d'un compilateur à l'autre. Même s'il est généralement pris en charge, il y a très peu de raisons d'utiliser l'assemblage en ligne et de nombreuses raisons de ne pas le faire.

Avantages

  1. Performances En écrivant les instructions d'assemblage spécifiques pour une opération, vous pouvez obtenir de meilleures performances que le code assembleur généré par le compilateur. Notez que ces gains de performance sont rares. Dans la plupart des cas, vous pouvez obtenir de meilleurs résultats tout en réorganisant votre code C afin que l'optimiseur puisse faire son travail.
  2. Interface matérielle Le code de démarrage du pilote de périphérique ou du processeur peut nécessiter un code d'assemblage pour accéder aux registres appropriés et pour garantir que certaines opérations se produisent dans un ordre spécifique avec un délai spécifique entre les opérations.

Les inconvénients

  1. Portabilité du compilateur La syntaxe de l'assemblage en ligne n'est pas garantie d'un même compilateur à l'autre. Si vous écrivez du code avec un assemblage en ligne qui doit être pris en charge par différents compilateurs, utilisez des macros de préprocesseur ( #ifdef ) pour vérifier quel compilateur est utilisé. Ensuite, écrivez une section d'assemblage en ligne distincte pour chaque compilateur pris en charge.
  2. Portabilité du processeur Vous ne pouvez pas écrire un assemblage en ligne pour un processeur x86 et attendez-vous à ce qu'il fonctionne sur un processeur ARM. L'assemblage en ligne est destiné à être écrit pour un processeur ou une famille de processeurs spécifique. Si vous avez un assemblage en ligne que vous souhaitez prendre en charge sur différents processeurs, utilisez des macros de préprocesseur pour vérifier le processeur pour lequel le code est compilé et pour sélectionner la section de code d'assemblage appropriée.
  3. Modifications futures des performances L'assemblage en ligne peut être écrit en anticipant les retards en fonction d'une certaine vitesse d'horloge du processeur. Si le programme est compilé pour un processeur avec une horloge plus rapide, le code de l'assembly peut ne pas fonctionner comme prévu.

gcc Basic asm support

La prise en charge de l'assembly de base avec gcc a la syntaxe suivante:

asm [ volatile ] ( AssemblerInstructions )

AssemblerInstructions est le code d'assemblage direct du processeur donné. Le mot clé volatile est facultatif et n'a aucun effet car gcc n'optimise pas le code dans une instruction asm de base. AssemblerInstructions instructions d'assemblage peuvent contenir plusieurs instructions d'assemblage. Une instruction asm de base est utilisée si vous avez une routine asm devant exister en dehors d'une fonction C. L'exemple suivant provient du manuel GCC:

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

Dans cet exemple, vous pouvez alors utiliser DebugBreak() à d’autres endroits de votre code pour exécuter l’instruction d’assemblage int $3 . Notez que même si gcc ne modifie aucun code dans une instruction asm de base, l'optimiseur peut toujours déplacer les instructions asm consécutives. Si vous avez plusieurs instructions d'assemblage qui doivent apparaître dans un ordre spécifique, incluez-les dans une seule instruction asm.

gcc Support asm étendu

La prise en charge asm étendue dans gcc a la syntaxe suivante:

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

AssemblerTemplate est le modèle de l'instruction assembleur, OutputOperands est une variable C pouvant être modifiée par le code assembleur, InputOperands est une variable C utilisée comme paramètre d'entrée, Clobbers est une liste ou un registre modifié par le code assembleur et GotoLabels sont des étiquettes de déclaration goto qui peuvent être utilisées dans le code d'assemblage.

Le format étendu est utilisé dans les fonctions C et constitue l'utilisation la plus courante de l'assemblage en ligne. Vous trouverez ci-dessous un exemple du noyau Linux pour l'échange d'octets de nombres 16 bits et 32 ​​bits pour un processeur 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

Chaque section asm utilise la variable x comme paramètre d'entrée et de sortie. La fonction C renvoie alors le résultat manipulé.

Avec le format asm étendu, gcc peut optimiser les instructions d'assemblage dans un bloc asm en suivant les mêmes règles que celles utilisées pour optimiser le code C. Si vous souhaitez que votre section asm reste intacte, utilisez le mot-clé volatile pour la section asm.

Assemblage en ligne gcc dans les macros

Nous pouvons mettre des instructions d'assemblage dans une macro et utiliser la macro comme vous appelleriez une fonction.

#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]);

L'utilisation d'instructions d'assemblage intégrées au code C peut améliorer le temps d'exécution d'un programme. Ceci est très utile dans les situations critiques pour le temps, comme les algorithmes cryptographiques tels que AES. Par exemple, pour une opération de décalage simple nécessaire dans l'algorithme AES, nous pouvons substituer une instruction d'assemblage Rotate Right directe à l'opérateur C shift >> .

Dans une implémentation de 'AES256', dans la fonction 'AddRoundKey ()' nous avons des instructions comme ceci:

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

Ils attribuent simplement la valeur de bit de w au tableau de subkey .

Nous pouvons changer trois shift + assign et une autre assigner une expression avec un seul assemblage. Rotate Right operation.

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

Le résultat final est exactement le même.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow