纯粹为了短时间保存而推送寄存器可以吗?
Is it okay to push registers purely for preservation for short periods of time?
我已经学习 NASM 几个星期了。一切顺利 - 我现在一直专注于 64 位。
早些时候我注意到当我执行 mul
指令时 rdx
寄存器被弄乱了。
基本上,代码类似于:
; Code using RDX is up here
mov rax,2
mov rbx,10
mul rbx
; Code using RDX again is down here .. but the value is now zero
所以,显然黑索金与mul
有关。为了解决这个问题,我将代码更改为:
push rdx
mov rax,2
mov rbx,10
mul rbx
pop rdx
基本上,我在 mul
指令之前将寄存器保存在堆栈中...然后将其弹出(因为我不关心 [=12] 中的值=] .. 我希望它成为我想要的样子)。
我的问题是:这样做可以吗?常见吗?很久没做这个了。。感觉有点奇怪。
我可以改为使用局部变量而不是寄存器来进行某些计算..这可能会解决问题而无需在这么短的时间内将其推入堆栈..但问题仍然存在.
额外问题:是否有某个地方完全涵盖了这些指令在 64 位上下文中的作用?我似乎找不到可以用简单的英语实际告诉我在 mul
指令之后 rdx
寄存器发生了什么的参考资料。
Is there somewhere that has full coverage of what these instructions do in a 64-bit context? I can't seem to find a reference that actually tells me in plain English what is happening to the rdx register after the mul instruction
Intel's manual 说得很清楚了:
MUL r/m64 Unsigned multiply (RDX:RAX ← RAX ∗ r/m64).
也就是说,RDX
将保留乘积的最高 64 位。
至于你的主要问题;如果可以的话,使用不同的寄存器。如果不能,则需要以某种方式备份 RDX
的值,使用堆栈是一种简单的方法。
Pushing/popping 在这种情况下是完全合理的。
为什么不使用 imul rax,rbx
甚至 imul rax,10
?这些 完全不会与 RDX 混淆。
并不总是好的。例如在 win64 上,不在 prolog 或 epilog 中的随机 push 和 pops 失败展开,如果在堆栈指针恢复正常之前发生异常,事情就会变得非常错误。
虽然在这种情况下并不是真的有必要,因为您可以相乘而不影响 rdx
。
我已经学习 NASM 几个星期了。一切顺利 - 我现在一直专注于 64 位。
早些时候我注意到当我执行 mul
指令时 rdx
寄存器被弄乱了。
基本上,代码类似于:
; Code using RDX is up here
mov rax,2
mov rbx,10
mul rbx
; Code using RDX again is down here .. but the value is now zero
所以,显然黑索金与mul
有关。为了解决这个问题,我将代码更改为:
push rdx
mov rax,2
mov rbx,10
mul rbx
pop rdx
基本上,我在 mul
指令之前将寄存器保存在堆栈中...然后将其弹出(因为我不关心 [=12] 中的值=] .. 我希望它成为我想要的样子)。
我的问题是:这样做可以吗?常见吗?很久没做这个了。。感觉有点奇怪。
我可以改为使用局部变量而不是寄存器来进行某些计算..这可能会解决问题而无需在这么短的时间内将其推入堆栈..但问题仍然存在.
额外问题:是否有某个地方完全涵盖了这些指令在 64 位上下文中的作用?我似乎找不到可以用简单的英语实际告诉我在 mul
指令之后 rdx
寄存器发生了什么的参考资料。
Is there somewhere that has full coverage of what these instructions do in a 64-bit context? I can't seem to find a reference that actually tells me in plain English what is happening to the rdx register after the mul instruction
Intel's manual 说得很清楚了:
MUL r/m64 Unsigned multiply (RDX:RAX ← RAX ∗ r/m64).
也就是说,RDX
将保留乘积的最高 64 位。
至于你的主要问题;如果可以的话,使用不同的寄存器。如果不能,则需要以某种方式备份 RDX
的值,使用堆栈是一种简单的方法。
Pushing/popping 在这种情况下是完全合理的。
为什么不使用 imul rax,rbx
甚至 imul rax,10
?这些 完全不会与 RDX 混淆。
并不总是好的。例如在 win64 上,不在 prolog 或 epilog 中的随机 push 和 pops 失败展开,如果在堆栈指针恢复正常之前发生异常,事情就会变得非常错误。
虽然在这种情况下并不是真的有必要,因为您可以相乘而不影响 rdx
。