首页 > 解决方案 > 如何获取特定 xmm 寄存器的位?

问题描述

所以我想获取特定 xmm 寄存器的值或状态。这主要用于崩溃日志或只是为了查看寄存器的状态以进行调试。我试过这个,但它似乎不起作用:

#include <x86intrin.h>
#include <stdio.h>

int main(void) {

     register __m128i my_val __asm__("xmm0");
     __asm__ ("" :"=r"(my_val));
     printf("%llu %llu\n", my_val & 0xFFFFFFFFFFFFFFFF, my_val << 63);
  return 0;
}

据我所知,store相关的内在函数不会将其__m128i视为 POD 数据类型,而是将其视为对 xmm 寄存器之一的引用。

如何获取和访问存储在__m128i64 位整数中的位?还是我__asm__上面的工作?

标签: cgccx86sseinline-assembly

解决方案


如何获取和访问存储在__m128i64 位整数中的位?

您必须将__m128i向量转换为一对uint64_t变量。您可以使用转换内在函数来做到这一点:

uint64_t lo = _mm_cvtsi128_si64(my_val);
uint64_t hi = _mm_cvtsi128_si64(_mm_unpackhi_epi64(my_val, my_val));

...或者虽然记忆:

uint64_t buf[2];
_mm_storeu_si128((__m128i*)buf, my_val);
uint64_t lo = buf[0];
uint64_t hi = buf[1];

后者在性能方面可能更差,但如果您打算仅将其用于调试,则可以。如果需要,适应不同大小的元素也很简单。

还是我__asm__上面的工作?

不,它没有。“=r”输出约束不允许向量寄存器,例如作为xmm0输出传递的,它只允许通用寄存器。没有通用寄存器是 128 位宽的,所以 asm 语句没有意义。

另外,我应该注意my_val << 63以错误的方式改变价值。如果您想输出假设的 128 位值的高半部分,那么您应该向右移动,而不是向左移动。除此之外,向量的移位要么没有实现,要么作用于向量的每个元素,而不是整个向量,这取决于编译器。但这部分没有实际意义,就像上面的代码一样,您不需要任何转换来输出两半。


推荐阅读