(Deitel, 2003) Considere o programa escrito em Simpletron Machine Language.
Posição | Palavra | Instrução |
---|---|---|
00 | +1024 | read N |
01 | +2024 | load N |
02 | +4119 | branch negative to 19 |
03 | +4219 | branch zero to 19 |
04 | +2023 | load constant 3 |
05 | +3326 | multiply K |
06 | +2125 | store A |
07 | +3326 | multiply K |
08 | +3025 | add A |
09 | +3022 | add constant 1 |
10 | +3027 | add Y |
11 | +2127 | store Y |
12 | +1127 | write Y |
13 | +2026 | load K |
14 | +3022 | add constant 1 |
15 | +2126 | store K |
16 | +3124 | subtract N |
17 | +4104 | branch negative to 04 |
18 | +4300 | halt |
19 | +1121 | write constant -1 |
20 | +4300 | halt |
21 | -0001 | constant -1 |
22 | +0001 | constant 1 |
23 | +0003 | constant 3 |
24 | +0000 | variable N |
25 | +0000 | variable A |
26 | +0000 | variable K |
27 | +0000 | variable Y |
Com base no programa apresentado, avalie as asserções a seguir.
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.
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, A → B, B → C) 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. Apresente o grafo de sintaxe da expressão a = (a + b) * c * (a + b) * c sobre a gramática livre de contexto G2.
G2 = ({A, E, T, F, V}, {a, b, c, =, +, -, *, /, (, )}, P2, A)
P2 = {A → V=E
E → T+E | T-E | T
T → F*T | F/T | F
F → (E) | V
V → a | b | c}
Se E1 e E2 são expressões pós-fixadas e q é um operador binário, então, E1 E2 q é a representação pós-fixada para a expressão E1 q E2. Se, por outro lado, E1 e E2 são expressões pré-fixadas, então q E1 E2 é a representação pré-fixada para a expressão E1 q E2. Notações pós e pré-fixadas podem ser generalizadas para operadores n-ários. Para a avaliação de expressões pós-fixadas, pode-se utilizar uma pilha e um processo que age do seguinte modo: lê a expressão da esquerda para a direita, empilhando cada operando até encontrar um operador. Encontrando um operador n-ário, aplica o operador aos n operandos do topo da pilha. Processamento semelhante pode ser aplicado para avaliação de expressões pré-fixadas; nesse caso, a expressão é lida da direita para a esquerda. Conforme exposto, qual das alternativas é a correta para a expressão numérica a = (a - (b * c)) / d + (a - (b * c)) * d considerando a gramática livre de contexto G3.
G3 = ({A, E, T, F, V}, {a, b, c, d, e, f, g, =, +, -, *, /, (, )}, P3, A)
P3 = {A → V=E
E → E+T | E-T | T
T → T*F | T/F | F
F → (E) | V
V → a | b | c | d | e | f | g}
a. a notação pós-fixada correspondente é a a b c * - d a b c d * - * / + =.
b. a notação pré-fixada correspondente é = + / - a a * b c d * - a * b c d.
c. a notação pós-fixada correspondente é a a b c * - d / a b c d * - * + =.
d. a notação pré-fixada correspondente é = a + / - * a b c d * - * a b c d.
e. a notação pós-fixada correspondente é a a b c * - d / a b c * - d * + =.
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 G4.
x = a + b + c;
y = a + b * c + d + e;
z = c + d / a + b;
G4 = ({A, E, T, F, V}, {a, b, c, d, e, f, x, y, z, =, +, -, *, /, (, )}, P4, A)
P4 = {A → V=E
E → E+T | E-T | T
T → T*F | T/F | F
F → (E) | V
V → a | b | c | d | e | f | x | y | z}
oper | arg1 | arg2 | result | |
---|---|---|---|---|
(0) | + | a | b | T1 |
(1) | + | T1 | c | T2 |
(2) | = | T2 | x | |
(3) | * | b | c | T3 |
(4) | + | a | T3 | T4 |
(5) | + | T4 | d | T5 |
(6) | + | T5 | e | T6 |
(7) | = | T6 | y | |
(8) | / | d | a | T7 |
(9) | + | c | T7 | T8 |
(10) | + | T8 | b | T9 |
(11) | = | T9 | z |
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 grafo acíclico dirigido para blocos básicos, do código de três endereços não otimizado elaborado na questão 04.
Com o grafo acíclico dirigido para blocos básicos produzido na questão 05, onde foram identificados as subexpressões comuns existentes no bloco básico considerado, apresente o código de três endereços otimizado, o qual futuramente será convertido em código objeto.
oper | arg1 | arg2 | result | |
---|---|---|---|---|
(0) | + | a | b | T1 |
(1) | + | T1 | c | T2 |
(2) | = | T2 | x | |
(3) | * | b | c | T3 |
(4) | + | a | T3 | T4 |
(5) | + | T4 | d | T5 |
(6) | + | T5 | e | T6 |
(7) | = | T6 | y | |
(8) | / | d | a | T7 |
(9) | + | c | T7 | T8 |
(10) | + | T8 | b | T9 |
(11) | = | T9 | z |
(Price, 2005) Considere o seguinte programa escrito na sintaxe Pascal:
program main;
var a, b : integer;
procedure p(x, y, z : integer);
begin
y := y + 1;
z := z + x;
end;
begin
a := 2;
b := 3;
p(a + b, a, a);
write(a);
end.
Com base no programa apresentado, avalie as asserções a seguir.
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.
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). Conforme exposto, o código objeto apresentado a seguir é equivalente a qual comando de atribuição?
LOAD c, R0
LOAD d, R1
MUL R1, R0
LOAD b, R1
COPY R1, R2
ADD R0, R1
LOAD a, R1
SUB R2, R1
ADD R0, R1
STORE R1, y
a. y = b + c * d
b. y = (a - b) + (c * d)
c. y = (a - b) - (b + c * d)
d. y = (a - b) + (b + c * d)
e. y = (a - b) - (a - b + c * d)