Usando yyparse () para fazer um montador duas passagens?
-
23-08-2019 - |
Pergunta
Eu estou escrevendo um assembler para um controlador de micro costume que eu estou trabalhando. Eu tenho o assembler a um ponto onde ele vai montar instruções para baixo para binário.
No entanto, agora estou tendo problemas com a obtenção de rótulos ao trabalho. Atualmente, quando meu montador encontra um novo rótulo, ele armazena o nome do rótulo e o local de memória a sua referindo. Quando um referências de instrução de um rótulo, os olhares montador até o rótulo e substitui a etiqueta com o valor apropriado.
Esta é fino e elegante, mas que se a etiqueta for definida depois da instrução fazendo referência a ele? Devido a isso, eu preciso ter meu analisador atropelado o código duas vezes.
Aqui está o que eu tenho atualmente para o meu principal função:
303 int main(int argc, char* argv[])
304 {
305
306 if(argc < 1 || strcmp(argv[1],"-h")==0 || 0==strcmp(argv[1],"--help"))
307 {
308 //printf("%s\n", usage);
309 return 1;
310 }
311 // redirect stdin to the file pointer
312 int stdin = dup(0);
313 close(0);
314
315 // pass 1 on the file
316 int fp = open(argv[1], O_RDONLY, "r");
317 dup2(fp, 0);
318
319 yyparse();
320
321 lseek(fp, SEEK_SET, 0);
322
323 // pass 2 on the file
324 if(secondPassNeeded)
325 {
326 fp = open(argv[1], O_RDONLY, "r");
327 dup2(fp, 0);
328 yyparse();
329 }
330 close(fp);
331
332 // restore stdin
333 dup2(0, stdin);
334
335 for(int i = 0; i < labels.size(); i++)
336 {
337 printf("Label: %s, Loc: %d\n", labels[i].name.c_str(), labels[i].memoryLoc);
338 }
339 return 0;
340 }
Eu estou usando isso dentro de um flex / bison configuração.
Solução
Se isso é tudo que você precisa, você não precisa de um montador de duas passagens completo. Se a etiqueta não é definido quando você referenciá-lo, você simplesmente emitir um stand-in endereço (dizem 0x0000) e ter uma estrutura de dados que lista todos os lugares com referências à frente e o símbolo que refered. No final do arquivo (ou bloco se você tiver símbolos locais), você simplesmente passar por essa lista e corrigir os endereços.