如何在不使用MUL或DIV运算符的情况下在汇编中分割两个数字?

时间:2016-12-07 02:15:32

标签: assembly x86

我正在研究在不使用MUL或DIV运算符的情况下在汇编中划分两个数字的东西。如果n * var<则逻辑是x,其中x是要除的数,var是要除的数,将n递增1并重复。因此,如果有剩余部分,分隔符将把答案四舍五入。

首先,我创建了一个利用位移的乘法器,这很有效。

//multiply
int ans, var1;
_asm {
        mov eax, 00001111b; A = 1111
        mov ebx, 00001010b; B = 1010
        mov var1, 00000001b; C = 0001
        mov ecx, 0;
        shl ebx, 3; shift b register left by 3
    L1:
        cmp ecx, 4; check if multiplication is done
            je L4; go to empty loop
        inc ecx; increment counter by 1
        AND var1, eax; check if the least significant bit is 1
        cmp var1, 1; checks if var1 is = 1
            je L2;
        cmp var1, 0; check if var1 = 0
            je L3;
    L2:
        shr eax, 1; shift a register right 1 bit
        add eax, ebx; add a and b registers
        jmp L1; go back to L1
    L3:
        shr eax, 1;
        jmp L1; go back to L1
    L4 :
        mov ans, eax; move eax to answer
};
cout << "Multiply 00001111 and 00001010" << endl << ans << endl;

所以我要做的是用另外两个循环实现这个乘法器:一个递增n并将寄存器设置为正确的数字以进行乘法,另一个检查n var&gt; = x。如果n var&lt; x,它将增加n并将寄存器设置为乘,然后将它们相乘。找到答案后,递增的寄存器(edx)将变为变量d并输出到控制台。

这个程序中有一些错误,我没有看到,并且不知何故,答案总是变成var2 * 16,其中var2是要分割的数字。

int var1;
int var2;
int var3;
int d;
_asm {
    ; if n*var3 < var2, increment n and repeat
    mov var2, 12; number to be divided
    mov var3, 5; number to divide with
    mov ecx, 0;
    mov edx, 0; number to increment
L11 :
    cmp eax, var2;
    js L12; if n*n < var2, increment n and multiply.
    cmp eax, var2
    jns L16; answer found, jump to empty loop       
L12 :
    inc edx
    mov eax, edx
    mov ebx, var3
    shl ebx, 3
    mov ecx, 0
    jmp L13
L13 :
    cmp ecx, 4; check if multiplication is done
    je L11;
    inc ecx; increment counter by 1
    AND var1, eax; check if the least significant bit is 1
    cmp var1, 1; checks if var1 is = 1
    je L14;
    cmp var1, 0; check if var1 = 0
    je L15;
L14:
    shr eax, 1; shift a register right 1 bit
    add eax, ebx; add a and b registers
    jmp L13; go back to L1
L15 :
    shr eax, 1;
    jmp L13;
L16:
    mov d, edx
};
cout << "The quotient is " << d << endl;

我还创建了一个非常相似的程序来计算数字的平方根,如果n * n&lt; x,其中x是取平方根的数字,递增n和重复。使用分隔符解决这个错误也应该帮助我使用平方根程序,同时发生同样的错误。

我已经被困在这几天了,我无法弄清楚造成这个奇怪错误的错误。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

减法可以解答您的问题(&#34;如何在不使用MUL或DIV运算符的情况下在汇编中分割两个数字?&#34;),示例(在VS2013上测试):

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(void){
    int dividend;
    cout << "Enter DIVIDEND : "; //◄■ EXAMPLE : 23.
    cin >> dividend;

    int divisor;
    cout << "Enter DIVISOR : "; //◄■ EXAMPLE : 4.
    cin >> divisor;

    int quotient = 0;
    _asm {
            mov eax, dividend
        divisions:
            cmp eax, divisor
            jb  finish        //◄■ IF DIVIDEND < DIVISOR
            sub eax, divisor  //◄■ DIVIDEND - DIVISOR. EXAMPLE :  23 - 4.
            inc quotient      //◄■ DIVISIONS COUNTER.
            jmp divisions
        finish:
    }
    cout << "The result is " << quotient; //◄■ EXAMPLE : 5
    return 0;
}

以前的代码会抛出整数结果。如果你想要带小数的结果,有必要将最后一个被除数(前一个例子中的3)乘以10表示一位小数,或乘以100表示​​两位小数(或1000表示三位小数,依此类推),例如(在VS2013上测试) ):

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(void){
    int dividend;
    cout << "Enter DIVIDEND : "; //◄■ EXAMPLE : 23.
    cin >> dividend;

    int divisor;
    cout << "Enter DIVISOR : "; //◄■ EXAMPLE : 4.
    cin >> divisor;

// ▼ CALCULATE QUOTIENT.
    int quotient = 0;
    _asm {
            mov eax, dividend
        divisions:
            cmp eax, divisor
            jb  finish1       //◄■ IF DIVIDEND < DIVISOR
            sub eax, divisor  //◄■ DIVIDEND - DIVISOR. EXAMPLE :  23 - 4.
            inc quotient      //◄■ DIVISIONS COUNTER.
            jmp divisions
        finish1:
            mov dividend, eax //◄■ LAST DIVIDEND (USED FOR REMAINDER). EXAMPLE : 3.
    }

// ▼ CALCULATE REMAINDER WITH TWO DECIMALS.
    int remainder = 0;
    _asm {
        // ▼ MULTIPLY LAST DIVIDEND BY 100. EXAMPLE : 3 * 100 = 300.
            mov ecx, 100  //◄■ REPEAT 100 TIMES.
            mov eax, 0
        multiply:
            add eax, dividend //◄■ MULTIPLY IS A SERIES OF ADDITIONS. EXAMPLE : EAX + 3.
            loop multiply
        // ▼ GET REMAINDER WITH TWO DECIMALS.
        decimals:
            cmp eax, divisor
            jb  finish2  //◄■ IF DIVIDEND < DIVISOR
            sub eax, divisor  //◄■ DIVIDEND - DIVISOR. EXAMPLE : 300 - 4.
            inc remainder //◄■ DIVISIONS COUNTER.
            jmp decimals
        finish2:
    }
    cout << "The result is " << quotient <<  "." << remainder; //◄■ EXAMPLE : 5.75
    return 0;
}