保存xmm寄存器的值

时间:2017-04-12 00:43:44

标签: assembly x86

我有点惊讶我找不到这方面的很多信息。

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

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

1 个答案:

答案 0 :(得分:4)

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

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

你需要最新的CPU。

;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:手动将regs保存到内存

另一种选择是简单地将寄存器的内容存储在内存中。 我们假设您要将数据存储在堆栈中 这种方法适用于任何CPU,并且更加便携,在接下来的十年中至少这将是我最喜欢的方法。

快速且脏的未对齐保存

;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.

如果要保存大量寄存器,则需要在32字节边界上对齐堆栈:

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

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

始终先将任何ymm寄存器和任何其他寄存器推送(按大小的递减顺序),这样堆栈将始终以最佳方式对齐。

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