如果您想将 XMM/YMM 寄存器保存到内存中,您有 2 个选项:
答:使用(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:手动将注册表保存到内存中
另一种选择是将寄存器的内容简单地存储在内存中。
假设您要将数据存储在堆栈中。
这种方法适用于任何 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。