可以在短时间内将寄存器纯粹用于保存吗?

时间:2015-01-21 11:32:24

标签: assembly 64-bit nasm x86-64

我已经学习NASM几周了。一切进展顺利 - 我现在一直专注于64位。

之前我注意到rdx寄存器在执行mul指令时被搞乱了。

基本上,代码与此类似:

; 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

所以,显然RDX与mul有关。为了解决这个问题,我将代码更改为:

push rdx
mov rax,2
mov rbx,10

mul rbx

pop rdx

基本上,我在mul指令之前保留堆栈上的寄存器,然后再将它弹回(因为我不关心{{1}中的值我希望它成为我想要的东西。)

我的问题是:这可以吗?这很常见吗?我已经很久没这么做了......但感觉有点奇怪。

我可以使用局部变量来进行一些计算而不是寄存器..这可能会解决问题而不需要在这么短的时间内将其推入堆栈。但问题仍然存在。 / p>

奖金问题:是否有某些地方完全覆盖了这些指令在64位上下文中的作用?我似乎找不到一个引用,它实际上用简单的英语告诉我在rdx指令之后rdx寄存器发生了什么。

3 个答案:

答案 0 :(得分:3)

  

是否有某些地方完全覆盖了这些指令在64位上下文中的作用?我似乎无法找到一个实际上用简单的英语告诉我在mul指令之后rdx寄存器发生了什么的引用

Intel's manual非常明确地说明了这一点:

MUL r/m64   Unsigned multiply (RDX:RAX ← RAX ∗ r/m64).

也就是说,RDX将保留产品中最重要的64位。

至于你的主要问题;如果可以的话,使用不同的注册表。如果你不能,那么你需要以某种方式备份RDX的值,并且使用堆栈是一种简单的方法。

答案 1 :(得分:1)

在这种情况下,推/弹是完全合理的。

为什么不使用imul rax,rbx甚至imul rax,10?这些根本不会与RDX混乱。

答案 2 :(得分:1)

并不总是好的。例如在win64上,不在prolog或epilog中的随机推送和弹出失败,如果在堆栈指针恢复正常之前发生异常,则会出现问题。

但在这种情况下并不是必需的,因为你可以在不影响rdx的情况下成倍增加。