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:
- Optimering : Til dette formål skrives assembly-koden manuelt for at implementere de mest ydeevnekritiske dele af algoritmen . Dette giver programmøren mulighed for at bruge deres opfindsomhed i det fulde omfang, uden at være begrænset af compiler-konstruktioner.
- Adgang til processorspecifikke instruktioner : Nogle processorer understøtter specielle instruktioner, såsom sammenligning med udveksling og test-og-sæt , instruktioner, der kan bruges til at implementere semaforer eller andre synkroniserings- og låseprimitiver. Stort set alle moderne processorer har disse eller lignende instruktioner, da de er nødvendige for at implementere multitasking . Særlige instruktioner kan findes i instruktionssystemerne til følgende processorer: SPARC VIS , Intel MMX og SSE , Motorola AltiVec .
- Systemkald : Programmeringssprog på højt niveau giver sjældent en direkte måde at foretage systemkald på, monteringskode bruges til dette formål [1] .
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 2 "Linux-programmering" Kapitel 5. Sådan fungerer systemopkald . Åbent net. Dato for adgang: 29. september 2013. Arkiveret fra originalen 2. oktober 2013. (ubestemt)
- ↑ Analyse af brugen af assembler-indlæg i koden for åbne projekter . åbent net . Hentet 3. maj 2022. Arkiveret fra originalen 3. maj 2022. (ubestemt)
- ↑ Årsager til, at du IKKE bør bruge inline asm . Hentet 3. maj 2022. Arkiveret fra originalen 28. april 2022. (ubestemt)
Links