首页 > 解决方案 > 将单个字节从内存移动到 xmm 寄存器作为浮点数

问题描述

如何从内存中的地址检索单个字节并将其作为浮点数移动到 xmm 寄存器中?(例如,如果地址位置有一个字节 123,我希望能够使用 sse 指令对这个值进行浮点运算,例如 123+5 等。)

我是组装新手,我希望这个问题是有道理的。我已经相当随机地尝试了几件事(例如al从那里移到第一个并移到 xmm - 但不知道如何继续转换为浮点数......);也许有人可以指出我正确的方向?

标签: assemblyx86ssesimd

解决方案


显而易见的标量方式,就像您从编译器 ( http://godbolt.org/ ) 中获得的那样:

movzx     eax,  byte [mem]         ; zero extend.  Use movsx to sign-extend
cvtsi2ss  xmm0, eax

这在 Sandybridge-family 上总共花费了 3 微秒。(cvtsi2ss是 2)。

请注意,cvtsi2ss它的设计很差,并合并到 XMM0 的旧值中,因此它具有错误的依赖关系。gcc 倾向于pxor xmm0,xmm0首先打破依赖关系,但如果 XMM0 最近没有使用,那么你应该没问题。使用 AVX,您可以将一个 XMM 寄存器归零,然后重复将其用作多个转换的安全无依赖源。

vxorps   xmm0, xmm0, xmm0

;then repeated multiple times:
vcvtsi2ss  xmm1, xmm0, eax       ; xmm1 is write-only, no false dep

如果 SSE4.1 可用,并且可以读取超过所需字节的 3 个字节(不会因读取未映射的页面而出现段错误,也不会因缓存行或页面拆分而出现性能问题),那么您可以这样做:

pmovzxbd    xmm0,  dword [mem]       ; byte->dword packed zero extend
cvtdq2ps    xmm1,  xmm0              ; packed-convert of int32 to float

这在 SnB 系列上总共花费 2 个微指令:pmovzx/sx使用 XMM 目标可以微熔断负载。(但不是 AVX2 YMM 版本)。(http://agner.org/optimize/)。

当然,如果您真的转换 4 个连续字节,这非常好。cvt否则,如果您有多次转换,您可能会随机设置指令。


推荐阅读