Assembly Eratosthenes x86组件的筛
我是汇编新手,试图实现Erathothenes的筛选,我有代码,但它只能在1到600之间工作,出于某种原因,当我输入n=1000时,它会失控,这是完整的代码,任何帮助都可以Assembly Eratosthenes x86组件的筛,assembly,x86,masm,irvine32,Assembly,X86,Masm,Irvine32,我是汇编新手,试图实现Erathothenes的筛选,我有代码,但它只能在1到600之间工作,出于某种原因,当我输入n=1000时,它会失控,这是完整的代码,任何帮助都可以 Include Irvine32.inc n=1000 .data prime DWORD n DUP(?) .code main PROC mov ecx,n ;initialize ecx to 1000 mov esi, OFFSET prime ;-----------
Include Irvine32.inc
n=1000
.data
prime DWORD n DUP(?)
.code
main PROC
mov ecx,n ;initialize ecx to 1000
mov esi, OFFSET prime
;--------------------------------------------------------
; Initialize Array with 1's
;--------------------------------------------------------
FillArray: mov eax,1
mov [esi],eax
mov eax,[esi]
add esi,TYPE DWORD ;4 to jump to the next index
loop FillArray
mov ebx,8
mov edx,0
mov ecx,n
mov ebp,2
mov esi,0
;----------------------------------------------------------------
; Sieve
;----------------------------------------------------------------
SIEVE: mov eax,prime[ebx]
mov edx,ebx
mov edi,ebx
add edx,edi ;j=i+i
mov esi,ebp
mov ecx,n
sub ecx,ebp
add ecx,2
add ebx,TYPE DWORD
cmp eax,1
je FLIP
inc ebp
loop SIEVE
jmp K
FLIP: mov eax,0
mov prime[edx],eax
add edx,edi
cmp esi,n
jg SIEVE
add esi,ebp
loop FLIP
K:
mov esi, OFFSET prime
mov ecx,n
sub ecx,2
mov ebx,1
mov edx,8 ;Start checking from index of second element
PRINT: mov eax,prime[edx] ;
add edx,TYPE DWORD
inc ebx
cmp eax,1
jne H
mov eax,ebx
call WriteDec
call Crlf
loop PRINT
jmp D
H: loop PRINT
D:
exit
main ENDP
END main
你对“乱七八糟”的意思不够明确,你可能没有调试你的代码,也没有对代码进行足够的注释以使其易于理解,所以在看了几分钟后,我听从了我的直觉,那就是告诉我从零开始,以常规的方式编写代码 这是否会对你有所帮助——我不知道,可能不会,至少如果没有“分析这一点”的努力 但我相信这是一个题为“Eratosthenes x86汇编的筛选”和“任何帮助都可以”的问题的有效答案 所以,在这里,你要试着完全理解外来的资源,并试图掌握使用的想法;在某种程度上,它将开始帮助您编写自己的代码。祝你好运
在编写代码之前的第一件事是,你应该首先清理一下你的数学任务 如果您愿意,您就会知道,在sqrt(n)值之外“筛选”是没有意义的 因为如果sqrt(n)是素数,那么它乘以2*sqrt(n),3*sqrt(n),…,之前的_素数*sqrt(n)已经从循环中较早筛选的较小素数中“筛选”出来 第一个“尚未查看”的数字是sqrt(n)*sqrt(n),即n本身,超出数组边界。因此,在达到number>=sqrt(n)之后,您可以结束您的算法主循环(我使用sharp
number>sqrt(n)
test,因为sqrt(n)
被截断为整数,所以对于特殊的“n”(带有整数sqrt(n)),我将尝试“筛选”n本身一次,但这将由翻转循环内的测试检测并终止
包括Irvine32.inc
n=1000
n_终端=31
;终端比较值为最小值(sqrt(n),0FFFFh)(最后一个要处理的值)
;由于第一次未设置的乘法是
;sqrt(n)*sqrt(n)=n=>超出数组
;且无需筛选10000h,因为10000h*10000h在32b中
.数据
主字节n重复(?)
.代码
主进程
;用“1”填充数组(从数字2到n)
mov edi,基本偏移量+2
mov-ecx,n-2
mov eax,1;eax=1也将在以后使用(也就是ah=0)
代表stosb
;将“0”和“1”也设置为非素数
mov单词PTR[prime],cx;(cx==0,在“rep stosb”之后)
;通过筛选将“0”设置为所有其他非素数
mov-esi,eax;esi=1,启动循环,就像上次处理“1”一样
筛孔环:
inc esi;下一个要测试的数字
;sqrt(n)足以处理,超出数组中的n
cmp esi,n_终端
ja筛头;表外,筛头
cmp素数[esi],al;与“1”比较
jne筛_循环;不是质数,不要翻转筛的其余部分
;esi为素数,从esi*esi(!)开始翻转它的其他倍数
mov edi,esi;esi*esi作为较小的倍数已包含在
imul edi,edi;更小的素数在之前筛选数组
翻转U形环:
cmp edi,n;检查乘法点是否超出表
jae sieve_循环;如果是,则使用下一个“prime”继续主循环
mov素数[edi],ah;将此数字设置为“0”(非素数)
加上edi,esi;edi=esi素数的下一个倍数
jmp翻转环
筛头:
;打印从2开始的所有素数
moveesi,eax;esi=1,就好像“1”是最后处理的一样
打印循环:
inc esi;而(++数字
我确实在linux下用NASM对它进行了测试,所以我不得不稍微修改一下语法来编译它,然后重新修改MASM/TASM+irvine的语法,所以在转换过程中可能会出现一些小错误,如果它不起作用,请告诉我。对于仍然有问题的人,我已经实现了以下代码,从python到汇编
from math import sqrt
def FindPrimes(limit):
isPrime = {}
isPrime[1] = False
for i in range(2, limit + 1):
isPrime[i] = True
checkLimit = int(sqrt(limit)) + 1
for i in range(2, checkLimit):
if isPrime[i]:
for factor in range(2, limit + 1):
j = i * factor
if (j > limit): break
isPrime[j] = False
primes = []
for i in range(1, limit + 1):
if isPrime[i]:
primes.append(i)
return primes
请注意,以下程序集实现在MASM中,它要求您手动输入平方根加1,因为我们将第一个DWORD处理为“isPrime[1]”,当然还有限制“FindPrime(limit)”
为了检查结果,您可以检查素数,它将连续包含每个素数作为双字
如果您有任何问题,请告诉我:)您在哪里将edx
缩放4以索引到DWORD数组?我不认为会发生这种情况。(当然,最好将其设置为字节数组,甚至位图,因为筛选性能通常受到数据缓存未命中的限制。将缓存占用空间减少4倍是一个巨大的胜利。)@PeterCordesedx
通过添加edi
,即ebx
,即预乘偏移量来缩放。(至少我是这样认为的,这段代码的逻辑非常复杂,很难在头脑中理解。)好吧,我试着去弄清楚,但它完全是雷区,不可能在头脑中“运行”它,太多模糊浪费的复杂性使得它与我的头脑所期望的短期实现有太大的不同。@Ped7g:这就是我开始尝试后的决定,这就是为什么我要求澄清/评论:P我说“我看不到它”时是字面意思,并不意味着我相信它不会发生。我只是有点怀疑。总之,@OP:使用调试器。如果你想让其他人帮你的话,可以对你的代码进行更好的注释。你能更具体地说“它乱了”吗?它起作用了,除了“mov[prime],cx”应该是“mov[prime],ch”谢谢。我无法对t发表评论
from math import sqrt
def FindPrimes(limit):
isPrime = {}
isPrime[1] = False
for i in range(2, limit + 1):
isPrime[i] = True
checkLimit = int(sqrt(limit)) + 1
for i in range(2, checkLimit):
if isPrime[i]:
for factor in range(2, limit + 1):
j = i * factor
if (j > limit): break
isPrime[j] = False
primes = []
for i in range(1, limit + 1):
if isPrime[i]:
primes.append(i)
return primes
.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword
n=1000
sqrt=32
.data
sieveArray DWORD n DUP(0)
primeNumbers DWORD n DUP(0)
limit DWORD 0
varInnerLoop DWORD 0 ;variable j
falseValue DWORD 0
primerHelper DWORD 1
.code
main PROC
mov ecx,LENGTHOF sieveArray-1
mov edi,OFFSET sieveArray+TYPE DWORD*2
mov eax,1
fillUp:
mov [edi],eax
add edi,TYPE DWORD
loop fillUp
checkForPrime:
mov edi,OFFSET sieveArray+TYPE DWORD*2 ;reset for iteration
mov esi,[edi] ;pointer helper
mov eax,TYPE DWORD ;offset helper
mov ebx,1 ;counter for loopOverNumbers reference
mov ecx,sqrt-1 ;sqrt(limit)+1 `limit`¨, -1 because index 0 = index 1, counter
mov edx,1 ;outer loop variable helper for inner loop
loopOverNumbers:
cmp ebx,ecx
je iterateOverPrimes ;take me out of the loop because I have iterated over range(1,edx)
cmp esi,1
pushad ;save my flags for outer loop, specially ebx and ecx
je iterateOverFactorsSetUp
continueIteration:
popad
add edi,eax
mov esi,[edi]
inc edx
loop loopOverNumbers
iterateOverFactorsSetUp:
mov eax,1 ;factor for inner loop
mov ecx,n+1
iterateOverFactors:
cmp ebx,ecx
je continueIteration
push edx
push eax
inc eax ;pointer must increment to reflect real value
inc edx ;pointer must increment to reflect real value
imul edx,eax
mov varInnerLoop,edx ;j = i * factor
cmp varInnerLoop,n ;if (j > limit): break
jg continueIterationHelper
imul edx,TYPE DWORD
mov edi,OFFSET sieveArray
add edi,edx
mov eax,0
mov [edi],eax ;reset to old value before pointer
pop eax
pop edx
inc eax
loop iterateOverFactors
continueIterationHelper: ;have to pop eax and edx in order to get original values when returning to
pop eax
pop edx
jmp continueIteration
iterateOverPrimes:
mov eax,TYPE DWORD
mov ecx,n+1 ;limit helper
mov ebx,0
mov edi,OFFSET sieveArray+TYPE DWORD
checkifPrime:
mov esi,[edi]
cmp esi,1
pushad
je appendToPrimeArray
continueSearch:
popad
add edi,eax
inc ebx
loop checkifPrime
jmp searchDone
appendToPrimeArray:
mov eax,TYPE DWORD
mov edi,OFFSET primeNumbers
imul eax,primerHelper ;pointer for primeNumbers helper
add edi,eax
inc ebx
mov [edi],ebx
inc primerHelper
jmp continueSearch
searchDone:
INVOKE ExitProcess,0
main ENDP
END main