Montážní vložka
V programování inline assembler odkazuje na schopnost kompilátoru vložit nízkoúrovňový kód napsaný v assembleru do programu napsaného v jazyce vysoké úrovně , jako je C nebo Ada . Použití vložek assembleru může sledovat následující cíle:
- Optimalizace : Pro tento účel je manuálně zapsán kód sestavení, aby se implementovaly výkonově kritické části algoritmu . To umožňuje programátorovi využít jejich vynalézavosti v maximální míře, aniž by byl omezován konstrukcemi kompilátoru.
- Přístup k instrukcím specifickým pro procesor : Některé procesory podporují speciální instrukce, jako je porovnat s exchange a test-and-set , instrukce, které lze použít k implementaci semaforů nebo jiných synchronizačních a zamykacích primitiv. Prakticky všechny moderní procesory mají tyto nebo podobné instrukce, protože jsou vyžadovány pro implementaci multitaskingu . Speciální instrukce lze nalézt v instrukčních systémech následujících procesorů: SPARC VIS , Intel MMX a SSE , Motorola AltiVec .
- Systémová volání : Programovací jazyky na vysoké úrovni jen zřídka poskytují přímý způsob, jak provádět systémová volání, k tomuto účelu se používá assembler [1] .
Příklad optimalizace a použití speciálních instrukcí procesoru
Tento příklad vkládání assembleru v programovacím jazyce D , který implementuje výpočet tečny x, používá instrukce x86 FPU . Tento kód běží rychleji než kód, který by mohl vygenerovat kompilátor. Také je zde použita instrukce , která načte nejbližší číselnou aproximaci pro architekturu x86.
fldpi
// Vypočtěte tangens x
real tan ( real x )
{
asm
{
fld x [ EBP ] ; // načíst x
fxam ; // test na liché hodnoty
fstsw AX ;
sahf ;
jc trigerr ; // x je NAN, nekonečno nebo prázdné
// 387 si poradí s denormaly
SC18 : fptan ;
fstp ST ( 0 ) ; // výpis X, což je vždy 1
fstsw AX ;
sahf ;
jnp Lret ; // C2 = 1 (x je mimo rozsah)
// Proveďte redukci argumentu, aby se x dostalo do rozsahu
fldpi ;
fxch ;
SC17 : fprem1 ;
fstsw AX ;
sahf ;
jp SC17 ;
fstp ST ( 1 ) ; // odebrání pi ze zásobníku
jmp SC18 ;
}
trigerr :
return real . nan ;
Lret :
;
}
Příklad systémového volání
Přímý přístup k operačnímu systému obecně není s chráněnou pamětí možný. OS běží na privilegovanější úrovni (režim jádra) než uživatel (režim uživatele). K odesílání požadavků na OS se používají softwarová přerušení. Zřídka jazyky na vysoké úrovni podporují tuto funkci, takže rozhraní systémových volání jsou psána pomocí inline assembleru [1] .
Následující příklad C obsahuje rozhraní systémového volání napsané pomocí syntaxe GNU Assembler společnosti AT&T . Nejprve se podívejme na formát vložení assembleru na jednoduchém příkladu:
asm ( "movl %ecx, %eax" ); /* přesune obsah ecx do eax */
Identifikátory asma __asm__jsou ekvivalentní. Další jednoduchý příklad vložení:
__asm__ ( "movb %bh, (%eax)" ); /* přesune bajt z bh do paměti označené eax */
Příklad implementace rozhraní systémového volání:
extern int errno ;
int název funkce ( int arg1 , int * arg2 , int arg3 )
{
int res ;
__asm__ volatilní (
"int $0x80" /* odešle požadavek na OS */
: "=a" ( res ), /* vrátí výsledek v eax ("a") */
"+b" ( arg1 ), /* předat arg1 v ebx ("b") */
"+c" ( arg2 ), /* předat arg2 v ecx ("c") */
"+d" ( arg3 ) /* předat arg3 v edx ("d") */
: "a" ( 128 ) /* předání systémového telefonního čísla v eax ("a") */
: "paměť" , "cc" ); /* oznámí kompilátoru, že paměť a stavové kódy byly upraveny */
/* Operační systém vrátí zápornou hodnotu při chybě;
* wrappery vrátí -1 při chybě a nastaví globální proměnnou errno */
if ( -125 <= res && res < 0 ) {
errno = -res ; _
res = -1 ;
} return res ;
}
Kritika
Od začátku 21. století je používání assemblerových vložek z různých důvodů stále více odsuzováno [2] [3] :
- Moderní optimalizační kompilátory jsou schopny generovat lepší assembler, než dokáže napsat průměrný programátor. Vložky assembleru mohou samy o sobě zasahovat do optimalizace jiných částí kódu. Některé triky, které umožnily optimalizovat provádění kódu na procesorech 80. až 90. let na pozdějších procesorech, mohou vést k výraznému zpomalení provádění v důsledku odlišné organizace výpočtů. Stejně jako u každé optimalizace je třeba otestovat vložky assembleru, aby bylo možné otestovat hypotézu o jejich účinnosti. Vzhledem ke zvýšení výkonu výpočetních systémů může být mnoho optimalizací irelevantních a do popředí se dostává čitelnost kódu, snadná údržba a prevence chyb.
- Sestavení kódu je časově náročnější na psaní. Ve vložce assembleru je snadné udělat chybu, které je těžké si všimnout. Jazyk symbolických instrukcí například nepodporuje kontrolu typu . Již vygenerovaný kód sestavení je náročnější na údržbu .
- Kód sestavy není přenosný. Montážní vložky jsou opodstatněné pro přístup k mechanismům specifickým pro platformu. Při použití assemblerových insertů v multiplatformních programech je nutné duplikovat assemblerové inserty pro různé platformy a také, pokud je to možné, ponechat alternativní implementaci v jazyce vyšší úrovně – tato praxe však vytváří problémy při údržbě programu kvůli potřeba provádět změny paralelně v několika částech kódu napsaných v různých jazycích. jazycích a pro různé platformy.
Poznámky
- ↑ 1 2 "Programování Linuxu" Kapitola 5. Jak fungují systémová volání . Opennet. Datum přístupu: 29. září 2013. Archivováno z originálu 2. října 2013. (neurčitý)
- ↑ Analýza použití assemblerových vložek v kódu otevřených projektů . opennet . Získáno 3. května 2022. Archivováno z originálu dne 3. května 2022. (neurčitý)
- ↑ Důvody, proč byste NEMĚLI používat inline asm . Získáno 3. května 2022. Archivováno z originálu dne 28. dubna 2022. (neurčitý)
Odkazy