Atividade obrigatória 3
Geração de números primos

Escreva um programa estruturado (ou seja, com subrotinas comentadas) em linguagem de montagem do ARM, para obter e armazenar em palavras (32 bits) da memória RAM os pimeiros 32 números primos, usando um dos 2 algoritmos do tipo "Crivo de Eratóstenes", cujos fontes em C aparecem abaixo (teste-os!). A sequencia de números primos deve ser exibida no vídeo com o formato "%10d\n" e deve ter o valor:
         1
         2
         3
         5
         7
        11
        13
        17
        19
        23
        29
        31
        37
        41
        43
        47
        53
        59
        61
        67
        71
        73
        79
        83
        89
        97
       101
       103
       107
       109
       113
       127
Importante: (i) traduza manualmente para assembler ("dicas" serão dadas em aula), um dos algoritmos em C, a seguir: o 1o, adaptado de Knuth, vol 1, p. 143(*), e o 2o, de J. P. Sundaran (1934)(**)
(ii) teste inicialmente o seu programa com um crivo pequeno, digamos, com 16 posições e depure-o com gdb;
Observe que, em princípio, o seu programa poderia gerar números primos sendo limitado unicamente pela capacidade da memória RAM do processador alvo. Uma tabela de números primos é exibida no diretório docs. Você pode usá-la para testar seu programa com uma quantidade maior de números primos.
(*)
//kprimes.c - adaptado de Knuth, "The Art of Computer Programming", Vol 1, p.143
#include <stdio.h>
#define MAXPRIMES 32
unsigned int primes[MAXPRIMES];
unsigned int next, prindex;
int main(){
   unsigned int i;
   primes[0]=1; primes[1]=2; primes[2]=3;
   printf("%10d\n", primes[0]);
   printf("%10d\n", primes[1]);
   next=3;
   prindex=2;
   printf("%10d\n", next);
   while(1){   //loop1
   loop1:
      next +=2;
      for (i=2; ; i++){
        if ((next % primes[i])==0) goto loop1;
        if (next / primes[i] <= primes[i]) break;
      }
      prindex++;
      primes[prindex]=next;
      printf("%10d\n", next);
   if (prindex==MAXPRIMES-1) break;
  }       
}
Explicação do algoritmo:
O laço interno (for (i=2...etc) verifica se o candidato ímpar "next" é primo dividindo-o
pelos primos encontrados até agora, até um valor limite primos[i] determinado
pelas seguintes asserções:
(i) todo inteiro não primo n pode se fatorado como produto de potencias de primos da forma: n= p1j1...pkjk
(p1<p2<...<pk);
(ii)se next % primes [i] == 0 então next é múltiplo de um dos primos da tabela e pode ser ignorado;
(iii)senão, se primes[i]>=sqrt(next) então por (i) acima next é primo, mas isto implica em:
     primes[i]2 >= next, ou seja,  primes[i]>=next/primes[i] > floor(next/primes[i]),
     logo, next é primo.

(**)
/* sund.c    - Geração de números primos usando o Crivo de Sundaran (1934)
http://en.wikipedia.org/wiki/Sieve_of_Sundaram
*/
#include <stdio.h>
#define N 64
int crivo[N+1];
int main(){
   int i,j,k;
   for (i=1;i<=N; i++)
	crivo[i]=i;
   for (j=1; j<=N; j++){
     for (i=1; i<=j; i++){
         k = i +j +2*i*j;
         if (k<=N) crivo[k]=0;
     }
   }

   for (i=1;i<=N; i++)
	if(crivo[i]>0)
           crivo[i]=2*crivo[i] +1;
   printf ("%10d\n%10d\n", 1, 2);
   for (i=1;i<=N; i++)
	if(crivo[i]>0) printf("%10d\n", crivo[i]);
}