我的程序正在尝试模拟使用指数的函数。功能是
x * y ^ 5
我在寄存器rsi中有x,在寄存器rcx中有y
我正在尝试使用shlq%rsi,%rcx两次,这应该是y ^ 4然后只是 使用imulq让它达到y ^ 5点,但我不知道如何使用 当值在寄存器内时,函数shlq。它必须是所有在线示例中的$ number值。不知道该怎么办。感谢。
答案 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
中有rsi
,y
中有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 ):
cl
寄存器。cl
寄存器。你可以通过查看documentation for one of the shift instructions来看到这一点。 (由于历史原因,还有一个特殊的编码用于移位1.这里不重要。)请注意,“源”和“目的地”在这里有点形式。 “目标”是 移位的值,以及结果最终的位置。 “来源”实际上不是来源;这只是班次计数。
因此,您看到的大部分内容都是通过立即转移注册值,即选项#1,但您也可以通过变量转移注册值 - catch是变量必须在cl
注册表中。 cl
是rcx
寄存器的最低8位(字节)。
所以如果你想这样做,请说:
x * 2 y
相当于:
x<< ÿ
且x
位于rsi
且y
位于rcx
,您可以将其写为:
shlq %cl, %rsi
movq %rsi, %rax
ret ; result is in RAX
当然,由于移位计数必须在cl
,cl
是一个8位寄存器,移位计数永远不会大于255.这实际上不是问题,尽管,因为将64位数量移动超过63是没有意义的。