Sök…


Anmärkningar

Inline montering är praxis att lägga till monteringsinstruktioner mitt i C-källkoden. Ingen ISO C-standard kräver stöd för inline-montering. Eftersom det inte krävs varierar syntaxen för inline-montering från kompilator till kompilator. Även om det vanligtvis stöds finns det mycket få skäl att använda inline-montering och många skäl att inte göra det.

Fördelar

  1. Prestanda Genom att skriva specifika monteringsinstruktioner för en operation kan du uppnå bättre prestanda än monteringskoden genererad av kompilatorn. Observera att dessa resultat är sällsynta. I de flesta fall kan du uppnå bättre prestandaförsäljningar bara genom att ordna om din C-kod så att optimeringen kan göra sitt jobb.
  2. Maskinvarugränssnitt Enhetsdrivrutin eller processor startkod kan behöva viss monteringskod för att få åtkomst till korrekta register och för att garantera att vissa operationer sker i en specifik ordning med en specifik fördröjning mellan operationerna.

Nackdelar

  1. Kompilatorportabilitet Syntax för inline-montering garanteras inte vara samma från en kompilator till en annan. Om du skriver kod med inline-montering som ska stöds av olika kompilatorer, använd preprocessor-makron ( #ifdef ) för att kontrollera vilken kompilator som används. Skriv sedan en separat inline-monteringsdel för varje kompilator som stöds.
  2. Processorportabilitet Du kan inte skriva inlineenhet för en x86-processor och förvänta sig att den ska fungera på en ARM-processor. Inline-montering är avsett att skrivas för en specifik processor eller processorfamilj. Om du har inline-montering som du vill ha stöd på olika processorer, använd preprocessor-makron för att kontrollera vilken processor koden kompileras för och välja rätt monteringskodavsnitt.
  3. Framtida prestationsändringar Inline-montering kan skrivas med förväntningar på förseningar baserade på en viss processorklockhastighet. Om programmet är kompilerat för en processor med en snabbare klocka, kanske monteringskoden inte fungerar som förväntat.

gcc Basic asm support

Grundläggande monteringsstöd med gcc har följande syntax:

asm [ volatile ] ( AssemblerInstructions )

där AssemblerInstructions är den direkta monteringskoden för den givna processorn. Det flyktiga sökordet är valfritt och har ingen effekt eftersom gcc inte optimerar koden inom ett grundläggande ASM-uttalande. AssemblerInstructions kan innehålla flera monteringsinstruktioner. En grundläggande asm-sats används om du har en asm-rutin som måste existera utanför en C-funktion. Följande exempel är från GCC-manualen:

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

I det här exemplet kan du sedan använda DebugBreak() på andra platser i din kod och det kommer att utföra monteringsinstruktionen int $3 . Observera att även om gcc inte kommer att ändra någon kod i ett grundläggande ASM-uttalande, kan optimeringsprogrammet fortfarande flytta på varandra följande ASM-uttalanden. Om du har flera monteringsinstruktioner som måste förekomma i en specifik ordning, inkludera dem i ett asm-uttalande.

gcc Utökat asm-stöd

Utökat asm-stöd i gcc har följande syntax:

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

där AssemblerTemplate är mallen för monteringsinstruktionen, OutputOperands är alla C-variabler som kan modifieras med monteringskoden, InputOperands är alla C-variabler som används som Clobbers , Clobbers är en lista eller register som modifieras av monteringskoden och GotoLabels är alla etiketter för goto-uttalanden som kan användas i monteringskoden.

Det utökade formatet används inom C-funktioner och är den mer typiska användningen av inline-montering. Nedan är ett exempel från Linux-kärnan för bytebyte av 16-bitars och 32-bitarsnummer för en ARM-processor:

/* 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

Varje asm-sektion använder variabeln x som sin ingångs- och utgångsparameter. C-funktionen returnerar sedan det manipulerade resultatet.

Med det utökade asm-formatet kan gcc optimera monteringsinstruktionerna i ett asm-block enligt samma regler som det använder för att optimera C-kod. Om du vill att ditt asmavsnitt ska förbli orört använder du det volatile nyckelordet för asmavsnittet.

gcc Inline-montering i makron

Vi kan lägga monteringsinstruktioner i ett makro och använda makroet som du skulle kalla en funktion.

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

Att använda inline monteringsinstruktioner inbäddade i C-kod kan förbättra körningstiden för ett program. Detta är mycket användbart i tidskritiska situationer som kryptografiska algoritmer som AES. Till exempel för en enkel skiftoperation som behövs i AES-algoritmen kan vi ersätta en direkt Rotate Right monteringsinstruktion med C shift-operatör >> .

I en implementering av 'AES256', i funktionen 'AddRoundKey ()' har vi några uttalanden som denna:

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

De tilldelar helt enkelt bitvärdet för w till subkey .

Vi kan ändra tre skift + tilldela och ett tilldela C-uttryck med bara en Rotate Right operation.

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

Det slutliga resultatet är exakt samma.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow