假设我已经在装配机器中实现了除MUL(多个)指令之外的所有ADD,AND,SHF,JUMP,BR,LDW,LDB(加载字加载字节......)........现在我想编写汇编代码来操作MUL指令,该指令接收存储在0x4000(a)和0x4001(b)(每个8位)中的数据并计算它们的乘积,然后将结果存储在0x4002(16位)中。我们希望尽量减少指令步骤。
我能想到的是:
a + a + a + a + ..... a(b次)最简单但显然最差的
Leftshift(a,7)+ leftshift(a,6)+ ..... + a(根据b移位并添加)
我想知道这个问题是否有更好的解决方案。 谢谢!
答案 0 :(得分:4)
一般的想法与你(应该)在学校学习时的长度相同"长乘法",除了我们用二进制代替十进制。请考虑以下两个示例:
1010 1234
x 1100 x 2121
---------- ---------
0000 1234
0000 2468
1010 1234
+ 1010 + 2468
--------- ---------
1111000 2617314
右边的例子是base-10(十进制),左边的例子是二进制。观察到你必须乘以顶部因子的唯一数字是0或1.乘以零很容易,答案总是为零,你甚至不必担心将其加入。乘以1也是很容易,这只是一个知道问题"转移它有多远"。但这很容易,它远远超过你必须要检查那一点。
从数字的16位工作副本开始,将16位累加器设置为零。将最上面的数字移过来,只要在最右边的数字中有一个数字,你就可以添加"工作副本"到累加器。无论是否有一个或零,你需要转移"工作副本"向左一点。当"顶部"得到零,你知道你已经完成了,答案是在累加器中。
您可以使用一些优化,这样您就不需要那么多的16位寄存器(或8位寄存器对),但我会让您详细说明。
答案 1 :(得分:2)
似乎您使用的是类似于8080,6502,6800和类似物的8/16位处理器。是的,一个8次迭代的移位和加法循环就足够了,几乎是最优的。 OTOH,如果你有一个常数表的1020个字节,使用下面公式的方法可能是最快的:
a*b = square(a+b)/4 - square(a-b)/4
如果参数是无符号的,则a + b的最大值为510.对于任何x,只需保留x ** 2/4的整数部分,因为公式中的小数部分将相互补偿;所以,映射是:0 - > 0,1 - > 0,2 - > 1,3-> 2,4-> 4,...,510 - > 65025.对于签名参数,该表小两倍。
还有许多其他快速乘法方法,包括几乎线性的成本;见例如唐纳德克努特"计算机编程艺术"传奇的书系列,第2卷。但是在8位参数的情况下,它们都有太大的开销。