X86 64 AT& T使用指数作为函数?

时间:2017-04-20 23:32:44

标签: assembly x86-64 exponent

我的程序正在尝试模拟使用指数的函数。功能是

x * y ^ 5

我在寄存器rsi中有x,在寄存器rcx中有y

我正在尝试使用shlq%rsi,%rcx两次,这应该是y ^ 4然后只是 使用imulq让它达到y ^ 5点,但我不知道如何使用 当值在寄存器内时,函数shlq。它必须是所有在线示例中的$ number值。不知道该怎么办。感谢。

1 个答案:

答案 0 :(得分:2)

也许我错过了一些特别聪明的东西,但我无法弄清楚你为什么要尝试使用左移操作来执行取幂。你会做一个左移来实现二进制乘法(乘以2的幂)。例如,如果您想将 n 乘以2,则将 n 向左移动1.将 n 向左移动5将等效于 n ×32。

对于求幂,您需要 n × n × n ×....你不能通过左移操作得到它。你需要一个很好的旧乘法。

  

x * y 5

可以改写为:

  

x *(y * y * y * y * y)

或:

  

temp =(y * y)
  x * temp * temp * y

事实上,第三个是C编译器将第二个公式转换为什么,因为它是一个基本的优化,可以省略乘法。

假设您在x中有rsiy中有rcx,在汇编中,这将是:

movq   %rcx, %rax   ; make a copy of 'y'
imulq  %rcx, %rax   ; y * y
imulq  %rcx, %rsi   ; (y * x
imulq  %rax, %rsi   ; y * x * (y * y)
imulq  %rsi, %rax   ; y * x * (y * y) * (y * y)
ret                 ; result is in RAX

很简单,imulq在现代64位处理器上几乎和shlq一样高效。所以这不是慢代码,更重要的是,它是正确的

关于你如何通过变量计数进行转换,Jester已经在评论中回答了这个问题,但是请允许我对它进行更多的充实。 x86上的移位指令有四种基本编码(忽略操作数 size ,只看操作数 type ):

  1. 移位目的地是寄存器,源是立即/常量。
  2. 转移目标为内存且源为立即/常量的位置。
  3. 移位目的地是寄存器,源是cl寄存器。
  4. 移位目的地是内存,源是cl寄存器。
  5. 你可以通过查看documentation for one of the shift instructions来看到这一点。 (由于历史原因,还有一个特殊的编码用于移位1.这里不重要。)请注意,“源”和“目的地”在这里有点形式。 “目标”是 移位的值,以及结果最终的位置。 “来源”实际上不是来源;这只是班次计数。

    因此,您看到的大部分内容都是通过立即转移注册值,即选项#1,但您也可以通过变量转移注册值 - catch是变量必须cl注册表中。 clrcx寄存器的最低8位(字节)。

    所以如果你想这样做,请说:

      

    x * 2 y

    相当于:

      

    x<< ÿ

    x位于rsiy位于rcx,您可以将其写为:

    shlq  %cl,  %rsi
    movq  %rsi, %rax
    ret                 ; result is in RAX
    

    当然,由于移位计数必须在clcl是一个8位寄存器,移位计数永远不会大于255.这实际上不是问题,尽管,因为将64位数量移动超过63是没有意义的。