我想在C中的FPU上执行除法(使用整数值):
float foo;
uint32_t *ptr1, *ptr2;
foo = (float)*(ptr1) / (float)*(ptr2);
在NASM中(来自通过GCC编译的对象)具有以下表示形式:
mov rax, QWORD [ptr1]
mov eax, DWORD [rax]
mov eax, eax
test rax, rax
js ?_001
pxor xmm0, xmm0
cvtsi2ss xmm0, rax
jmp ?_002
?_001:
mov rdx, rax
shr rdx, 1
and eax, 01H
or rdx, rax
pxor xmm0, xmm0
cvtsi2ss xmm0, rdx
addss xmm0, xmm0
?_002:
mov rax, QWORD [ptr2]
; ... for ptr2 pattern repeats
_001下的“黑魔法”是什么意思? cvtsi2ss是否足以从整数转换为浮点数?
最佳答案
一般而言,cvtsi2ss可以解决问题-将标量整数(其他来源将其双字整数转换为单标量,但我的命名与其他 vector ins一致)为标量单(浮点数)。但它期望带符号的整数。
所以这段代码
mov rdx, rax
shr rdx, 1
and eax, 01H
or rdx, rax
pxor xmm0, xmm0
cvtsi2ss xmm0, rdx
addss xmm0, xmm0
帮助将无符号转换为带符号(请注意js跳转-如果设置了符号位,则将执行此代码-否则将被跳过)。 uint32_t的值大于0x7FFFFFFF时设置符号。
因此,“魔术”代码可以做到:
mov rdx, rax ; move value from ptr1 to edx
shr rdx, 1 ; div by 2 - logic shift not arithmetic because ptr1 is unsigned
and eax, 01H ; save least significant bit
or rdx, rax ; move this bit to divided value to someway fix rounding errors
pxor xmm0, xmm0
cvtsi2ss xmm0, rdx
addss xmm0, xmm0 ; add to itself = multiply by 2
我不确定您使用什么编译器和编译选项-GCC只是简单地
cvtsi2ssq xmm0, rbx
cvtsi2ssq xmm1, rax
divss xmm0, xmm1
希望对您有所帮助。
关于c - GCC在将整数强制转换为 float 期间生成的FPU操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41495498/