起初,我无法理解你的程序相对于维基链接算法的意义。
p
,将每个元素标记为非质数。
loop1
没有那样做。
看起来
回路1
正在执行步骤(4),然后
loop2
将执行步骤(3)。这实际上可以按相反的顺序进行。
为了简化操作,我维护了一个“数组结束”指针,而不是一个计数。并且,使用了
.byte
数组而不是
.word
以下是wiki版本:
.data
array: .byte 1:1000
earray:
# array[1000] = {1} (assume all are prime initially)
msg_nl: .asciiz "\n"
.text
.globl main
# registers:
# s0 -- address of array
# s1 -- address of end of array
#
# t0 -- value of array[current]
# t1 -- pointer to current array value being tested
# t2 -- current "p" value
main:
la $s0,array # get &array[0]
la $s1,earray # get pointer to end of array
sb $zero,0($s0) # 0 is not prime
sb $zero,1($s0) # 1 is not prime
li $t2,2 # p = 2
move $t1,$s0 # get &array[0]
addu $t1,$t1,$t2 # get &array[2]
addu $t1,$t1,$t2 # get &array[4]
j mark_start
# mark 2p, 3p, ... as not prime
mark_loop:
sb $zero,0($t1) # mark as not prime
addu $t1,$t1,$t2 # advance to next cell
mark_start:
blt $t1,$s1,mark_loop # done with this p? if no, loop
# find next higher prime than p
addu $t1,$s0,$t2 # get &array[p]
addiu $t1,$t1,1 # get &array[p + 1]
j find_start
find_loop:
lb $t0,0($t1) # is current number [still] prime?
bnez $t0,find_match # yes, fly
addiu $t1,$t1,1 # no, advance to next cell
find_start:
blt $t1,$s1,find_loop # over edge? if no, loop
j print_all # yes, sieve complete
# found new p value -- set up to restart marking loop
find_match:
sub $t2,$t1,$s0 # get the new p value
addu $t1,$t1,$t2 # get &array[2p]
j mark_start # restart the marking loop
# print all the primes
print_all:
move $t1,$s0 # get array start
li $t2,0 # get p value
print_loop:
bge $t1,$s1,main_exit # over edge? if yes, exit program
lb $t0,0($t1) # is current value prime?
bnez $t0,print_match # if yes, fly
print_next:
addi $t1,$t1,1 # advance to next array element
addiu $t2,$t2,1 # increment p
j print_loop
print_match:
li $v0,1
move $a0,$t2
syscall
li $v0,4
la $a0,msg_nl
syscall
j print_next
main_exit:
li $v0,10
syscall
下面是颠倒步骤的步骤:
.data
array: .byte 1:1000
earray:
# array[1000] = {1} (assume all are prime initially)
msg_nl: .asciiz "\n"
.text
.globl main
# registers:
# s0 -- address of array
# s1 -- address of end of array
#
# t0 -- value of array[current]
# t1 -- pointer to current array value being tested
# t2 -- current "p" value
main:
la $s0,array # get &array[0]
la $s1,earray # get pointer to end of array
sb $zero,0($s0) # 0 is not prime
sb $zero,1($s0) # 1 is not prime
li $t2,1 # p = 1
# find next higher prime than p
find_begin:
move $t1,$s0 # get &array[0]
addu $t1,$s0,$t2 # get &array[p]
addiu $t1,$t1,1 # get &array[p + 1]
j find_start
find_loop:
lb $t0,0($t1) # is current number [still] prime?
bnez $t0,find_match # yes, fly
addiu $t1,$t1,1 # no, advance to next cell
find_start:
blt $t1,$s1,find_loop # over edge? if no, loop
j print_all # yes, sieve complete
# found new p value -- set up to restart marking loop
find_match:
sub $t2,$t1,$s0 # get the new p value
addu $t1,$t1,$t2 # get &array[2p]
j mark_start # restart the marking loop
# mark 2p, 3p, ... as not prime
mark_loop:
sb $zero,0($t1) # mark as not prime
addu $t1,$t1,$t2 # advance to next cell (2p, 3p, 4p, ...)
mark_start:
blt $t1,$s1,mark_loop # done with this p? if no, loop
j find_begin
# print all the primes
print_all:
move $t1,$s0 # get array start
li $t2,0 # get p value
print_loop:
bge $t1,$s1,main_exit # over edge? if yes, exit program
lb $t0,0($t1) # is current value prime?
bnez $t0,print_match # if yes, fly
print_next:
addi $t1,$t1,1 # advance to next array element
addiu $t2,$t2,1 # increment p
j print_loop
print_match:
li $v0,1
move $a0,$t2
syscall
li $v0,4
la $a0,msg_nl
syscall
j print_next
main_exit:
li $v0,10
syscall