[汇编]汇编学习笔记(4):SHUFPS(洗牌)指令

        《3D.Game.Engine.Programming》书上刚看到一个SHUFPS指令。这个SHUFPS指令类似洗牌功能,这个指令的功能还是比较难理解的。自己多次测试和百度Google后,大致理解这个指令的功能,记录一下。
先借用一篇文章的内容:文章地址


        《3D.Game.Engine.Programming》书上的代码例子是SHUFPS XMM0, XMM1, 9Ch,这个9Ch表示的是16进制,等于10011100。刚开始这段文字一直没理解,看了上面这张图,就比较好理解了。

        不用寄存器来介绍,用数组来举例:有2个长度为4的数组,从中随机选择数据生成一个新的长度为4的数组,这就是作者一直在说的洗牌功能,但是有个注意点,就是新生成的数组前2个数据是用第一个数组上的数据,后2个数据是用第2个数组上的数据。
        但到底是用数组上那个数据呢?00~11,啥玩意啊,好难记啊。经过代码测试,大致理解00~11的功能,类似数组的索引,00转换成10进制是0,01转换成10进制是1,10转换成10进制是2,11转换成10进制是3。再结合上面写的数组例子,就很好知道9Ch这个功能了,就是洗牌的规则。PS:在学汇编的时候,教程上说需要背下16进制到2进制的转换,很难记,大脑反应不过来。


        用代码来说明,因为在游戏开发中,4个float的值很容易想到是向量,这边就不采用数组,直接用向量来测试。数据结构还是上一篇的Vector结构
        比如现在有2个4维向量:(1.0f, 2.0f, 3.0f, 4.0f),(5.0f, 6.0f, 7.0f, 8.0f),想生成一个新的向量(1.0f, 4.0f, 6.0f, 7.0f)。这里得说明一下,如果是从这种结构看的话,左边是低位,右边是高位。分析新生成的向量,因为1.0f和4.0f在低位,所以(1.0f, 2.0f, 3.0f, 4.0f)是在源寄存器上,(5.0f, 6.0f, 7.0f, 8.0f)就在目的寄存器上。1.0f在(1.0f, 2.0f, 3.0f, 4.0f)的索引是0(2进制是00),4.0f在(1.0f, 2.0f, 3.0f, 4.0f)的索引是3(2进制是11),6.0f在(5.0f, 6.0f, 7.0f, 8.0f)的索引是1(2进制是01),7.0f在(5.0f, 6.0f, 7.0f, 8.0f)的索引是2(2进制是10)。好,把得到的4个索引数据拼接一下,洗牌规则就是10 01 11 00(左边是高位,右边是低位)。PS:如果我想生成一个新的向量(6.0f, 7.0f, 1.0f, 4.0f),洗牌规则不变,只交换2个寄存器的位置能实现吗?不用代码测试,按照我上面一样去推断。

        代码和结果放一下,还好支持2进制,不然放个16进制上去,还得转换下。如果理解上面的内容话,也应该猜到在何时会用到这个功能吧,效率不要太高啊。
代码:


结果:

        书上也介绍了SHUFPS指令的一个案例:求4维向量的长度,我就不再做推导了。在汇编代码中,每一步指令后面我都注释了相应的结果。

代码:

	float Length()
	{
		float f = 0.0f;
		DWORD currentTime, deltaTime;
		float  forTimes = 100000000;
		currentTime = timeGetTime();
		for(int i = 0; i < forTimes; ++i)
			f = (float)sqrt(x * x + y * y + z * z);
		deltaTime = timeGetTime() - currentTime;
		std::cout << "[C++]deltaTime: " << deltaTime << std::endl;

		f = 0.0f;

		currentTime = timeGetTime();
		for (int i = 0; i < forTimes; ++i)
		{
			w = 0.0f;
			__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			;
			}
			w = 1.0f;
		}
		deltaTime = timeGetTime() - currentTime;
		std::cout << "[Assemble]deltaTime: " << deltaTime << std::endl;

		return f;
	}

100000000多次C++执行的时间和汇编代码执行所需要的时间:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值