Ассемблерная вставка
Ассемблерная вставка — в программировании возможность компилятора встраивать низкоуровневый код, написанный на ассемблере, в программу, написанную на языке высокого уровня, например, Си или Ada. Использование ассемблерных вставок может преследовать следующие цели:
Пример оптимизации и использования специальных инструкций процессора
Этот пример ассемблерной вставки на языке программирования D, реализующий вычисление тангенса x, использует инструкции FPU архитектуры x86. Этот код исполняется быстрее, чем код, который мог бы быть сгенерирован компилятором. Также, здесь использована инструкция // Compute the tangent of x
real tan(real x)
{
asm
{
fld x[EBP] ; // load x
fxam ; // test for oddball values
fstsw AX ;
sahf ;
jc trigerr ; // x is NAN, infinity, or empty
// 387's can handle denormals
SC18: fptan ;
fstp ST(0) ; // dump X, which is always 1
fstsw AX ;
sahf ;
jnp Lret ; // C2 = 1 (x is out of range)
// Do argument reduction to bring x into range
fldpi ;
fxch ;
SC17: fprem1 ;
fstsw AX ;
sahf ;
jp SC17 ;
fstp ST(1) ; // remove pi from stack
jmp SC18 ;
}
trigerr:
return real.nan;
Lret:
;
}
Пример системного вызоваОбращение к операционной системе напрямую, как правило, невозможно при наличии защищенной памяти. ОС работает на более привилегированном уровне (режим ядра), чем пользователь (пользовательский режим). Для того чтобы делать запросы в ОС, используются программные прерывания. Редко языки высокого уровня поддерживают такую возможность, поэтому интерфейсы системных вызовов пишутся с использованием ассемблерных вставок[1]. Следующий пример на языке СИ содержит интерфейс системного вызова, написанный с использованием AT&T синтаксиса GNU Assembler. Для начала рассмотрим формат ассемблерной вставки на простом примере: asm("movl %ecx, %eax"); /* moves the contents of ecx to eax */
Идентификаторы __asm__("movb %bh, (%eax)"); /* moves the byte from bh to the memory pointed by eax */
Пример реализации интерфейса системного вызова: extern int errno;
int funcname(int arg1, int *arg2, int arg3)
{
int res;
__asm__ volatile(
"int $0x80" /* make the request to the OS */
: "=a" (res), /* return result in eax ("a") */
"+b" (arg1), /* pass arg1 in ebx ("b") */
"+c" (arg2), /* pass arg2 in ecx ("c") */
"+d" (arg3) /* pass arg3 in edx ("d") */
: "a" (128) /* pass system call number in eax ("a") */
: "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */
/* The operating system will return a negative value on error;
* wrappers return -1 on error and set the errno global variable */
if (-125 <= res && res < 0) {
errno = -res;
res = -1;
}
return res;
}
КритикаС начала XXI века применение ассемблерных вставок всё чаще осуждается по множеству причин[2][3]:
См. такжеПримечания
Ссылки |