INF1018 - Software Básico

Instruções de Ponto Flutuante

Traduza as funções abaixo para assembly. Para cada função traduzida, crie um arquivo C contendo uma função main para testá-la.

Verifique se os resultados estão corretos!

ATENÇÃO: na tradução das funções, chame explicitamente as funções sin/cos da biblioteca matemática. Lembre-se que o argumento dessas funções é um valor double, veja protótipos abaixo:

    double sin(double x);
    double cos(double x);
Para gerar seu programa executável, utilize:

gcc -Wall ... -lm
(a opção '-lm' é para incluir a biblioteca matemática no passo de ligação)

  1. Traduza a função foo para assembly.
    float foo (double a, float b) {
      return (a+b)*(a-b);
    }
    
    Repare que você pode efetuar as operações de soma, subtração e multiplicação com operandos do tipo float ou double. Trabalhando com operandos double você pode obter um resultado com maior precisão!

    Experimente não colocar o protótipo de foo na sua main. O compilador vai dar um "warning"... O que acontece se você gerar e executar seu programa assim mesmo? Você consegue explicar o que aconteceu?

  2. Traduza a função foo1 para assembly. Para testá-la, é importante usar alguns valores de seno bem conhecidos. Você pode incluir na sua função main o arquivo de cabeçalho math.h, que define, por exemplo, as constantes M_PI e M_PI_2 (PI/2).

    Lembre-se que qualquer registrador %xmm pode ser sobrescrito por uma função! Você deve ter o cuidado de salvar valores que podem ser perdidos...

    float foo1 (float a, float b) {
      return sin(a) + b;
    }
    
    Dica: use a pilha de execução para guardar valores...

  3. Traduza a função foo2 para assembly. Novamente, use para testá-la valores de seno e coseno bem conhecidos!
    double foo2 (float a, float b) {
      return sin(a) + cos(b);
    }
    
    Dica 1: use a pilha de execução para guardar o resultado da primeira chamada de função.

    Dica 2: muito cuidado com a pilha/localização de parametros e etc... antes e depois das chamadas a sin e cos! Desenhe a pilha de execução e simule essas chamadas!

  4. Traduza a função foo3 para assembly.
    double foo3 (double *a, int n) {
      int i;
      double r = 0.0;
      for (i=0; i<n; i++) {
        r += sin(*a);
        a++;
      }
      return r;
    }
    
    Dicas:
    • Você deve guardar a variável local r na pilha!
    • Observe que o primeiro parâmetro é um ponteiro!
    • Lembre-se que o código da função sin pode sobrescrever quaisquer registradores que não são callee-saved!