Construção do executável1 Construção de ficheiros executáveis Compilação Ligação...

23
Construção do executável 1 Construção de ficheiros Construção de ficheiros executáveis executáveis Compilação Ligação Carregamento (loading) Bibliotecas estáticas e dinâmicas

Transcript of Construção do executável1 Construção de ficheiros executáveis Compilação Ligação...

Page 1: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 1

Construção de ficheiros Construção de ficheiros executáveisexecutáveis

CompilaçãoLigação

Carregamento (loading)Bibliotecas estáticas e dinâmicas

Page 2: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 2

Construção e execução de programasConstrução e execução de programasConstrução e execução de programasConstrução e execução de programas

Compilador Linker

dados

código

stack

Loader

Memória(espaço lógico ou virtual)

Ficheirosfonte

Bibliotecasexternas

00101 11010 00101

obj

00101 11010 00101

obj

00101 11010 00101

obj

00101 11010 00101

exe

00101 11010 00101

lib

Unidades decompilação

Page 3: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 3

Ligação de unidades de compilaçãoLigação de unidades de compilaçãoLigação de unidades de compilaçãoLigação de unidades de compilação

...int x;

void main( ){...foo( )...x = ......}

...int y;

...void foo( ){ y = x; ... bar( )}

void bar( ){ ...}

Código main: ... r1 &foo ... call foo ... r2 x (300) ...

Dados ... x: ...

Importações

Exportações

Recolocações

foo

x

x

80

0h

30

0h

50

0h

Código foo: r1 x r2 y (400) ... call bar (1000) ... bar: ...

Dados ... y: ...

Importações

Exportações

Recolocações

x

foobary

bary

16

00

h

40

0h

60

0h

10

00

h

40

0h

Page 4: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 4

Ligação de unidades de compilação Ligação de unidades de compilação (cont.)(cont.)

Ligação de unidades de compilação Ligação de unidades de compilação (cont.)(cont.)

Código main: ... r1 &foo (c00) ... call foo (c00) ... r2 x (2300) ... foo: r1 x (2300) r2 y (2900) ... call bar (1800) ... bar: ...

Dados ... x: ... y: ...

1e

00

h

c00

h1

80

0h

20

00

hb

00

h

90

0h 30

0h

Imagem executável

Dados

Heap

Código

Serviços do SO

Stack

bibliotecasdinâmicas

Memória(lógica ou virtual)

“Loading”

4 G

B

endereçoscrescentes

Page 5: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 5

Bibliotecas estáticas e dinâmicasBibliotecas estáticas e dinâmicasBibliotecas estáticas e dinâmicasBibliotecas estáticas e dinâmicas Bibliotecas estáticas

O código é incorporado no ficheiro executável pelo “linker”Se a mesma biblioteca for usada por vários programas o código é

repetido nos ficheiros executáveisO código também é repetido na memória nos vários processos que

as utilizaremSimples de criar e com execução ligeiramente mais rápida

Bibliotecas dinâmicasO código reside apenas no ficheiro da bibliotecaÉ carregado e mapeado no processo quando da execução de um

programaO código é partilhado por todos os processos que o utilizam (pode

haver diversas cópias dos dados)“Loading” e inicialização mais complicados e demoradosLigeiramente menos eficientes

Page 6: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 6

Bibliotecas dinâmicasBibliotecas dinâmicasBibliotecas dinâmicasBibliotecas dinâmicas

.

.

.

.

.

.

Código DLL

CódigoCódigo

Dados Dados

Código DLL Código DLLDados proc. 1

Dados proc. 2Dados DLL Dados DLL

Memória físicaMapeamento(tabelas de

páginas)

Mapeamento(tabelas de

páginas)

Memória lógica(processo 1)

Memória lógica(processo 2)

Page 7: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Construção do executável 7

Bibliotecas dinâmicas - Bibliotecas dinâmicas - implementaçãoimplementação

Bibliotecas dinâmicas - Bibliotecas dinâmicas - implementaçãoimplementação

...---call foo: push gp t9 *(gp+A) jalr t9 pop gp

---load x: t0 *(gp+C)

---load y: t0 *(gp+B) t0 *t0...

x

gpAB

C

...foo: gp t9+E-D......---load y: t0 *(gp+F) t0 *t0...

y

gpF

D

E

tabela deligação

(linkage table)

1 cópia porprocesso

1 cópia porprocesso

(adjacente)

código da DLL(partilhado)

Page 8: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 8

Organização da memória em Organização da memória em run-run-timetime

Memória de dadosRegistos de activação

Procedimentos embutidos e acessos não locais

Passagem de parâmetros

Page 9: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 9

Execução de programasExecução de programasExecução de programasExecução de programas Geralmente é possível fazer as seguintes suposições acerca

da execução de um programa:Alguns blocos de código constituem procedimentos (ou funções) que

podem ser invocados de diversos locais no programa;Quando um procedimento é invocado, o controlo regressa após a sua

execução, ao ponto imediatamente após a invocação; Esta suposição leva a que o fluxo de controlo entre procedimentos possa

ser modelizado através de uma árvore.

Os procedimentos podem conter dados locais e também (de forma embutida) outros procedimentos (nalgumas linguagens).

Durante a execução de um procedimento constitui-se o que se designa por uma activação do procedimento.

Num dado instante podem existir várias activações de procedimentos (inclusivé do mesmo, em linguagens recursivas).

Page 10: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 10

Algumas definiçõesAlgumas definiçõesAlgumas definiçõesAlgumas definições Tempo de vida de uma activação de procedimento: intervalo

durante o qual essa activação existe; compreende:a execução de todas as instruções do procedimento;os tempos de vida das activações dos procedimentos invocados por

ele.

Tempo de vida de uma variável: intervalo durante o qual existe o espaço de memória necessário ao armazenamento dos valores associados à variável; se a variável for local a um procedimento, a regra é fazer corresponder o seu tempo de vida ao tempo de vida da activação do procedimento (há excepções).

A associação de um nome ao local de armazenamento, e a associação deste local ao seu conteúdo (valor), designam-se genericamente por binding (ligação) da variável.

O scope (alcance) de uma variável, é o conjunto de locais, no código, onde é possível aceder a essa variável.

Noções estáticasNoções estáticas Noções dinâmicas (execução)Noções dinâmicas (execução)

procedimentoprocedimento activaçãoactivaçãonomenome bindingbindingscopescope tempo de vidatempo de vida

Page 11: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 11

ExemploExemploExemploExemploprogram sort;program sort; var a : array[0..10] of integer; var a : array[0..10] of integer;

procedure readarray;procedure readarray; var i : integer; var i : integer; begin begin for i:=1 to 9 do read(a[i]) for i:=1 to 9 do read(a[i]) end; end;

function partition(y, z : integer) : integer;function partition(y, z : integer) : integer; var i, j, x, v : integer; var i, j, x, v : integer; begin … begin … end; end;

procedure quicksort(m, n : integer);procedure quicksort(m, n : integer); var i : integer; var i : integer; begin begin if (n > m) then begin if (n > m) then begin i := partition(m, n); i := partition(m, n); quicksort(m, i-1); quicksort(i+1, n) quicksort(m, i-1); quicksort(i+1, n) end end end; end;

beginbegin a[0] := -9999; a[10] := 9999; a[0] := -9999; a[10] := 9999; readarray; readarray; quicksort(1, 9) quicksort(1, 9) end. end.

s

r q(1,9)

p(1,9) q(1,3) q(5,9)

p(1,3) q(1,0) q(2,3) p(5,9) q(5,5) q(7,9)

p(2,3) q(2,1) q(3,3) p(7,9) q(7,7) q(9,9)

Árvore de activação para o programa escrito ao ladoÁrvore de activação para o programa escrito ao lado

Em cada instante só existem os registos de activação de Em cada instante só existem os registos de activação de procedimentos que estão no caminho desde a raiz até ao procedimentos que estão no caminho desde a raiz até ao que está em execução no momento.que está em execução no momento.

Quando a activação da chamada quicksort(2,3) (q(2,3)) está Quando a activação da chamada quicksort(2,3) (q(2,3)) está em execução apenas existem as activações de s, q(1,9) e em execução apenas existem as activações de s, q(1,9) e q(1,3).q(1,3).

Page 12: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 12

Organização da memória de dadosOrganização da memória de dadosOrganização da memória de dadosOrganização da memória de dados A organização da memória de dados depende grandemente

da resposta às seguintes perguntas, para uma dada linguagem:A linguagem é recursiva ?O que acontece aos nomes locais quando termina a activação de um

procedimento ?Um procedimento pode aceder a nomes não locais ?Como são passados os parâmetros de um procedimento ?É possível passar procedimentos como parâmetros ?É possível retornar um procedimento como resultado ?É possível alocar memória dinamicamente ?É necessário libertar explicitamente memória alocada

dinamicamente ? Para a maioria das linguagens actualmente em utilização,

as activações dos procedimentos é perfeitamente embutida pelo que é comum adoptar-se uma organização geral destas activações baseada numa stack (geralmente suportada directamente pelo hardware do processador).

Page 13: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 13

Organização da memória de dados Organização da memória de dados (cont.)(cont.)

Organização da memória de dados Organização da memória de dados (cont.)(cont.)

Dados estáticosDados estáticos - Esta parte da memória contém os - Esta parte da memória contém os dados globais (constantes e variáveis inicializadas ou dados globais (constantes e variáveis inicializadas ou não) cujo tamanho pode ser determinado inteiramente não) cujo tamanho pode ser determinado inteiramente durante a compilação. Na compilação geram-se durante a compilação. Na compilação geram-se apenas “offsets” para o início desta área de memória.apenas “offsets” para o início desta área de memória.

StackStack - Implementado no stack suportado - Implementado no stack suportado directamente pelo processador; contém os directamente pelo processador; contém os chamados registos de activação dos procedimentos, chamados registos de activação dos procedimentos, refletindo a estrutura intrínseca das suas chamadas e refletindo a estrutura intrínseca das suas chamadas e retornos; as variáveis locais dos procedimentos são retornos; as variáveis locais dos procedimentos são criadas e destruídas nesta área.criadas e destruídas nesta área.

HeapHeap - Área utilizada para todo o restante - Área utilizada para todo o restante armazenamento de dados. São colocados aqui os armazenamento de dados. São colocados aqui os dados alocados dinamicamente, ou variáveis locais dados alocados dinamicamente, ou variáveis locais cujo tamanho só é conhecido durante a execução, ou cujo tamanho só é conhecido durante a execução, ou ainda cujo tempo de vida não se coaduna com o ainda cujo tempo de vida não se coaduna com o armazenamento nos registos de activação.armazenamento nos registos de activação.

códigoendereçosmais baixos

endereçosmais altos

dados estáticosou globais

stack

heap

Page 14: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 14

Registos de activaçãoRegistos de activaçãoRegistos de activaçãoRegistos de activação

Chamada de procedimento:Chamada de procedimento:

……push parpush parnn

……push parpush par11

push accesspush accesscall proccall procadd sp,n1add sp,n1……

No procedimento proc:No procedimento proc:

push bppush bpmov bp,sp código demov bp,sp código desub sp,n2 entradasub sp,n2 entradapushapusha…………popapopaadd sp,n2 códigoadd sp,n2 códigopop bp de saídapop bp de saídaretret

valor de retorno

parâmetrosdo

procedimento

apontador de acesso

endereço de retorno

salvaguardade registos doprocessador

dados locais

temporários

apontador de controloregisto deactivação

apontador de controlo

frame pointer(bp)

stack pointer(sp)

chamador

hardware

chamado

Page 15: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 15

Alocação de registos de activaçãoAlocação de registos de activaçãoAlocação de registos de activaçãoAlocação de registos de activação Consideram-se geralmente três estratégias diferentes

para alocação dos registos de activação dos procedimentos:Alocação estática, onde os registos de activação de todos os

procedimentos são colocados na zona de dados estáticos;Este tipo de alocação só é possível se a linguagem não for recursiva e mantiver os valores das variáveis locais de umas chamadas para as outras;

Alocação na stack, a mais geralmente utilizada;Alocação no heap, necessária para quando o tempo de vida das

variáveis locais ultrapassa o da activação do respectivo procedimento, ou quando este ultrapassa o do chamador.

Considere-se o seguinte código em pseudo-Considere-se o seguinte código em pseudo-C:C:

int (*)() f(int x) {int (*)() f(int x) { int g(int y) {return x+y} int g(int y) {return x+y} return g; return g;}}

main() {main() { int (*h)() = f(3); int (*h)() = f(3); int (*j)() = f(4); int (*j)() = f(4); int z = h(5); int z = h(5); int w = j(7); int w = j(7);}}

O registo de activação de f() não pode ser O registo de activação de f() não pode ser descartado após as chamadas f(3) e f(4), descartado após as chamadas f(3) e f(4), porque a função g() no seu interior depende porque a função g() no seu interior depende do parâmetro com que f() foi chamado.do parâmetro com que f() foi chamado.

A linguagem ML permite estas construções.A linguagem ML permite estas construções.

Page 16: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 16

Alocação na stackAlocação na stackAlocação na stackAlocação na stackÉ a forma mais utilizada de alocação

dos registos de activação;

Pode requerer espaços para a stack consideráveis;

Os parâmetros devem ser colocados na stack pela ordem inversa, se se permitirem definições de procedimentos com número variável de argumentos (a la C);

Requer acesso indirecto se existirem parâmetros cujo comprimento dependa de um valor passado como parâmetro (ex: passagem de arrays em Algol e arrays conformantes em Pascal).

valor de retorno

parâmetrosdo

procedimento

apontador de acesso

endereço de retorno

salvaguardade registos doprocessador

dados locais

temporários

apontador de controlo frame pointer(bp)

stack pointer(sp)

array A

apontador para A

procedure p(A : array[ j..k : integer ] of integer ) begin var i : integer; for i := j to k do A[ i ] := 2*i; end;

Page 17: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 17

Acesso a variáveis não locaisAcesso a variáveis não locaisAcesso a variáveis não locaisAcesso a variáveis não locais Grande parte das linguagens utiliza o que se designa por

estrutura de blocos; os blocos estão embutidos uns nos outros;

O scope (alcance) de uma variável, numa estrutura de blocos, está sujeito à regra do embutimento mais próximo. Assim:O scope de uma declaração num bloco B abrange todo o bloco B;Um nome x, acedido em B mas não declarado em B, pertencerá ao

scope de uma declaração de x num bloco mais externo B’, que contenha essa declaração e seja o bloco mais próximo de B (de dentro para fora)

Algumas linguagens não permitem o embutimento de funçõesB0B0 B1B1

B2B2

B3B3

Neste tipo de blocos inseridos dentro dos Neste tipo de blocos inseridos dentro dos procedimentos, só existe um registo de activação procedimentos, só existe um registo de activação para todos os blocos:para todos os blocos:

aa00

bb00

bb11

aa22, b, b33

Variáveis locais a Variáveis locais a main( )main( )

main() {main() { int a, b; int a, b; { int b; { int b; { int a; { int a; … } … } { int b; { int b; … } … } … } … }… }… }

Page 18: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 18

Acesso a variáveis não locais Acesso a variáveis não locais (embutidas)(embutidas)

Acesso a variáveis não locais Acesso a variáveis não locais (embutidas)(embutidas)

Nas linguagens em que é permitido o embutimento de Nas linguagens em que é permitido o embutimento de procedimentos há necessidade de aceder a variáveis procedimentos há necessidade de aceder a variáveis locais existentes em registos de activação anteriores.locais existentes em registos de activação anteriores.

Esses registos são acedidos através de um apontador Esses registos são acedidos através de um apontador de acesso que funciona como mais um parâmetro de acesso que funciona como mais um parâmetro (escondido) nas chamadas dos procedimentos.(escondido) nas chamadas dos procedimentos.

No entanto esses registos podem não estar contíguos No entanto esses registos podem não estar contíguos na stack. Vejam-se os seguintes exemplos:na stack. Vejam-se os seguintes exemplos:

program sort;program sort; var a : array[0..10] of integer; var a : array[0..10] of integer; x : integer; x : integer;

procedure readarray;procedure readarray; var i : integer; var i : integer; begin … a … end; begin … a … end;

procedure exchange(i, j : integer);procedure exchange(i, j : integer); begin begin x := a[i]; a[i] := a[j]; a[j] := x x := a[i]; a[i] := a[j]; a[j] := x end; end;

procedure quicksort(m, n : integer);procedure quicksort(m, n : integer); var k, v : integer; var k, v : integer;

function partition(y, z : integer) : integer;function partition(y, z : integer) : integer; var i, j : integer; var i, j : integer; begin begin … a … v … exchange(i, j); … … a … v … exchange(i, j); … end; end;

begin … end;begin … end;

begin … end.begin … end.

s

a, x

acesso

nil

q(1, 9)

k, v

s

a, x

acesso

nil

q(1, 3)

k, v

acessoq(1, 9)

k, v

acessop(1, 3)

i, j

s

a, x

acesso

nil

q(1, 3)

k, v

acessoq(1, 9)

k, v

acessop(1, 3)

i, j

s

a, x

acesso

nil

q(1, 3)

k, v

acessoq(1, 9)

k, v

acessoe(1, 3)

Page 19: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 19

Uso dos apontadores de acessoUso dos apontadores de acessoUso dos apontadores de acessoUso dos apontadores de acessoDefine-se profundidade de embutimento de um procedimento como

o número de níveis de embutimento que é necessário transpor para chegar a esse procedimento; os procedimentos mais externos têm profundidade 1; no exemplo anterior temos sort - 1, exchange - 2, e partition - 3.

Estabelcimento dos apontadores de acesso:

Utilização dos apontadores de acesso:

Os apontadores de acesso são colocados na stack (registo de activação) pelo Os apontadores de acesso são colocados na stack (registo de activação) pelo procedimento chamador; Se o procedimento p com profundidade np chama o procedimento chamador; Se o procedimento p com profundidade np chama o procedimento x de profundidade nx então:procedimento x de profundidade nx então: - para np < nx (deverá ser nx = np + 1) o apontador de acesso é o apontador de controlo - para np < nx (deverá ser nx = np + 1) o apontador de acesso é o apontador de controlo (frame pointer) actual;(frame pointer) actual; - para np - para np nx o apontador de acesso a colocar na stack obtém-se seguindo np - nx + 1 nx o apontador de acesso a colocar na stack obtém-se seguindo np - nx + 1 apontadores de acesso, começando no do próprio procedimento; (ver figura anterior)apontadores de acesso, começando no do próprio procedimento; (ver figura anterior)

O procedimento p com profundidade np pretende aceder a uma variável x, declarada num O procedimento p com profundidade np pretende aceder a uma variável x, declarada num procedimento com profundidade nx; deverá sempre ser np procedimento com profundidade nx; deverá sempre ser np nx; nx; - se np = nx, então x está no registo de activação corrente; - se np = nx, então x está no registo de activação corrente; - se np > nx, então x está num registo de activação cujo endereço se obtém seguindo - se np > nx, então x está num registo de activação cujo endereço se obtém seguindonp-nx apontadores de acesso, a partir do registo de activação actual. (ver figura anterior)np-nx apontadores de acesso, a partir do registo de activação actual. (ver figura anterior)

Page 20: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 20

Procedimentos como parâmetrosProcedimentos como parâmetrosProcedimentos como parâmetrosProcedimentos como parâmetrosQuando é possível passar procedimentos como parâmetros, o

procedimento passado pode não estar na cadeia de embutimentos do procedimento que o vai usar; neste caso quando da passagem do procedimento, deve também passar-se o apontador de acesso correspondente. Veja-se o exemplo seguinte:

program param;program param;

procedure b(function h(n: integer): integer);procedure b(function h(n: integer): integer); begin writeln(h(2)) end; begin writeln(h(2)) end;

procedure c;procedure c; var m: integer; var m: integer;

function f(n: integer) : integer;function f(n: integer) : integer; begin f := m + n end; begin f := m + n end;

begin m := 0; b(f) endbegin m := 0; b(f) end

beginbegin c c end. end.

param

c

m

<f, acesso>

b

h = f

n

Page 21: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 21

ScopeScope dinâmico dinâmicoScopeScope dinâmico dinâmicoCertas linguagens não seguem as regras de Certas linguagens não seguem as regras de scopescope enunciadas atrás ( enunciadas atrás (scopescope estático ou léxico), mas estático ou léxico), mas determinam que quando há um acesso a uma variável não local, esse acesso refere-se a uma variável com o determinam que quando há um acesso a uma variável não local, esse acesso refere-se a uma variável com o mesmo nome que tenha sido criada o mais recentemente possível na stack.mesmo nome que tenha sido criada o mais recentemente possível na stack.

Se o programa seguinte utilizasse este tipo de Se o programa seguinte utilizasse este tipo de scopescope dinâmico, a sua saída seria: dinâmico, a sua saída seria: 0.250 0.125 0.250 0.125 0.250 0.125 0.250 0.125

A implementação deste A implementação deste scopescope dinâmico é imediata: em vez de se utilizarem os apontadores de acesso dinâmico é imediata: em vez de se utilizarem os apontadores de acesso utilizam-se os apontadores de controlo, que ligam os registos de activação pela ordem com que foram utilizam-se os apontadores de controlo, que ligam os registos de activação pela ordem com que foram criados; usa-se a variável que esteja definida no registo de activação que menos distar do actual.criados; usa-se a variável que esteja definida no registo de activação que menos distar do actual.

program dynamic;program dynamic; var r: real; var r: real;

procedure show;procedure show; begin writeln(r:5:3) end; begin writeln(r:5:3) end;

procedure small;procedure small; var r: real; var r: real; begin r := 0.125; show end; begin r := 0.125; show end;

beginbegin r := 0.250; r := 0.250; show; small; writeln; show; small; writeln; show; small; writeln show; small; writeln end. end.

Page 22: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 22

Passagem de parâmetros (1)Passagem de parâmetros (1)Passagem de parâmetros (1)Passagem de parâmetros (1) Passagem por valor

Uma cópia dos valores dos parâmetros é colocada nos registos de activação.

Passagem por referênciaAquilo que é colocado nos registos de activação é o endereço do

local onde sencontram os valores dos parâmetros (variáveis simples); o acesso a esses valores faz-se indirectamente; assim é possível passar para o chamador novos valores através dos parâmetros.

Passagem por copy-restore linkageO chamador passa para os registos de activação os r-values dos

parâmetros, ao mesmo tempo que toma nota dos respectivos l-values; quando a chamada regressa, e antes de eliminar os parâmetros, os respectivos valores são colocados nos l-values anteriormente calculados.

Page 23: Construção do executável1 Construção de ficheiros executáveis Compilação Ligação Carregamento ( loading ) Bibliotecas estáticas e dinâmicas.

Organização da memória em run-time 23

Passagem de parâmetros (2)Passagem de parâmetros (2)Passagem de parâmetros (2)Passagem de parâmetros (2) Passagem por nome

Aqui o que é colocado nos registos de activação são subrotinas (thunks) capazes de calcular o l-value e o r-value do parâmetro correspondente. Sempre que há um acesso ao parâmetro essa subrotina é chamada. Tudo se passa como se não houvesse qualquer chamada e o código chamado fosse colocado directamente no local de chamada (como uma macro).real procedure sum(expr, i, low, high) value low, high; real expr; integer i, low, high;begin real rtn; rtn := 0; for i := low step 1 until high do rtn := rtn + expr; sum := rtn;end sum

...y := sum(3*x*x-5*x+2, x, 1, 10);...

101

2 253x

xxy