Ybadoo - Soluções em Software Livre
Turmas
2º Semestre de 2023

Questão 01

Desenvolva um programa em Simpletron Machine Language, que apresente o Máximo Divisor Comum (MDC) entre dois números. Por exemplo, caso os valores fornecidos pelo usuário sejam 18 e 60, o programa deverá apresentar como resposta o valor 6. Caso o usuário forneça valores inválidos (menores ou iguais a zero), o programa deverá apresentar como resposta o valor -1.

Mais informações sobre o Máximo Divisor Comum em Wikipédia.

Questão 01 da Segunda Avaliação
PosiçãoPalavraInstrução
00+1021read A
01+2021load A
02+4117branch negative to 17
03+4217branch zero to 17
04+1022read B
05+2022load B
06+4117branch negative to 17
07+4217branch zero to 17
08+2021load A
09+3422module B
10+2123store C
11+2022load B
12+2121store A
13+2023load C
14+2122store B
15+4219branch zero to 19
16+4008branch to 08
17+1124write -1
18+4020branch to 20
19+1121write A
20+4300halt
21+0000variable A
22+0000variable B
23+0000variable C
24-0001constant -1
Welcome to Simpletron!

Questão 02

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 → T+E | T-E | T
T → F*T | F/T | F
F → a | b | c | d | e | f}
  1. 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.
  2. 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.
  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 03

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 → E+T | E-T | T
T → T*F | T/F | 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

Uma representação intermediária do programa fonte pode ser gerada com a transformação da árvore de derivação em um segmento de código. Em relação à etapa de geração de código intermediário do compilador, analise as seguintes assertivas.

  1. Uma das vantagens da aplicação da fase de geração de código intermediário é a possibilidade da realização de otimização e a tradução do código para diversas máquinas.
  2. Árvores de sintaxe e códigos de três endereços são algumas das possibilidades de representação intermediária.
  3. Na geração de código intermediário, são realizadas tarefas como seleção de instruções, alocação e atribuição de registradores e escalonamento de instruções que dependem do conhecimento da máquina-alvo para a qual será gerado o código objeto.
  4. Apesar da geração de código intermediário tornar a implementação do compilador mais portável, já que o código intermediário pode ser traduzido para várias arquiteturas diferentes, o código intermediário é geralmente mais difícil de ser otimizado já que ainda está muito longe do código alvo final.

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

Considere o seguinte programa escrito na sintaxe C:

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

void main()
{
int x, y;

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

xpto(x, y, y + 2, x + 3);

printf("%d %d", x, 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 48 e 99.
  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 8 e 4.
  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 15 e 33.
  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 24 e 30.

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 06

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 = (c + e - f) / (a * b);
y = (c + e) - d / a * b;
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 → E+T | E-T | T
T → T*V | T/V | V
V → (E) | F
F → a | b | c | d | e | f | x | y | z}
Código de três endereços, gerado em pós-ordem, representado por quádruplas
 operarg1arg2result
(0)+ceT1
(1)-T1fT2
(2)*abT3
(3)/T2T3T4
(4)=T4 x
(5)/daT5
(6)*T5bT6
(7)-T1T6T7
(8)=T7 y
(9)-efT8
(10)*T5T8T9
(11)=T9 z
Código de três endereços, gerado em pré-ordem, representado por quádruplas
 operarg1arg2result
(0)*abT1
(1)+ceT2
(2)-T2fT3
(3)/T3T1T4
(4)=T4 x
(5)/daT5
(6)*T5bT6
(7)-T2T6T7
(8)=T7 y
(9)-efT8
(10)*T5T8T9
(11)=T9 z

Questão Extra

Apresente o código objeto resultante do código de três endereços otimizado obtido na Questão 06.

Código objeto resultante do código de três endereços, gerado em pós-ordem

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

Código objeto resultante do código de três endereços, gerado em pré-ordem

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