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
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:
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 é (contendo
), o valor de retorno deve ficar em
, e a instrução final de retorno da função deve ser
(voltar para o chamador). O comportamento desejado é: se
então retornar
(ou seja,
); caso contrário retornar
.
Informações relevantes do enunciado e do problema que usaremos: o parâmetro de entrada é
Passo 2
Breve “aula” prática sobre convenção e instruções que usamos aqui (explicação didática):
- Registradores usados comumente:
-
: primeiro argumento da função (aqui contém ). -
: local onde colocamos o valor de retorno. -
: registrador que guarda o endereço de retorno (usado por ). -
: registrador que sempre contém o valor zero (constante 0).
-
- Instruções aritméticas simples:
-
significa , ou seja . -
significa , ou seja .
-
- Instruções de desvio (branch):
-
faz o salto para se . -
faz o salto para se .
Explicando em palavras: para implementar o iftemos 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):
Código da alternativa (a) (respeitando a escrita dada):
Raciocínio passo a passo para (a):
- A instrução
diz: "se (ou seja, ) salte para o rótulo ". - Se
, o salto leva diretamente ao rótulo e ali executa , que coloca em — exatamente o que queremos para o ramo else. - Se
, o salto NÃO é tomado, então o fluxo cai na instrução seguinte imediatamente após o branch, que é . Essa instrução calcula e coloca em — exatamente o que queremos para o ramo then (quando num < 0). Em seguida pula para a saída e faz .
Portanto (a) produz o comportamento correto: quandoretorna ; quando retorna .
Passo 4
Análise da alternativa (b):
Código (b):
Código (b):
Raciocínio:
-
salta para quando (isto é, quando ). - Se
, o salto vai para e executa , que retorna (valor negativo) — isso é errado: quando devemos retornar , não . - Se
, o salto NÃO é tomado, caímos na e retornamos 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):
Código (c):
Raciocínio atento à posição do rótulo:
- A instrução
salta para o rótulo se . - Observe a ordem textual: logo após o branch vem uma instrução
seguida de um , e só depois aparece o rótulo com a . - Se o branch for tomado (isto é,
), o salto vai para o rótulo que está localizado depois da e do ; assim, o salto leva ao bloco que faz — retornando quando , o que está errado. - Se o branch NÃO for tomado (isto é,
), cai-se na e retorna-se (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):
Código (d):
Raciocínio:
- Aqui aparece
usado como comparador e como operando nas instruções aritméticas. Mas não foi definido/atribuído nessa função; o código correto deve comparar com (o registrador zero) e usar 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 ). Logo (d) está incorreta.
Passo 7
Comparando todas as alternativas e resumindo:
- (a) faz: se
salta para else (retorna ); se não, faz (retorna ). 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
sem inicialização, portanto está errado.
Conclusão: a alternativa correta é a (a).
Resposta
a)