我已经学习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
寄存器发生了什么。
答案 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
的情况下成倍增加。