Verwenden Sie yyparse(), um einen Assembler mit zwei Durchgängen zu erstellen?
-
23-08-2019 - |
Frage
Ich schreibe einen Assembler für einen benutzerdefinierten Mikrocontroller, an dem ich arbeite.Ich habe den Assembler so weit gebracht, dass er Anweisungen bis zur Binärdatei zusammenfügt.
Allerdings habe ich jetzt Probleme damit, Etiketten zum Laufen zu bringen.Wenn mein Assembler derzeit auf ein neues Label trifft, speichert er den Namen des Labels und den Speicherort, auf den es verweist.Wenn eine Anweisung auf eine Bezeichnung verweist, sucht der Assembler nach der Bezeichnung und ersetzt die Bezeichnung durch den entsprechenden Wert.
Das ist in Ordnung und gut, aber was ist, wenn die Bezeichnung nach der darauf verweisenden Anweisung definiert wird?Aus diesem Grund muss mein Parser den Code zweimal durchlaufen lassen.
Folgendes habe ich derzeit für meine Hauptfunktion:
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 }
Ich verwende dies in einer Flex/Bison-Konfiguration.
Lösung
Wenn das alles ist, was Sie brauchen, benötigen Sie keinen vollständigen Two-Pass-Assembler.Wenn die Bezeichnung beim Verweisen nicht definiert ist, geben Sie einfach eine Ersatzadresse aus (z. B. 0x0000) und verfügen über eine Datenstruktur, die alle Orte mit Vorwärtsverweisen und das Symbol, auf das sie verweisen, auflistet.Am Ende der Datei (oder des Blocks, wenn Sie lokale Symbole haben) gehen Sie einfach diese Liste durch und patchen die Adressen.