Dentre as alternativas, qual programa em MIPS melhor traduz o código em C abaixo?
int abs(int num) {
    if (num < 0)
        return 0 - num;
    else
        return num;
}
a) abs:
    bge \(a0,\)0, else
    sub \(v0,\)0, $a0
    j abs_exit
    else:
    add \(v0,\)0, $a0
    abs_exit:
    jr $ra
b) abs:
    blt \(a0,\)0, else
    sub \(v0,\)0, $a0
    j abs_exit
    else:
    add \(v0,\)0, $a0
    abs_exit:
    jr $ra
c) abs:
    bge \(a0,\)0, then
    add \(v0,\)0, $a0
    j abs_exit
    then:
    sub \(v0,\)0, $a0
    abs_exit:
    jr $ra
d) abs:
    blt \(a0,\)s0, else
    sub \(v0,\)s0, $a0
    j abs_exit
    else:
    add \(v0,\)s0, $a0
    abs_exit:
    jr $ra

Passo 1

O enunciado dá uma função em C:
\text{int abs(int num) \{}
\quad \text{if (num < 0)}
\quad\quad \text{return 0 - num;}
\quad \text{else}
\quad\quad \text{return num;}
\}
Pergunta: dentre as alternativas (a), (b), (c) e (d), qual programa em MIPS traduz corretamente esse código C?
Informações relevantes do enunciado e do problema que usaremos: o parâmetro de entrada é \$a0 (contendo \text{num}), o valor de retorno deve ficar em \$v0, e a instrução final de retorno da função deve ser \text{jr }\$ra (voltar para o chamador). O comportamento desejado é: se \text{num} < 0 então retornar -\text{num} (ou seja, 0 - \text{num}); caso contrário retornar \text{num}.

Passo 2

Breve “aula” prática sobre convenção e instruções que usamos aqui (explicação didática):
  • Registradores usados comumente:
    • \$a0: primeiro argumento da função (aqui contém \text{num}).
    • \$v0: local onde colocamos o valor de retorno.
    • \$ra: registrador que guarda o endereço de retorno (usado por \text{jr }\$ra).
    • \$0: registrador que sempre contém o valor zero (constante 0).
  • Instruções aritméticas simples:
    • \text{sub }\$v0,\\ \$0,\\ \$a0 significa \$v0 = \$0 - \$a0, ou seja \$v0 = -\text{num}.
    • \text{add }\$v0,\\ \$0,\\ \$a0 significa \$v0 = \$0 + \$a0, ou seja \$v0 = \text{num}.
  • Instruções de desvio (branch):
    • \text{bge }\$a,\\ \$b,\\ \text{label} faz o salto para \text{label} se \$a \ge \$b.
    • \text{blt }\$a,\\ \$b,\\ \text{label} faz o salto para \text{label} se \$a < \$b.
      Explicando em palavras: para implementar o if (\text{num} < 0) temos duas abordagens típicas em MIPS: ou testamos a condição e saltamos para o ramo “else” quando a condição for falsa, ou testamos e saltamos para o ramo “then” quando a condição for verdadeira. O importante é que o branch usado tenha a lógica correta (quando saltar) e que os rótulos (labels) no código estejam posicionados onde se espera.

Passo 3

Análise detalhada da alternativa (a):
Código da alternativa (a) (respeitando a escrita dada):
\text{abs:}
\quad \text{bge }\$a0,\\ \$0,\\ \text{else}
\quad \text{sub }\$v0,\\ \$0,\\ \$a0
\quad \text{j abs\_exit}
\text{else:}
\quad \text{add }\$v0,\\ \$0,\\ \$a0
\text{abs\_exit:}
\quad \text{jr }\$ra
Raciocínio passo a passo para (a):
  • A instrução \text{bge }\$a0,\\ \$0,\\ \text{else} diz: "se \$a0 \ge \$0 (ou seja, \text{num} \ge 0) salte para o rótulo \text{else}".
  • Se \text{num} \ge 0, o salto leva diretamente ao rótulo \text{else} e ali executa \text{add }\$v0,\\ \$0,\\ \$a0, que coloca \text{num} em \$v0 — exatamente o que queremos para o ramo else.
  • Se \text{num} < 0, o salto NÃO é tomado, então o fluxo cai na instrução seguinte imediatamente após o branch, que é \text{sub }\$v0,\\ \$0,\\ \$a0. Essa instrução calcula -\text{num} e coloca em \$v0 — exatamente o que queremos para o ramo then (quando num < 0). Em seguida \text{j abs\_exit} pula para a saída e faz \text{jr }\$ra.
    Portanto (a) produz o comportamento correto: quando \text{num}<0 retorna -\text{num}; quando \text{num}\ge0 retorna \text{num}.

Passo 4

Análise da alternativa (b):
Código (b):
\text{abs:}
\quad \text{blt }\$a0,\\ \$0,\\ \text{else}
\quad \text{sub }\$v0,\\ \$0,\\ \$a0
\quad \text{j abs\_exit}
\text{else:}
\quad \text{add }\$v0,\\ \$0,\\ \$a0
\text{abs\_exit:}
\quad \text{jr }\$ra
Raciocínio:
  • \text{blt }\$a0,\\ \$0,\\ \text{else} salta para \text{else} quando \$a0 < \$0 (isto é, quando \text{num} < 0).
  • Se \text{num} < 0, o salto vai para \text{else} e executa \text{add }\$v0,\\ \$0,\\ \$a0, que retorna \text{num} (valor negativo) — isso é errado: quando \text{num}<0 devemos retornar -\text{num}, não \text{num}.
  • Se \text{num} \ge 0, o salto NÃO é tomado, caímos na \text{sub} e retornamos -\text{num} para um número não-negativo — também errado.
    Portanto (b) está invertido: a condição de salto e o código resultante produzem o comportamento contrário ao desejado.

Passo 5

Análise da alternativa (c):
Código (c):
\text{abs:}
\quad \text{bge }\$a0,\\ \$0,\\ \text{then}
\quad \text{add }\$v0,\\ \$0,\\ \$a0
\quad \text{j abs\_exit}
\text{then:}
\quad \text{sub }\$v0,\\ \$0,\\ \$a0
\text{abs\_exit:}
\quad \text{jr }\$ra
Raciocínio atento à posição do rótulo:
  • A instrução \text{bge }\$a0,\\ \$0,\\ \text{then} salta para o rótulo \text{then} se \text{num} \ge 0.
  • Observe a ordem textual: logo após o branch vem uma instrução \text{add }\$v0,\\ \$0,\\ \$a0 seguida de um \text{j abs\_exit}, e só depois aparece o rótulo \text{then:} com a \text{sub}.
  • Se o branch for tomado (isto é, \text{num} \ge 0), o salto vai para o rótulo \text{then} que está localizado depois da \text{add} e do \text{j}; assim, o salto leva ao bloco que faz \text{sub }\$v0,\\ \$0,\\ \$a0 — retornando -\text{num} quando \text{num}\ge0, o que está errado.
  • Se o branch NÃO for tomado (isto é, \text{num} < 0), cai-se na \text{add} e retorna-se \text{num} (negativo) — também errado.
    Portanto (c) é incorreta devido à combinação da condição com a posição dos rótulos: o fluxo fica invertido.

Passo 6

Análise da alternativa (d):
Código (d):
\text{abs:}
\quad \text{blt }\$a0,\\ \$s0,\\ \text{else}
\quad \text{sub }\$v0,\\ \$s0,\\ \$a0
\quad \text{j abs\_exit}
\text{else:}
\quad \text{add }\$v0,\\ \$s0,\\ \$a0
\text{abs\_exit:}
\quad \text{jr }\$ra
Raciocínio:
  • Aqui aparece \$s0 usado como comparador e como operando nas instruções aritméticas. Mas \$s0 não foi definido/atribuído nessa função; o código correto deve comparar com \$0 (o registrador zero) e usar \$0 nas somas/subtrações como nas outras alternativas. Portanto (d) usa registradores errados e produz um comportamento indefinido/errado (depende do valor arbitrário em \$s0). Logo (d) está incorreta.

Passo 7

Comparando todas as alternativas e resumindo:
  • (a) faz: se \$a0 \ge \$0 salta para else (retorna \text{num}); se não, faz \$v0=\$0-\$a0 (retorna -\text{num}). Corresponde exatamente ao comportamento de C.
  • (b) e (c) têm a lógica invertida ou rótulos posicionados de forma que o fluxo fica errado.
  • (d) usa registrador \$s0 sem inicialização, portanto está errado.
    Conclusão: a alternativa correta é a (a).

Resposta

a)

Exercícios relacionados