Compiladores  
Aula 08 Geração de Código de Máquina  
Edirlei Soares de Lima  
<edirlei.lima@universidadeeuropeia.pt>  
Processo de Compilação  
unidades léxicas  
Analisador  
Léxico  
Analisador  
Sintático  
Programa-fonte  
parse trees  
(opcional)  
Gerador de Código  
Intermediário e  
Analisador  
Tabela de Símbolos  
Otimização  
Semântico  
código  
intermediário  
linguagem de máquina  
Programa Objeto  
Gerador de Código  
Processo de Compilação  
O Gerador de Código converte a versão do código intermediário  
do programa para um programa em linguagem de máquina  
equivalente.  
Geração de Código de Máquina  
Etapas:  
1. Gravar o código intermediário (Assembly) em um arquivo;  
2. Gerar o código de máquina (arquivo .exe) utilizando o NASM e GCC.  
É necessário organizar o código intermediário de acordo com  
a estrutura de um programa Assembly, separando a seção de  
dados da seção do código do programa.  
Solução: armazenar inicialmente o código intermediário em duas listas  
e depois gravar as linhas de código no arquivo Assembly.  
Listas Encadeadas em C  
Uma Lista Encadeada é uma sequência de elementos, onde  
cada elemento tem uma informação armazenada e um  
ponteiro para o próximo elemento da sequência:  
lista  
.
. .  
InfoN  
Info1  
Info2  
Info3  
Sequência encadeada de elementos, chamados de nós da lista;  
Nó da lista é representado por dois campos:  
Informação armazenada;  
Ponteiro para o próximo elemento da lista;  
A lista é representada por um ponteiro para o primeiro nó;  
O ponteiro do último elemento é NULL;  
Listas Encadeadas em C  
Estrutura:  
typedef struct element  
{
char *code;  
struct element *next;  
Element;  
}
Funções necessárias:  
Criação da lista:  
Element* CreateList();  
Inserção no final da lista:  
Element* InsertList(Element* list, char* code);  
Listas Encadeadas em C  
Criação da lista:  
Element* CreateList(){  
return NULL;  
}
Inserção no final da lista:  
Element* InsertList(Element* list, char* code){  
Element* elem = list;  
Element* nelem = (Element*)malloc(sizeof(Element));  
nelem->code = (char*)malloc(strlen(code) + 1);  
strcpy(nelem->code, code);  
nelem->next = NULL;  
if (elem == NULL)  
return nelem;  
else{  
while (elem->next != NULL){  
elem = elem->next;  
}
elem->next = nelem;  
}
return list;  
}
Geração de Código Máquina  
(Implementação)  
.
..  
void GenerateMachineCode(Node * ast)  
{
Element* datacode = CreateList();  
Element* progcode = CreateList();  
int i = 0;  
char codeline[256];  
char path[256];  
char cmd1[1024];  
char cmd2[1024];  
datacode = InsertList(datacode, "SECTION .data\n");  
datacode = InsertList(datacode, "formatout: db \"%d\", 10, 0\n");  
progcode = InsertList(progcode, "SECTION .text\n");  
progcode = InsertList(progcode, "global _main\n");  
progcode = InsertList(progcode, "extern _printf\n");  
progcode = InsertList(progcode, "_main :\n");  
GenerateCode(ast, datacode, progcode);  
.
..  
Geração de Código Máquina  
Implementação)  
(
Executando o NASM e GCC:  
.
..  
getcwd(path, sizeof(path));  
chdir("C:\\MinGW\\bin\\");  
sprintf(cmd1, "C:\\MinGW\\bin\\nasm.exe -f win32 %s\\code.asm", path);  
system(cmd1);  
sprintf(cmd2, "C:\\MinGW\\bin\\gcc.exe %s\\code.obj -o %s\\code.exe", path, path);  
system(cmd2);  
.
..  
Geração de Código Máquina  
Implementação)  
(
Entrada:  
int test;  
test = (46 + 100)/2;  
print(test);  
Leitura Complementar  
Aho, A. V., Lam, M. S., Jeffrey, R. S.  
Compiladores: Princípios, Técnicas e  
Ferramentas. 2ª edição, Pearson, 2007.  
ISBN: 978-8588639249.  
Capítulo 8: Code Generation