这是编写一个返回9x寄存器值的函数的正确方法吗?

时间:2015-07-22 19:56:42

标签: assembly nasm

这可以用于返回RAX寄存器中9倍的内容吗?

Times9:
    mov rbp, rax
    add rax, rax  ;(x2)
    add rax, rax  ;(x4)
    add rax, rax  ;(x8)
    add rax, rbp  ;(x9)
    push rax
    ret

3 个答案:

答案 0 :(得分:5)

您可以使用LEA

在一条指令中乘以9
lea rax,[rax + rax*8]   ; rax *= 9

注意:我还没有做过任何基准测试,看看这是否比其他方法更快。无论如何,它的代码更少。

答案 1 :(得分:1)

这是一个有效的方法,但您的具体实施有一些问题。

首先,它会不必要地破坏寄存器。尽可能减少副作用是一个很好的经验法则,例如(在这种情况下)改变rbp。当然,如果您特意陈述某些寄存器可能已损坏,您可以通过不保存它们来实现更快的速度。

其次,rbp并不是真正正确的寄存器,因为它在堆栈帧管理的许多调用约定中使用。我使用其他通用寄存器之一,例如rbx

第三,你拥有的例程几乎肯定会崩溃,因为条目中的堆栈内容与退出时相同。你最后按rax然后尝试返回,这意味着返回地址几乎肯定是 CPU所期望的。

为此,我会将其重写为:

Times9:
    push rbx           ; save 

    push rax           ; rax -> rbx
    pop  rbx

    add  rax, rax      ; double
    add  rax, rax      ; quadruple
    add  rax, rax      ; octuple
    add  rax, rbx      ; now nine times

    pop  rbx           ; restore and return
    ret

现在,请记住,可以通过向左移动三位来完成乘八运算,例如:

    shl  rax, 3

但是,如果代码简洁是您的主要考虑因素,则可以使用MULIMUL完成整数乘以九,这样您可能需要考虑这一点。

答案 2 :(得分:-1)

是的。如果您正在考虑性能,可以这样做

     Times9: 
         mov rbp, rax
         shl rax, 3 // left shift by 3: 8x
         add rax, rbp
         push rax
         ret