Brainfuck Compiler

Anwendungen, Tools, Userlibs und anderes nützliches.
Benutzeravatar
Eric
Beiträge: 303
Registriert: 05.09.2004 09:50
Wohnort: Göttingen

Brainfuck Compiler

Beitrag von Eric »

Ich hab noch so ca. 1 1/2 Wochen Ferien und nichts zu tun, also hab ich mal einen Brainfuck Compiler geschrieben.

Brainfuck? Wasn das?

Wichtig:
Ihr braucht noch die nasmw.exe http://nasm.sourceforge.net

Der Compiler erzeugt eine Assembler Datei un nasm macht daraus dann eine 16Bit Com-Datei.

Der Compiler sollte eigendlich mit allen Programmen funktionieren, falls nicht, einfach mal #stacksize erhöhen. Außerdem sollten die Programme nicht zu groß sein (Com Dateien dürfen nur 64kb groß sein und schon alleine 30000 Byte gehen für den Datenspeicher drauf...)

Der Compiler ist noch nicht sonderlich gut entwickelt, es gibt sicherlich noch einige Fehler und Optimierungsmöglichkeiten, aber Hey, ich arbeite dran :wink:.

Ich warte auf eure Vorschläge/Anregungen/Kritik.

Hier sind einige Programme zum ausprobieren.

Code: Alles auswählen

;Brainfuck Compiler V0.01

#stacksize=2000

Structure memory
  adr.l
  len.l 
EndStructure


Structure stack
  sp.l
  ss.l
  adr.l
EndStructure

Procedure Push(stk.l, value.w)
  PokeW(PeekL(stk+8)+(PeekL(stk)*2),value)
  PokeL(stk,PeekL(stk)+1)
EndProcedure

Procedure.w Pop(stk.l)
  PokeL(stk,PeekL(stk)-1)
  a= PeekW(PeekL(stk+8)+(PeekL(stk)*2))
  ProcedureReturn a
EndProcedure

If OpenFile(0,OpenFileRequester("","*.bf","*.bf",1))
  mem.memory\adr=AllocateMemory(Lof())
  mem\len=Lof()
  ReadData(mem\adr,Lof())
  CloseFile(0)

  count=0
  For x=0 To mem\len
    If PeekB(mem\adr)=91
      count+1
    ElseIf PeekB(mem\adr)=93
      count-1
    EndIf
  Next

  If count=0
    CreateFile(0,"out.asm")
    WriteStringN("segment.code")
    WriteStringN("org 0x100")
    WriteStringN("mov si,buffer")
    WriteStringN("xor cx,cx")
    WriteStringN("loop_:")
    WriteStringN("mov word [si],0")
    WriteStringN("add si,2")
    WriteStringN("inc cx")
    WriteStringN("cmp cx,15000")
    WriteStringN("jne loop_")
    WriteStringN("mov si,buffer")
    
    stk.stack\adr=AllocateMemory(#stacksize*2)
    stk\ss=#stacksize
    stk\sp=0
    cur=0
    
    For x=0 To mem\len
      Select PeekB(mem\adr+x)
      
      
        Case 43 ;+
          If PeekB(mem\adr+x+1)=43
            count=1
            Repeat
              x+1
              count+1
            Until PeekB(mem\adr+x+1)<>43
            WriteStringN("add byte [si],"+Str(count))
          Else
            WriteStringN("inc byte [si]")
          EndIf
        
        Case 44 ;,
          WriteStringN("mov ah,0x06")
          WriteStringN("mov dl,0xFF")
          WriteStringN("int 0x21")
          WriteStringN("mov [si],al")
        
        Case 45 ;-
          If PeekB(mem\adr+x+1)=45
            count=1
            Repeat
              x+1
              count+1
            Until PeekB(mem\adr+x+1)<>45
            WriteStringN("sub byte [si],"+Str(count))
          Else
            WriteStringN("dec byte [si]")
          EndIf  
         
        Case 46 ;.
          WriteStringN("mov ah,0x02")
          WriteStringN("mov dl,[si]")
          WriteStringN("int 0x21")
         
        Case 60 ;<
          If PeekB(mem\adr+x+1)=60
            count=1
            Repeat
              x+1
              count+1
            Until PeekB(mem\adr+x+1)<>60
            WriteStringN("sub si,"+Str(count))
          Else
            WriteStringN("dec si")
          EndIf  
          
        Case 62 ;>
          If PeekB(mem\adr+x+1)=62
            count=1
            Repeat
              x+1
              count+1
            Until PeekB(mem\adr+x+1)<>62
            WriteStringN("add si,"+Str(count))
          Else
            WriteStringN("inc si")
          EndIf  
          
        Case 91 ;[
          WriteStringN("loop_"+Str(cur)+":")
          WriteStringN("cmp byte [si],0")
          WriteStringN("je near loop_"+Str(cur)+"_end")
          Push(@stk,cur)
          cur+1
          
          
        Case 93 ;]
          a=Pop(@stk)
          WriteStringN("jmp loop_"+Str(a))
          WriteStringN("loop_"+Str(a)+"_end:")
      EndSelect
        
    Next
    WriteStringN("mov ah,0x4C")
    WriteStringN("int 0x21")
    WriteStringN("buffer:")
    RunProgram("nasmw.exe","-o out.com out.asm",".\")


  Else
    MessageRequester("Fehler","Das Verhältnis der [ und ] ist unausgeglichen.")
  EndIf

Else
  MessageRequester("Fehler","Datei nicht gefunden!")
EndIf
El_Choni_work: cant't you just spit the binary data to sqlite, as you would spit a hamster into a microwave oven?
* Fangles falls off the chair laughing
Bild
Benutzeravatar
Reever
Beiträge: 29
Registriert: 13.08.2005 21:36
Wohnort: NRW

Beitrag von Reever »

Hi
Vielleicht hast du nicht so große Lust drauf, aber könntest du mir zumindest ansatzweise im mittleren Teil erklären, was da genau passiert?
Wenn nicht ist auch nicht schlimm, ist ja nicht das, was hier reinkommen sollte :lol: achja und wo ich grad dabei bin, wie muss man denken, um sowas hinzukriegen? :mrgreen:
Das Wort eines Menschen wiegt nichts in den Augen eines Narrs
Benutzeravatar
Eric
Beiträge: 303
Registriert: 05.09.2004 09:50
Wohnort: Göttingen

Beitrag von Eric »

Also:

Die For-Schleife geht das Programm Zeichen für Zeichen durch.
Dann wird ermittelt, um welchen Befehl es sich handelt (+-.,<>[])
und sich wiederholende Befehle werden Zusammengefasst
(+ wird z.B. zu inc byte [si], was schneller und kompakter als add byte [si],1 ist (Vom Effekt her ist beides das Gleiche), wenn jetzt aber z.B. +++ kommt, wird daraus nicht 3 mal hintereinander inc byte [si], sondern add byte[si],3)
Damit lassen sich die Befehle + - < und > optimieren.
Falls der Befehl allerdings [ oder ] ist, so wird bei [ der entsprechende Code in die Datei geschrieben, die 'ID' für die Klammer auf den Stack gepackt und der Zähler um eins erhöht. Bei ] wird der Wert wieder vom Stack geholt und ein Sprungbefehl vor die dazugehörige [ in die Datei geschrieben.

So, ich glaube, das war es so weit...
Boah, schon 2:18...
jetzt muss ich mich aber wirklich mal hinlegen.
El_Choni_work: cant't you just spit the binary data to sqlite, as you would spit a hamster into a microwave oven?
* Fangles falls off the chair laughing
Bild
Eclipse
Beiträge: 99
Registriert: 04.06.2005 18:09

Beitrag von Eclipse »

so könnte man sich theoretisch eine eigene programmiersprache schreiben
Benutzeravatar
Eric
Beiträge: 303
Registriert: 05.09.2004 09:50
Wohnort: Göttingen

Beitrag von Eric »

Bin ich auch schon dabei, aber das ist doch ein etwas umfangreicheres Programm (und auch mit C++ und nicht mit PB, nichts gegen PB, aber ohne OOP wird mir das zu unübersichtlich)
Und es ist auch nicht unbedingt optimal, das Programm Zeichen für Zeichen durchzugehen und nach Befehlen zu suchen :lol:
El_Choni_work: cant't you just spit the binary data to sqlite, as you would spit a hamster into a microwave oven?
* Fangles falls off the chair laughing
Bild
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

Weiß nicht wo dein Problem ist. Ich hab ganz wunderbar in PB einen
sehr kleinen Compiler geschrieben. Ich freue mich schon auf das
fertige Ergebnis :allright:.
Bild
Antworten