简体   繁体   English

在不使用指令MUL,IMUL,SHL,SHR,LOOP的情况下将数字相乘

[英]Multiply numbers without using instructions MUL, IMUL, SHL, SHR, LOOP

是否可以不使用x86汇编语言中的指令MUL,IMUL,SHL,SHR,LOOP,JMP来计算乘法结果?

The following code will multiply the contents of the registers ecx and edx and store the result in register eax . 以下代码将寄存器ecxedx的内容相乘,并将结果存储在寄存器eax The content of the registers ebx and edx is destroyed: 寄存器ebxedx被破坏:

  mov ebx, 1
  mov eax, 0
repeat:
  test ecx, ebx
  jz dontadd
  add eax, edx
dontadd:
  add edx, edx
  add ebx, ebx
  jnz repeat

without ... LOOP 没有...循环

If "LOOP" does not only cover the "LOOP" instruction but any conditional jump instructions: 如果“ LOOP”不仅涵盖“ LOOP”指令,还包括任何条件跳转指令:

Doing a multiplication without conditional jump instructions is a bit more difficult but not impossible; 在没有条件跳转指令的情况下进行乘法要困难一些,但并非没有可能。 the following example does so (Input: ecx and edx , output eax , the content of all registers used will be destroyed): 下面的示例这样做(输入: ecxedx ,输出eax ,使用的所有寄存器的内容都会被破坏):

mov ebx, 1
mov eax, 0
not ecx
  # Repeat the following code 32 times:
mov esi, ebx
and esi, ecx
dec esi
and esi, edx
add eax, esi
add edx, edx
add ebx, ebx
  # (repeat the code here)

Is it possible to calculate result of multiplication without using instructions MUL, IMUL, SHL, SHR, LOOP, JMP in x86 assembly language? 是否可以不使用x86汇编语言中的指令MUL,IMUL,SHL,SHR,LOOP,JMP来计算乘法结果?

Yes. 是。

Without MUL the normal approach is "SHIFT LEFT and TEST and ADD" in a loop, like this: 如果没有MUL,通常的方法是循环循环“ SHIFT LEFT,TEST和ADD”,如下所示:

    result = 0;
    while(a > 0) {
        result = result << 1;
        if( a & 0x80000000 != 0) {
            result = result + b;
        }
        a = a << 1;
    }

Note that a loop like this for 32-bit integers will have (at most) 32 iterations. 请注意,像这样的32位整数循环最多(最多)进行32次迭代。

You can replace these shifts with additions (eg shl eax, 1 replaced with add eax, eax ); 您可以将这些班次替换为shl eax, 1 (例如shl eax, 1替换为add eax, eax ); and you can replace LOOP with an explicit loop (eg dec ecx , jne next ) or unroll the loop (repeat the code 32 times). 您可以将LOOP替换为显式循环(例如dec ecxjne next )或展开循环(重复32次代码)。 These replacements will probably improve performance. 这些替换可能会提高性能。

Once you have unsigned multiplication, IMUL can be replaced with branches that convert the values to positive and uses unsigned multiplication. 一旦完成无符号乘法运算,就可以将IMUL替换为将值转换为正数并使用无符号乘法运算的分支。 Eg like: 例如:

    if(a < 0) {
        a = -a;
        if(b < 0) {
            b = -b
            return a*b;    // Unsigned multiplication
        } else {
            return -a*b;   // Unsigned multiplication
        }
    } else {
        if(b < 0) {
            b = -b
            return -a*b;   // Unsigned multiplication
        } else {
            return a*b;    // Unsigned multiplication
    }
}

Hell bent against full table lookup and logarithm, addition and exponentiation , you can still do 反对全表查找对数,加法和求幂的地狱,您仍然可以
table lookup of squares and subtraction : ab = (a+b)²/4 - (ab)²/4 . 平方和减法的表查找 :ab = (a + b)²/ 4-(ab)²/ 4

CPUs without a multiply instruction can generally do it with repeated addition but that becomes extremely difficult without loops. 没有乘法指令的CPU通常可以通过重复加法来执行此操作,但是如果没有循环,这将变得极为困难。

However, since you haven't specified which specific CPU you're interested in, I would posit one that either has an instruction like: 但是,由于您尚未指定感兴趣的特定 CPU,因此我假定其中一个具有以下指令:

add rt, rs, count

instruction which adds rs to rt exactly count times. rs加到rt指令精确count时间。 That would enable you to do it without a loop or jump instruction :-) 这将使您无需loopjump指令即可执行此操作:-)

Of course, then you could just have an paxmul instruction that does multiplication for you - not technically a mul but no doubt against the spirit of the question. 当然,你可能只是有一个paxmul指令,可以做乘法你-技术上不是mul ,但对这个问题的精神无疑。

But, to be honest, this question may be seen as moot since you'd be hard pressed actually trying to find a CPU without the instructions you list. 但是,老实说,由于您实际上很难在没有列出的指令的情况下尝试找到CPU,因此这个问题可能被认为是没有实际意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM