Вы не были достаточно конкретными с тем, что «идти наперекосяк» означает, и вы, вероятно, не отладки кода, ни вы прокомментировали его достаточно, чтобы сделать его легко следовать, поэтому через несколько минут, глядя на это я следовали моему инстинкту, который велел мне начинать с нуля и писать его регулярно.
Будет ли это вам помогать - я понятия не имею, возможно, нет, по крайней мере, не без достаточного «анализа этого» усилия.
Но я считаю, что это является действительный ответ на вопрос с названием «Решето Эратосфена x86 Ассамблеи» и «любая помощь будет делать».
Итак, вы идете, попытайтесь понять полностью иностранный источник и попытайтесь понять используемые идеи; к точке, где она начнет вам помогать при написании собственного кода. Удачи. :)
Прежде всего, перед некоторым кодом вы должны сначала очистить свою задачу с точки зрения математики.
Если вы хотите, вы бы знали, что нет смысла «сито» далее за пределами sqrt (n) значение.
Потому что если SQRT (п) простое, то его умножает 2 * SQRT (п), 3 * SQRT (п), ..., previous_prime * SQRT (п) уже "просеивают" от меньшего простые числа, просеивающие ранее в цикле.
Первый номер «все еще несчастливый» - это sqrt (n) * sqrt (n), то есть n сам, и это вне границ массива. Поэтому после достижения числа> = sqrt (n) вы можете закончить основной цикл алгоритма (я использую острый тест number > sqrt(n)
, потому что sqrt(n)
усечен до целого числа, поэтому для специального «n» (с целым числом sqrt (n)) постараюсь «сито» п сам однажды, но будут обнаружены с помощью теста внутри flip_loop
и прекращается в любом случае.
Include Irvine32.inc
n=1000
n_terminal=31
; terminal compare value is min(sqrt(n), 0FFFFh) (last value to process)
; no point to sieve beyond sqrt(n), because first unset multiply is
; sqrt(n)*sqrt(n) = n => beyond array
; and no point to sieve 10000h, because 10000h*10000h is out of 32b
.data
prime BYTE n DUP(?)
.code
main PROC
; fill array with "1" (from number 2 to n)
mov edi,OFFSET prime+2
mov ecx,n-2
mov eax,1 ; eax=1 will be used also later (also ah=0)
rep stosb
; set "0" and "1" as non-prime too
mov WORD PTR [prime],cx ; (cx == 0 after "rep stosb")
; set "0" to all other non-primes by sieving
mov esi,eax ; esi=1, start the loop as if "1" was handled last
sieve_loop:
inc esi ; next number to test
; sqrt(n) is enough to process, beyond that n <= number*number => out of array
cmp esi,n_terminal
ja sieve_end ; out of table, end sieving
cmp prime[esi],al ; compare with "1"
jne sieve_loop ; not a prime, don't flip the rest of sieve
; esi is prime, flip the other multiplies of it, starting from esi*esi (!)
mov edi,esi ; esi*esi as smaller multiples are already covered by
imul edi,edi ; smaller prime numbers sieving the array before
flip_loop:
cmp edi,n ; check if the multiply points beyond table
jae sieve_loop ; if yes, continue main loop with next "prime"
mov prime[edi],ah ; set this number to "0" (not prime)
add edi,esi ; edi = next multiply of esi prime
jmp flip_loop
sieve_end:
; print all primes starting from 2
mov esi,eax ; esi = 1, as if "1" was handled last
print_loop:
inc esi ; while (++number < n)
cmp esi,n
jae end_print_loop
cmp BYTE PTR prime[esi],1 ; eax/al is modified from "WriteDec"
jne print_loop ; not a prime number, loop
; esi is prime number, print it
mov eax,esi
call WriteDec ; these two calls must preserve esi
call Crlf
jmp print_loop
end_print_loop:
exit
main ENDP
END main
я проверить его под Linux с NASM, так что я пришлось немного изменить синтаксис, чтобы скомпилировать его, а затем изменить синтаксис для MASM/TASM + irvine, поэтому mayb e небольшая ошибка проскользнула там во время конвертации, сообщите мне, если это не сработает.
Где масштабировании 'edx' от 4 до индекса в массиве DWORD? Я этого не вижу. (Конечно, было бы намного лучше сделать его байтовым массивом или даже растровым изображением, поскольку производительность сита часто ограничена промахами в кеше данных. Уменьшение размера кеша в 4 раза - огромная победа.) –
@PeterCordes 'edx' масштабируется добавлением' edi', который является 'ebx', который является предварительно умноженным смещением. (по крайней мере, я так думаю, логика этого кода настолько расточительно сложна, что нелегко следить за ней в голове). – Ped7g
Ну, я попытался понять это, но это полное минное поле, невозможно «запустить» его в голове, поэтому многие неясные расточительные сложности делают его слишком отличным от короткого выполнения, ожидаемого моей головой. – Ped7g