我有点惊讶我找不到这方面的很多信息。
如果我们想保存/恢复通用寄存器的值,我们可以使用pushad
/ popad
。
是否有类似的方法来保存/恢复xmm寄存器的 ALL ?
答案 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
。