保存 xmm 寄存器的值 [英] Save value of xmm registers

查看:77
本文介绍了保存 xmm 寄存器的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点惊讶我找不到这方面的太多信息.

如果我们想保存/恢复通用寄存器的值,我们可以使用pushad/popad.

是否有类似的方法来保存/恢复 ALL 的 xmm 寄存器?

解决方案

如果您想将 XMM/YMM 寄存器保存到内存中,您有两个选择:

A:使用(F)XSAVE/(F)XRSTOR,请参阅:Intel x86-64 XSAVE/XRSTOR

为此您需要最新的 CPU.

<块引用>

;保存:移动 rdx, -1mov rax, -1 ;保存所有可能的regsxsave [位置]...一些改变寄存器的代码;恢复:移动 rdx, -1mov rax, -1xrstor [位置]

B:手动将 regs 保存到内存

另一种选择是简单地将寄存器的内容存储在内存中.假设您想将数据存储在堆栈中.
这种方法可以在任何 CPU 上运行,并且更加便携,至少在接下来的十年里,这将是我最喜欢的方法.

快速且脏的未对齐保存

;push xmm0lea rsp,[rsp-16*numOfRegsToSave] ;在栈上保留空间vmovdqu [rsp+16*0],xmm0 ;压入一个寄存器(注意未对齐!写)vmovdqu [rsp+16*1],xmm1 ;继续推......;弹出 xmm0......vmovdqu xmm1,[rsp+16*1] ;按相反顺序弹出寄存器vmovdqu xmm0,[rsp+16*0] ;首先'弹出'寄存器lea rsp,[rsp+16*numOfRegsToSave] ;然后更新堆栈.

如果您有很多寄存器要保存,您需要在 32 字节边界上对齐堆栈:

稍微快一点的代码(以一个损坏的寄存器为代价)

mov rbp,rsp ;保存栈指针和 rsp,-32 ;在 32 字节边界上对齐;推ymm0lea rsp,[rsp-32*numOfRegsToSave] ;在栈上保留空间vmovdqa [rsp+32],ymm0 ;push 一个寄存器(注意对齐!写)......;pop ymm0....vmovdqa ymm0,[rsp+32]mov rsp,rbp

总是先压入任何 ymm 寄存器,然后再压入任何其他寄存器(按大小递减顺序),这样堆栈将始终以最佳方式对齐.

请注意,x64 不再支持 pushad/popad.

I'm a little surprised I couldn't find much information on this.

If we want to save/restore the values of the general purpose registers we can use pushad/popad.

Is there a similar way to save/restore ALL of the xmm registers?

解决方案

If you want to save the XMM/YMM registers to memory you have 2 options:

A: use (F)XSAVE / (F)XRSTOR, see: Intel x86-64 XSAVE/XRSTOR

You'll need the latest CPU for this.

;save:
mov     rdx, -1              
mov     rax, -1                 ;save all possible regs
xsave   [location]

...some code that alters the registers
;restore:
mov     rdx, -1
mov     rax, -1
xrstor  [location]

B: manually save the regs to memory

The other option is to simply store the contents of the registers in memory. Let's assume you want to store your data on the stack.
This approach will work on any CPU and is much more portable, for the next decade at least this would be my favoured approach.

Quick and dirty unaligned save

;push xmm0
lea rsp,[rsp-16*numOfRegsToSave]          ;reserve space on the stack
vmovdqu [rsp+16*0],xmm0                   ;push a register (note unaligned! write) 
vmovdqu [rsp+16*1],xmm1                   ;keep pushing
.......

;pop xmm0
.......
vmovdqu xmm1,[rsp+16*1]                   ;pop registers in reverse order
vmovdqu xmm0,[rsp+16*0]                   ;first 'pop' the register
lea rsp,[rsp+16*numOfRegsToSave]          ;then update the stack.

If you have lots of registers to save, you'll want to align the stack on a 32 byte boundary:

Slightly faster code (at the cost of one clobbered register)

mov rbp,rsp                       ;save the stack pointer
and rsp,-32                       ;align on a 32 byte boundary
;push ymm0
lea rsp,[rsp-32*numOfRegsToSave] ;reserve space on the stack
vmovdqa [rsp+32],ymm0             ;push a register (note aligned! write)
.......

;pop ymm0
....
vmovdqa ymm0,[rsp+32]
mov rsp,rbp

Always push any ymm registers first and any other registers later (in decreasing order of size), that way the stack will always be aligned optimally.

Note that pushad/popad are no longer supported on x64.

这篇关于保存 xmm 寄存器的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆