Samlingsindsats

I programmering refererer inline assembler til compilerens evne til at indlejre lavniveaukode skrevet i assembler i et program skrevet på et højt niveau sprog , såsom C eller Ada . Brugen af ​​assembler-indsatser kan forfølge følgende mål:

Et eksempel på optimering og brug af specielle processorinstruktioner

Dette eksempel på assembler-indsættelse i D- programmeringssproget , som implementerer beregningen af ​​tangenten til x, bruger x86 FPU- instruktioner . Denne kode kører hurtigere end den kode, der kunne genereres af compileren. Instruktionen her bruges også fldpi, som indlæser den nærmeste taltilnærmelse for x86-arkitekturen.

// Beregn tangensen af ​​x reel tan ( reel x ) { asm { fld x [ EBP ] ; // load x fxam ; // test for ulige værdier fstsw AX ; sahf ; jc trigerr ; // x er NAN, infinity eller tom // 387'er kan håndtere denormale SC18 : fptan ; fstp ST ( 0 ) ; // dump X, som altid er 1 fstsw AX ; sahf ; jnp Lret ; // C2 = 1 (x er uden for området) // Udfør argumentreduktion for at bringe x ind i området fldpi ; fxch ; SC17 : fpreml ; fstsw AX ; sahf ; jp SC17 ; fstp ST ( 1 ) ; // fjern pi fra stakken jmp SC18 ; } trigerr : returner ægte . nan ; Lret : ; }

Eksempel på systemkald

Det er generelt ikke muligt at få direkte adgang til operativsystemet med beskyttet hukommelse. OS kører på et mere privilegeret niveau (kernetilstand) end brugeren (brugertilstand). For at fremsætte anmodninger til operativsystemet, bruges softwareafbrydelser. Sjældent sprog på højt niveau understøtter denne funktion, så systemopkaldsgrænseflader skrives ved hjælp af inline assembler [1] .

Det følgende C-eksempel indeholder en systemopkaldsgrænseflade skrevet ved hjælp af AT&T 's GNU Assembler -syntaks . Lad os først se på assembler-indsættelsesformatet ved hjælp af et simpelt eksempel:

asm ( "movl %ecx, %eax" ); /* flytter indholdet af ecx til eax */

Identifikatorerne asmog __asm__er ækvivalente. Et andet simpelt indsættelseseksempel:

__asm__ ( "movb %bh, (%eax)" ); /* flytter byten fra bh til hukommelsen, der peges af eax */

Et eksempel på implementering af systemopkaldsgrænsefladen:

ekstern int errno ; int funcname ( int arg1 , int * arg2 , int arg3 ) { int res ; __asm__ flygtig ( "int $0x80" /* lav anmodningen til OS */ : "=a" ( res ), /* returnerer resultat i eax ("a") */ "+b" ( arg1 ), /* pass arg1 i ebx ("b") */ "+c" ( arg2 ), /* pass arg2 i ecx ("c") */ "+d" ( arg3 ) /* pass arg3 i edx ("d") */ : "a" ( 128 ) /* videregive systemopkaldsnummer i eax ("a") */ : "hukommelse" , "cc" ); /* meddeler compileren, at hukommelses- og tilstandskoderne er blevet ændret */ /* Operativsystemet returnerer en negativ værdi ved fejl; * wrappers returnerer -1 ved fejl og indstiller den globale variabel errno */ if ( -125 <= res && res < 0 ) { errno = -res ; _ res = -1 ; } returner res ; }

Kritik

Siden begyndelsen af ​​det 21. århundrede er brugen af ​​assembler-indsatser i stigende grad blevet fordømt af forskellige årsager [2] [3] :

  • Moderne optimerende compilere er i stand til at generere bedre assembly-kode, end en gennemsnitlig programmør kan skrive. I sig selv kan assembler-indsatser forstyrre optimeringen af ​​andre dele af koden. Nogle tricks, der gjorde det muligt at optimere udførelsen af ​​kode på processorer fra 1980-90'erne på senere processorer, kan føre til en betydelig opbremsning i udførelsen på grund af en anden organisering af beregninger. Som med enhver optimering skal assembler-indsatser testes for at teste hypotesen om deres effektivitet. På grund af den øgede ydeevne af computersystemer kan mange optimeringer være irrelevante, og kodelæsbarhed, nem vedligeholdelse og fejlforebyggelse kommer i forgrunden.
  • Monteringskode er mere tidskrævende at skrive. Det er nemt at lave en fejl i samleindsatsen, hvilket er svært at bemærke. For eksempel understøtter assemblersprog ikke typekontrol . Allerede genereret monteringskode er sværere at vedligeholde .
  • Monteringskoden er ikke bærbar. Samlingsindsatser er berettigede for at få adgang til platformspecifikke mekanismer. Ved brug af assembler-indlæg i programmer på tværs af platforme er det nødvendigt at duplikere assembler-indlæg til forskellige platforme, og også, hvis det er muligt, beholde en alternativ implementering i et sprog på højt niveau - men denne praksis skaber problemer ved vedligeholdelse af programmet pga. behov for at foretage ændringer parallelt med flere sektioner af kode skrevet på forskellige sprog, sprog og til forskellige platforme.

Noter

  1. 1 2 "Linux-programmering" Kapitel 5. Sådan fungerer systemopkald . Åbent net. Dato for adgang: 29. september 2013. Arkiveret fra originalen 2. oktober 2013.
  2. Analyse af brugen af ​​assembler-indlæg i koden for åbne projekter . åbent net . Hentet 3. maj 2022. Arkiveret fra originalen 3. maj 2022.
  3. Årsager til, at du IKKE bør bruge inline asm . Hentet 3. maj 2022. Arkiveret fra originalen 28. april 2022.

Links