В ядре вы не должны использовать float
вообще (используйте lookup tables и умножайтесь на коэффициенты, чтобы сохранить точность на операциях деления). В пользовательском пространстве все операции с типом float
на RHS приведут к использованию инструкции FPU. Если у вас есть 2 целых числа на RHS, но присваивание результата float (на LHS) - вы закончите с целыми операциями, но также с литьем в инструкцию по плаванию (например, cvtsi2ss
).
На самом деле очень легко ответить на ваш вопрос, просто глядя на дизассемблирование для соответствующего кода на языке C.
код C (сборка с gcc -Wall -O0 -g main.c
):
int main(void)
{
volatile float f1, f2;
volatile int i;
f1 = i * 356;
f2 = f1 * f2;
return 0;
}
Разберите (с использованием objdump -DS a.out
):
int main(void)
{
4004b6: 55 push %rbp
4004b7: 48 89 e5 mov %rsp,%rbp
volatile float f1, f2;
volatile int i;
f1 = i * 356;
4004ba: 8b 45 f4 mov -0xc(%rbp),%eax
4004bd: 69 c0 64 01 00 00 imul $0x164,%eax,%eax
4004c3: 66 0f ef d2 pxor %xmm2,%xmm2
4004c7: f3 0f 2a d0 cvtsi2ss %eax,%xmm2
4004cb: 66 0f 7e d0 movd %xmm2,%eax
4004cf: 89 45 fc mov %eax,-0x4(%rbp)
f2 = f1 * f2;
4004d2: f3 0f 10 4d fc movss -0x4(%rbp),%xmm1
4004d7: f3 0f 10 45 f8 movss -0x8(%rbp),%xmm0
4004dc: f3 0f 59 c8 mulss %xmm0,%xmm1
4004e0: 66 0f 7e c8 movd %xmm1,%eax
4004e4: 89 45 f8 mov %eax,-0x8(%rbp)
return 0;
4004e7: b8 00 00 00 00 mov $0x0,%eax
}
Здесь вы можете увидеть, что:
- при умножении числа на целое число , но присваивая результат float, он приводит к команде imul (целочисленное умножение), но также и для команды cvtsi2ss (преобразование в float).
- при умножении 2 поплавков, это приводит к mulss инструкции, которая поплавок множительной
В принципе вы можете увидеть сразу, если FPU участвует инструкция работает на регистрах FPU, как %xmm0
, %xmm1
и т.д.
Наверное, нет , но это зависит от аппаратного обеспечения. – Barmar
Я не верю, что операция плавания доступна в ядре –
Это зависит. Если 'g' был сохранен в регистре FPU, то, очевидно, будет использоваться FPU. –