《3D.Game.Engine.Programming》第4章都是数学计算相关的优化,大部分都是采用汇编代码,然而这本书有点老了,书上x86平台都是采用混编的方式,x64位的编译就会报出如下错误,不支持x64位,有点伤,又逼我面向百度和Google编程。
百度Google后,了解x64位需要写.asm文件,如果需要工程同时支持x86和x64位的话,需要一个宏定义_AMD64_来实现。具体的看下面代码,x86的就不再多说了,下面代码实现的功能是获取向量的长度。
#ifdef _AMD64_
f = VectorLength(this);
#else
__asm
{
mov esi, this;
movups xmm0, [esi] ;xmm0:x, y, z, w
mulps xmm0, xmm0 ;xmm0:x^2, y^2, z^2, w^2
movaps xmm1, xmm0 ;xmm1=xmm0:x^2, y^2, z^2, w^2
shufps xmm1, xmm1, 4Eh ;xmm1:z^2, w^2, x^2, y^2
addps xmm0, xmm1 ;xmm0:x^2+z^2, y^2+w^2, z^2+x^2, w^2+y^2
movaps xmm1, xmm0 ;xmm1=xmm0:x^2+z^2, y^2+w^2,z^2+x^2,w^2+y^2
shufps xmm1, xmm1, 11h ;xmm1:y^2+w^2, x^2+z^2, w^2+y^2, z^2+x^2
addps xmm0, xmm1 ;xmm0:x^2+z^2+y^2+w^2(4个都是)
sqrtss xmm0, xmm0 ;xmm0:sqrt(x^2+z^2+y^2+w^2)
movss f, xmm0 ;
}
#endif
参考百度Google到的内容开始写x64的汇编,首先是声明
extern "C" float __stdcall VectorLength(void*);
添加依赖项
创建.asm文件,Visual Studio中没有.asm后缀的文件,随便选一个改下后缀就好了。接下来按照格式写,然后把x86的代码拷过来,rcx寄存器上存储的是第一个参数,因此稍微修改下就得到下面的结果。
.code
VectorLength proc
mov rsi, rcx;
movups xmm0, [rsi] ;xmm0:x, y, z, w
mulps xmm0, xmm0 ;xmm0:x^2, y^2, z^2, w^2
movaps xmm1, xmm0 ;xmm1=xmm0:x^2, y^2, z^2, w^2
shufps xmm1, xmm1, 4Eh ;xmm1:z^2, w^2, x^2, y^2
addps xmm0, xmm1 ;xmm0:x^2+z^2, y^2+w^2, z^2+x^2, w^2+y^2
movaps xmm1, xmm0 ;xmm1=xmm0:x^2+z^2, y^2+w^2,z^2+x^2,w^2+y^2
shufps xmm1, xmm1, 11h ;xmm1:y^2+w^2, x^2+z^2, w^2+y^2, z^2+x^2
addps xmm0, xmm1 ;xmm0:x^2+z^2+y^2+w^2(4个都是)
sqrtss xmm0, xmm0 ;xmm0:sqrt(x^2+z^2+y^2+w^2)
;movq rax, xmm0;
ret;
VectorLength endp
end;
编译测试,ok,切换到x86平台,编译,报错,选中.asm文件,右键Properties(属性),在Excluded From Build中选中Yes,表示.asm文件不参与x86平台的编译。然后编译ok,x86也没问题,接着继续在x86和x64上相互切换运行,没问题。
还没学过x64的汇编,现在的写法不清楚有啥问题,等学完再来改呗。
参考文章:
https://stackoverflow.com/questions/30648007/how-can-i-move-a-int-from-xmm-register-to-eax-register
https://www.cs.uaf.edu/2017/fall/cs301/reference/nasm_vs/
https://www.cnblogs.com/iBinary/p/10959444.html
https://blog.youkuaiyun.com/Alisebeast/article/details/79875620