Ybadoo - Soluções em Software Livre
Turmas
1º Semestre de 2022

Questão 01

(vale 1,0 ponto) A notação tradicional para expressões aritméticas, que representa uma operação binária na forma x + y, ou seja, com o operador entre seus dois operandos, é conhecida como notação infixada. Uma notação alternativa para esse tipo de expressão é a notação pré-fixada, na qual o operador é expresso antes de seus operandos, como por exemplo, + x y. Outra notação alternativa é a notação pós-fixada, na qual o operador é expresso após seus operandos, como por exemplo, x y +. O atrativo das notações pré-fixada e pós-fixada é que elas dispensam o uso de parênteses ao adotar a noção de pilha para a representação das expressões. Analise as assertivas a seguir, considerando a gramática livre de contexto G.

G = ({A, E, T, F}, {a, b, c, d, e, f, =, +, -, *, /}, P, A)
P = {A → F=E
E → E+T | E-T | T
T → T*F | T/F | F
F → a | b | c | d | e | f}
  1. A notação pré-fixada da expressão aritmética a = f / c + c / e - f + c - f + b é = a + / f c - / c e + f - c + f b.
  2. A notação pré-fixada da expressão aritmética a = d * b * f + d / c + f + e / a é = a + + + * * d b f / d c f / e a.
  3. A notação pós-fixada da expressão aritmética a = e * d / e - b - a * a * d / c é a e d * e / b - a a * d * c / - =.
  4. A notação pós-fixada da expressão aritmética a = a - e + a * f - e + d + c / b é a a e a f * e d c b / + + - + - =.

Quais das assertivas apresentadas estão corretas?

a. apenas as assertivas I e II.

b. apenas as assertivas I e III.

c. apenas as assertivas II e III.

d. apenas as assertivas II e IV.

e. apenas as assertivas III e IV.

Questão 02

(vale 1,0 ponto) Os principais requisitos impostos a geradores de código objeto são os seguintes: a) o código gerado deve ser correto e de alta qualidade; b) o código deve fazer uso efetivo dos recursos da máquina e; c) o código gerado deve executar eficientemente. O problema de gerar código ótimo é insolúvel (indecidível) como tantos outros. Na prática, devemos contentar-nos com técnicas heurísticas que geram bom código (não necessariamente ótimo). Diante do exposto, o código objeto apresentado a seguir é equivalente a qual comando de atribuição.

LOAD   x, R0
COPY R0, R1
LOAD y, R2
ADD R2, R0
SUB R1, R2
COPY R0, R1
DIV R1, R2
SUB R2, R0
ADD R2, R0
STORE R0, z

a. z = (y - x) / (x + y) + (y - x) / (x + y) - (x + y)

b. z = (x + y) - (y - x) / (x + y) + (y - x) / (x + y)

c. z = (x + y) - (y - x) / (x + y) + (x + y) / (y - x)

d. z = (x + y) - (x + y) / (y - x) + (y - x) / (x + y)

e. z = (x + y) / (y - x) + (y - x) / (x + y) - (x + y)

Questão 03

(vale 1,0 ponto) A geração de código intermediário é a transformação da árvore de derivação em um segmento de código. Esse código pode, eventualmente, ser o código objeto final, mas, na maioria das vezes, constitui-se num código intermediário, pois a tradução de código fonte para objeto em mais de um passo apresenta algumas vantagens. Existem vários tipos de código intermediário, como por exemplo, as representações gráficas por meio de árvores e grafo de sintaxe. Uma árvore de sintaxe é uma forma condensada de árvore de derivação na qual somente os operandos da linguagem aparecem como folhas; os operadores constituem nós interiores da árvore. Outra simplificação da árvore de sintaxe é que cadeias de produções simples (por exemplo, AB, BC) são eliminadas. Um grafo de sintaxe, além de incluir as simplificações da árvore de sintaxe, faz a fatoração das subexpressões comuns, eliminando-as. Analise as assertivas a seguir, considerando a gramática livre de contexto G.

G = ({A, E, T, F}, {a, b, c, d, e, f, =, +, -, *, /}, P, A)
P = {A → F=E
E → T+E | T-E | T
T → F*T | F/T | F
F → a | b | c | d | e | f}
  1. A expressão aritmética a = a * f / a + c - d + f / a - b teria uma das subexpressões f / a eliminada pelo grafo de sintaxe.
  2. A expressão aritmética a = f / b + e - c * f / b - c * f teria uma das subexpressões f / b eliminada pelo grafo de sintaxe.
  3. A expressão aritmética a = f / b + e - c * f / b - c * f teria uma das subexpressões c * f eliminada pelo grafo de sintaxe.
  4. A expressão aritmética a = f * b / a + f * b * d - b - c teria uma das subexpressões f * b eliminada pelo grafo de sintaxe.

Quais das assertivas apresentadas estão corretas?

a. apenas as assertivas I e II.

b. apenas as assertivas I e III.

c. apenas as assertivas II e III.

d. apenas as assertivas II e IV.

e. apenas as assertivas III e IV.

Questão 04

(vale 1,0 ponto) Considere o seguinte programa escrito na sintaxe C:

void xpto(int a, int b, int c)
{
a = b * c;
b = a + c;
}

void main()
{
int x;
int y;

scanf("%d", &x);
scanf("%d", &y);

xpto(x, y, x + 2);

printf("%d", x);
printf("%d", y);
}

Com base no programa apresentado, avalie as asserções a seguir.

  1. Caso os valores fornecidos pelo usuário sejam 5 e 6 e os parâmetros sejam passados por valor, os valores impressos serão 42 e 49.
  2. Caso os valores fornecidos pelo usuário sejam 1 e 2 e os parâmetros sejam passados por referência, os valores impressos serão 6 e 9.
  3. Caso os valores fornecidos pelo usuário sejam 2 e 3 e os parâmetros sejam passados por nome, os valores impressos serão 12 e 16.
  4. Caso os valores fornecidos pelo usuário sejam 3 e 4 e os parâmetros sejam passados por valor-resultado, os valores impressos serão 20 e 25.

A respeito dessas asserções, assinale a alternativa correta.

a. apenas as assertivas I e II.

b. apenas as assertivas I e III.

c. apenas as assertivas II e III.

d. apenas as assertivas II e IV.

e. apenas as assertivas III e IV.

Questão 05

(vale 1,0 ponto) Desenvolva um programa em Simpletron Machine Language, que verifique se o número fornecido pelo usuário é um número primo. Caso o valor fornecido pelo usuário seja um número primo, o programa deverá apresentar como resposta o valor 1. Caso o valor fornecido pelo usuário não seja um número primo, o programa deverá apresentar como resposta o valor 0. E caso o usuário forneça um valor inválido, o programa deverá apresentar como resposta o valor -1.

Mais informações sobre números primos na Wikipédia.

Questão 06 da Segunda Avaliação
PosiçãoPalavraInstrução
00+1020read N
01+2020load N
02+4114branch negative to 14
03+4214branch zero to 14
04+3122subtract 1
05+2121store D
06+3122subtract 1
07+4216branch zero to 16
08+4118branch negative to 18
09+2020load N
10+3421module D
11+4218branch zero to 18
12+2021load D
13+4004branch to 04
14+1123write -1
15+4019branch to 19
16+1122write 1
17+4019branch to 19
18+1124write 0
19+4300halt
20+0000variable N
21+0000variable D
22+0001constant 1
23-0001constant -1
24+0000constant 0
Welcome to Simpletron!

Questão 06

(vale 1,0 ponto) A fase de otimização do código intermediário vem logo após a fase de geração desse código e tem por objetivo tornar o código intermediário mais apropriado para a produção de código objeto (código de máquina) eficiente, tanto em relação ao tamanho como ao tempo de execução. Uma das técnicas de otimização de código intermediário consiste em identificar segmentos sequencias do programa, chamados blocos básicos, e representá-los através de grafos dirigidos e submetê-los a um processo de otimização. Apresente o código de três endereços otimizado da seguinte sequência de comandos, sobre a gramática livre de contexto G.

x = (a * b) / (c + e - f);
y = d / a * b - (c + e);
z = d / a * (e - f);
G = ({A, E, T, V, F}, {a, b, c, d, e, f, x, y, z, =, +, -, *, /, (, )}, P, A)
P = {A → F=E
E → T+E | T-E | T
T → V*T | V/T | V
V → (E) | F
F → a | b | c | d | e | f | x | y | z}
Código de três endereços, representado por quádruplas
 operarg1arg2result
(0)*abT1
(1)-efT2
(2)+cT2T3
(3)/T1T3T4
(4)=T4 x
(5)/dT1T5
(6)+ceT6
(7)-T5T6T7
(8)=T7 y
(9)*aT2T8
(10)/dT8T9
(11)=T9 z

Questão Extra

(vale 1,0 ponto) Apresente o código objeto resultante do código de três endereços otimizado obtido na Questão 06.

LOAD   a, R0 // R0 = a
LOAD b, R1 // R1 = b
MUL R1, R0 // R0 = R0 * R1 (a * b)
COPY R0, R1 // R1 = R0 (a * b)
LOAD e, R2 // R2 = e
LOAD f, R3 // R3 = f
SUB R3, R2 // R2 = R2 - R3 (e - f)
LOAD c, R3 // R3 = c
ADD R2, R3 // R3 = R3 + R2 (c + (e - f))
DIV R3, R0 // R0 = R0 / R3 ((a * b) / (c + (e - f)))
STORE R0, x
LOAD d, R0 // R0 = d
DIV R1, R0 // R0 = R0 / R1 (d / (a * b))
LOAD c, R1 // R1 = c
LOAD e, R3 // R3 = e
ADD R3, R1 // R1 = R1 + R3 (c + e)
SUB R1, R0 // R0 = R0 - R1 ((d / (a * b)) - (c + e))
STORE R0, y
LOAD a, R0 // R0 = a
MUL R2, R0 // R0 = R0 * R2 (a * (e - f))
LOAD d, R1 // R1 = d
DIV R0, R1 // R1 = R1 / R0 (d / (a * (e - f)))
STORE R1, z