Seite 1 von 1

Brainfuck Compiler

Verfasst: 13.08.2005 16:28
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

Verfasst: 16.08.2005 08:53
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:

Verfasst: 18.08.2005 02:23
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.

Verfasst: 20.08.2005 20:32
von Eclipse
so könnte man sich theoretisch eine eigene programmiersprache schreiben

Verfasst: 20.08.2005 20:54
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:

Verfasst: 20.08.2005 21:12
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:.