Assembly Eratosthenes x86组件的筛

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 ;-----------

我是汇编新手,试图实现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
;--------------------------------------------------------
;   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倍是一个巨大的胜利。)@PeterCordes
edx
通过添加
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