【问题标题】:Loading SSE registers加载 SSE 寄存器
【发布时间】:2012-03-26 20:06:39
【问题描述】:

我正在为操作系统开发课做家庭作业。一项任务是在中断时保存 SSE 寄存器的上下文。现在,保存和恢复上下文很容易(fxsave/fxsave)。但我有测试的问题。我想将相同的样本日期放入其中一个寄存器,但我得到的只是错误中断 6。这是代码:

// load some SSE registers
struct Vec4 {
    int x, y, z, w;
} vec = { 0, 1, 2, 3 }; 


asm volatile (  "movl %0, %%eax"
        : /* no output */
        : "r"( &vec )
        :
        );
asm volatile ( "movups (%eax), %xmm0" );

我在互联网上搜索解决方案。我得到的只是它可能与有效地址空间有关。但我不知道它是什么。

【问题讨论】:

  • 我需要做什么才能完成这项工作:asm volatile ( "movups (0x0), %xmm0" );

标签: gcc assembly sse osdev


【解决方案1】:

您需要使用内存操作数作为内联汇编中的约束。这比自己生成地址(正如您尝试使用 & 运算符)并加载到寄存器中要好得多,因为如果地址是 rip 相对地址或可重定位地址,后者将不起作用。

asm volatile ( "movups %0, %%xmm0" 
        : /* no output */
        : "m"( vec )
        :
        );

并且你需要在注册名称前使用两个“%%”。

在此处阅读有关 gcc 约束的更多信息:http://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html#Simple-Constraints。标题有点误导,因为这个概念远非简单:-)

【讨论】:

  • 对我来说听起来像是 XY 问题。
  • 我需要的是一种从结构加载 xmm* 寄存器、生成中断、保存 xmm* 寄存器的上下文、通过编辑 xmm* 寄存器的状态来处理中断、恢复上下文以及从注册以查看上下文保存/恢复是否成功。执行此操作的操作系统是一些基本操作系统,仅支持在 GRUB 将执行传递给操作系统后控制系统,通过直接访问 GPU 内存和处理中断(这是我的任务)将文本打印到屏幕。
  • 我唯一的问题是,每当我尝试使用 xmm* 寄存器做某事时,我都会收到中断 6。 (处理器支持 SSE,ofc)
  • 更有趣的是,使用 fxrstor 加载有效,而使用 movups 加载无效...我尝试对齐数据但没有任何帮助。
【解决方案2】:

我发现了问题所在。必须通过设置 CR0 和 CR4 寄存器中的一些标志来启用 SSE 指令的执行。更多信息在这里:http://wiki.osdev.org/SSE

【讨论】:

  • OSDev的第一条规则:先启用,后使用。请记住,处理器以 16 位实模式启动,几乎所有功能都被禁用 - 每个处理器功能和扩展(在开发 8086 时不存在)在启动时都被禁用。
【解决方案3】:

你让这种方式变得比它需要的更难 - 只需使用 *mmintrin.h 标头中的内在函数,例如

#include <emmintrin.h>

__m128i vec = _mm_set_epi32(3, 2, 1, 0);

如果您需要将其放入特定的 XMM 寄存器中,则以上面的示例为起点,然后生成 asm,例如使用 gcc -S 并使用生成的 asm 作为您自己代码的模板。

【讨论】:

  • 谢谢,我知道 *mmintrin.h 头文件,但我不能使用这些头文件。我正在使用专门为这个项目制作的基于 Linux 的定制操作系统。我从您的示例中查看了汇编代码。这很有帮助。现在我知道如何使用汇编程序在 xmm* 中加载数据。但是有没有办法像我尝试过的那样从结构中加载它。我需要这样的东西,所以我可以应用相同的技术从寄存器中取回数据并将其打印出来。我知道我可以通过将每个 32 位组件移动到通用寄存器并读出它们来做到这一点。但是应该有更有效的方法。
猜你喜欢
  • 1970-01-01
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
相关资源
最近更新 更多