В программировании, ассемблерной вставкой называют возможность компилятора встраивать низкоуровневый код, написанный на ассемблере, в программу, написанную на языке высокого уровня, например, Си или Ada. Использование ассемблерных вставок может преследовать следующие цели:
Этот пример ассемблерной вставки на языке программирования D, реализующий вычисление тангенса x, использует инструкции FPU архитектуры x86. Этот код исполняется быстрее, чем код, который мог бы быть сгенерирован компилятором. Также, здесь использована инструкция fldpi
, которая загружает наиболее близкую аппроксимацию числа
для архитектуры 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
и __asm__
эквивалентны. Другой пример простой вставки:
__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;
}
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .