【发布时间】:2016-12-07 02:15:31
【问题描述】:
我正在研究一种可以在不使用 MUL 或 DIV 运算符的情况下在汇编中将两个数字相除的东西。逻辑是,如果 n*var
首先,我创建了一个利用位移的乘法器,这很有效。
//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 并将寄存器设置为正确的数字以进行相乘,另一个检查 nvar >= x。如果 nvar
这个程序有一些我没有看到的错误,不知何故,答案总是 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
我已经被这个问题困扰了几天,我无法弄清楚是什么问题导致了这个奇怪的错误。任何帮助表示赞赏。
【问题讨论】:
-
使用调试器单步调试代码,看看它在哪些地方没有做你想做的事情。
-
前段时间,我用纯 asm 编写了一个小型波兰语计算器。它工作,至少对于整数。尽管如此,整数除法的结果也是小数,这似乎也有效。只要你知道,那个除法就是重复减法,你可以用 sub 来做。我就是这样做的。
-
在第二个代码块中:
eax第一次经过L11:是什么?对我来说看起来不确定。再加上用js/jns两次做同样的cmp是在浪费CPU 周期。在第一个cmp + js指令对之后,您不需要再次执行cmp,因为标志仍然从以前设置(然后js不会修改标志)并且jns将在100% 的情况下发生,因为之前的js已经处理了所有 SF=1 的案例。 ...我确实只检查了第二块的那〜10 行,因为我很好奇你是否真的 做++n然后乘以n*varAGAIN,OMG :D .. 荒谬。(n+1)*var == (n*var)+var! -
你的乘数坏了。它仅在 a 小于 2 的幂时起作用。您的测试用例恰好是您没有注意到的幸运值之一。
-
有一种更有效的平方根算法,它不是尝试每个可能的值,而是从平方根作为
0开始并尝试一次设置一位,从最高可能位向下。如果此测试值的平方为 0x8000,下一次尝试将是0xC000或0x0400,具体取决于第一次尝试的结果,等等。