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

Questão 01

Para desempenhar suas tarefas, um compilador deve executar dois tipos de atividade. A primeira atividade é a análise do código fonte, onde a estrutura e significado do programa de alto nível são reconhecidos. A segunda atividade é a síntese do programa equivalente em linguagem simbólica. Após realizada a análise do código fonte, na fase de síntese, o compilador deverá gerar o código em linguagem simbólica equivalente ao código analisado. Analise as seguintes afirmativas sobre a fase de síntese de um compilador.

  1. De acordo com Aho (2008), o problema de gerar um código "ótimo" é que não pode ser solucionado, contudo é possível garantir, com a aplicação de técnicas de otimização, um código bom.
  2. 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.
  3. O processo de otimização de código desenvolve-se em duas fases, uma que inclui técnicas para eliminar atribuições redundantes e suprimir subexpressões comuns, e outra, que inclui a troca de instruções de máquina por instruções mais rápidas e da melhor utilização de registradores.
  4. 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 está sendo gerado o código objeto.

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

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, g, h, =, +, -, *, /}, 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 | g | h}
  1. A notação pré-fixada da expressão aritmética a = b + c * d / e - f + g * h é = a + b - / * c d e + f * g h.
  2. A notação pós-fixada da expressão aritmética a = b + c * d / e - f + g * h é a b c d * e / f g h * + - + =.
  3. A notação pré-fixada da expressão aritmética a = b + c * d / e - f + g * h é = a + b - * c / d e + f * g h.
  4. A notação pós-fixada da expressão aritmética a = b + c * d / e - f + g * h é a b c d e / * f g h * + - + =.

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

Dado o trecho de programa a seguir:

int a, b;

void xpto (T1 int x, T2 int y)
{
int z = x + a;
x = y + 2;
y = y + z;
}

void main()
a = 3;
b = 2;
xpto(a, b);
printf("%d %d", a, b);
}

Onde T1 e T2 indicam mecanismos de passagem de parâmetros (por valor ou por referência). A tabela a seguir deve ser preenchida com os valores a serem impressos pelo programa para cada combinação de T1 e T2.

T1
valorreferência
T2valor  
referência  

Qual das alternativas abaixo preenche a tabela acima com os valores a serem impressos pelo trecho de programa?

a.

T1
valorreferência
T2valor3   24   8
referência3   84   2

b.

T1
valorreferência
T2valor3   22   4
referência3   88   4

c.

T1
valorreferência
T2valor3   84   2
referência3   24   8

d.

T1
valorreferência
T2valor3   24   2
referência3   84   8

e.

T1
valorreferência
T2valor3   24   2
referência4   24   8

Questão 04

Considere o programa escrito em Simpletron Machine Language, apresento a seguir.

Programa em Simpletron Machine Language
PosiçãoPalavraInstrução
00+1017read N
01+2017load N
02+4114branch negative to 14
03+4214branch zero to 14
04+3317multiply N
05+3018add S
06+2118store S
07+2017load N
08+3016add -1
09+2117store N
10+4212branch zero to 12
11+4004branch to 04
12+1118write S
13+4300halt
14+1116write -1
15+4300halt
16-0001variable -1
17+0000variable N
18+0000variable S

Com base no programa apresentado, avalie as assertivas a seguir.

  1. Caso o valor fornecido pelo usuário seja 2, o valor impresso pelo programa será 5.
  2. Caso o valor fornecido pelo usuário seja 3, o valor impresso pelo programa será 14.
  3. Caso o valor fornecido pelo usuário seja 4, o valor impresso pelo programa será 24.
  4. Caso o valor fornecido pelo usuário seja 5, o valor impresso pelo programa será 120.

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

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 não otimizado da seguinte sequência de comandos, sobre a gramática livre de contexto G, utilizando a notação pós-fixada.

a = d + e – f * g + h;
b = e – f * g / h;
c = d + e + g / h;
G = ({A, E, T, F}, {a, b, c, d, e, f, g, h, =, +, -, *, /}, 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 | g | h }
Código de três endereços, representado por quádruplas
 operarg1arg2result
(0)+deT1
(1)*fgT2
(2)-T1T2T3
(3)+T3hT4
(4)=T4 a
(5)*fgT5
(6)/T5hT6
(7)-eT6T7
(8)=T7 b
(9)+deT8
(10)/ghT9
(11)+T8T9T10
(12)=T10 c

Questão 06

Um grafo acíclico dirigido também é uma representação intermediária de um compilador, sendo utilizado para a identificação de subexpressões comuns existentes no mesmo bloco básico. Apresente o código de três endereços otimizado, após a construção do grafo acíclico dirigido para blocos básicos, no código de três endereços não otimizado elaborado na Questão 5.

Código de três endereços, representado por quádruplas
 operarg1arg2result
(0)+deT1
(1)*fgT2
(2)-T1T2T3
(3)+T3hT4
(4)=T4 a
(5)/T2hT5
(6)-eT5T6
(7)=T6 b
(8)/ghT7
(9)+T1T7T8
(10)=T8 c

Questão Extra

Apresente o código objeto resultante do código de três endereços otimizado obtido na Questão 6, utilizando no máximo cinco registradores (R0 a R4).

Código objeto resultante do código de três endereços otimizado obtido na Questão 6
Código objetoComentárioR0R1R2R3R4
LOAD d, R0R0 = dd    
LOAD e, R3R3 = ed  e 
ADD R3, R0R0 = R0 + R3 (d + e)(d + e)  e 
COPY R0, R1R1 = R0 (d + e)(d + e)(d + e) e 
LOAD f, R2R2 = f(d + e)(d + e)fe 
LOAD g, R4R4 = g(d + e)(d + e)feg
MUL R4, R2R2 = R2 * R4 (f * g)(d + e)(d + e)(f * g)eg
SUB R2, R1R1 = R1 - R2 ((d + e) - (f * g))(d + e)((d + e) - (f * g))(f * g)eg
LOAD h, R4R4 = h(d + e)((d + e) - (f * g))(f * g)eh
ADD R4, R1R1 = R1 + R4 (((d + e) - (f * g)) + h)(d + e)(((d + e) - (f * g)) + h)(f * g)eh
STORE R1, aa = (((d + e) - (f * g)) + h)(d + e)(((d + e) - (f * g)) + h)(f * g)eh
DIV R4, R2R2 = R2 / R4 ((f * g) / h)(d + e)(((d + e) - (f * g)) + h)((f * g) / h)eh
SUB R2, R3R3 = R3 – R2 (e - ((f * g) / h))(d + e)(((d + e) - (f * g)) + h)((f * g) / h)(e - ((f * g) / h))h
STORE R3, bb = (e - ((f * g) / h))(d + e)(((d + e) - (f * g)) + h)((f * g) / h)(e - ((f * g) / h))h
LOAD g, R1R1 = g(d + e)g((f * g) / h)(e - ((f * g) / h))h
DIV R4, R1R1 = R1 / R4 (g / h)(d + e)(g / h)((f * g) / h)(e - ((f * g) / h))h
ADD R1, R0R0 = R0 + R1 ((d + e) + (g / h))((d + e) + (g / h))(g / h)((f * g) / h)(e - ((f * g) / h))h
STORE R0, cc = ((d + e) + (g / h))((d + e) + (g / h))(g / h)((f * g) / h)(e - ((f * g) / h))h