如果要将 XMM/YMM 寄存器保存到内存中,您有 2 个选项:
A:使用(F) XSAVE / (F) XRSTOR,参见:Intel x86-64 XSAVE/XRSTOR
为此,您将需要最新的 CPU。
Run Code Online (Sandbox Code Playgroud);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.
Run Code Online (Sandbox Code Playgroud)
如果您有很多寄存器要保存,您需要在 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
Run Code Online (Sandbox Code Playgroud)
始终先压入任何 ymm 寄存器,然后再压入任何其他寄存器(按大小递减顺序),这样堆栈将始终以最佳方式对齐。
请注意,pushad/popadx64 上不再支持。