【问题标题】:Move single byte from memory to xmm register as float将单个字节从内存移动到 xmm 寄存器作为浮点数
【发布时间】:2019-01-06 00:23:09
【问题描述】:

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

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

【问题讨论】:

  • 您需要将 8 位值解压缩为 32 位,然后使用例如cvtdq2ps 将 32 位 int 转换为浮点数。
  • 检查the documentation,尤其是所有标记为“转换”的说明。
  • @fuz 谢谢你的链接 - 为什么我自己找不到这个??
  • @Duke 我不知道。在你的谷歌上工作!

标签: assembly x86 sse simd


【解决方案1】:

明显的标量方式,就像您从编译器 (http://godbolt.org/) 获得的一样:

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

这在 Sandybridge-family 上总共花费 3 uops。 (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 指令。

【讨论】:

  • 太好了,它有效!还要感谢伟大的链接 - 显然我不擅长谷歌搜索......
  • @Duke:请参阅stackoverflow.com/tags/x86/info,了解更多官方文档和性能信息的有用链接。
  • 哦,是的,这些资源很多! :-) 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
相关资源
最近更新 更多