给你一个非负整数n。在 [2, n-1] 范围内求出这个数的除数个数。
输入:不超过1000的整数非负数n。
输出:整数非负数
我试了一下代码,但我不能总是得到正确的结果。
%include"io.inc"
section .text
global CMAIN
CMAIN:
;write your code here
GET_UDEC 4, eax
mov ebx, 2
mov ecx, 0
cycle:
cmp eax, ebx
jbe end;
xor edx, edx
div ebx
mul eax, ebx
inc ebx
cmp edx, 0
jne cycle;
inc ecx;
jmp cycle;
end:
PRINT_UDEC 4, ecx
NEWLINE
xor eax, eax
ret
我的代码有问题吗?请帮我指出来
...我总不能得到正确的结果
原因是,随着循环的每次迭代,您都会更改股息,而股息应该保持不变。我看到您添加了一条
mul eax, ebx
指令,试图将股息恢复到其原始值,但遗憾的是,该指令可能看起来像双操作数乘法,实际上它是变相的通常的单操作数 mul ebx
!它使用 EAX 是隐含的,它将修改 EDX 寄存器(这意味着除法的余数消失了)。会起作用的是 imul eax, ebx
后跟 add eax, edx
(1),但首选的解决方案是在每个除法之前重新加载红利。使用 push eax
和 pop eax
(2),或者从用输入数字 (3) 初始化的备用寄存器加载 EAX。
解决方案 1
GET_UDEC 4, eax
mov ebx, 2
mov ecx, 0
cycle:
cmp eax, ebx
jbe end
xor edx, edx
div ebx
IMUL EAX, EBX <<<< Does not destroy the remainder in EDX
ADD EAX, EDX <<<<
inc ebx
cmp edx, 0
jne cycle
inc ecx
jmp cycle
end:
解决方案 2
GET_UDEC 4, eax
mov ebx, 2
mov ecx, 0
cycle:
cmp eax, ebx
jbe end
xor edx, edx
PUSH EAX <<<<
div ebx
POP EAX <<<<
inc ebx
cmp edx, 0
jne cycle
inc ecx
jmp cycle
end:
解决方案 3
GET_UDEC 4, eax
MOV ESI, EAX <<<<
mov ebx, 2
mov ecx, 0
cycle:
cmp eax, ebx
jbe end
xor edx, edx
div ebx
MOV EAX, ESI <<<<
inc ebx
cmp edx, 0
jne cycle
inc ecx
jmp cycle
end:
输入为不超过1000的非负数N。
在 [2, N-1] 范围内求出这个数的除数个数。
考虑 N=1000。您当前的代码会将 1000 除以 [2,999] 范围内的每个数字。一共998个师!现在看看当您开始将 1000 除以 [501,999] 范围内的数字时会发生什么:余数永远不会为零,因此代码永远不会再增加 ECX。简而言之,您可以在 N/2 以上的 EBX 处停止循环。
GET_UDEC 4, eax
MOV EDI, EAX <<<<
SHR EDI, 1 <<<< EDI is now N/2
MOV ESI, EAX <<<<
XOR ECX, ECX <<<<
mov ebx, 2
cycle:
CMP EBX, EDI <<<< Exits on EBX > N/2, and also exits on N < 4
JA end <<<<
xor edx, edx
div ebx
MOV EAX, ESI <<<<
inc ebx
TEST EDX, EDX <<<<
JNZ cycle <<<<
inc ecx
jmp cycle
end: