AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein [asm/delphi] AV bei Ausführung von MOV-Instruction
Thema durchsuchen
Ansicht
Themen-Optionen

[asm/delphi] AV bei Ausführung von MOV-Instruction

Ein Thema von Namenloser · begonnen am 23. Jan 2010 · letzter Beitrag vom 25. Jan 2010
Antwort Antwort
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#1

[asm/delphi] AV bei Ausführung von MOV-Instruction

  Alt 23. Jan 2010, 22:34
Hallo ihr ,

angeregt durch die verschiedenen BF-Interpreter im Brainfuck-Thread, wollte ich versuchen, einen kleinen JIT-Compiler zu schreiben.

Bisher habe ich nur die Rechenoperationen (und Schleifen) implementiert, und soweit scheint der generierte Binärcode - wenn auch nicht optimal - zumindest korrekt zu sein, denn wenn ihn mir in der CPU-Ansicht von Delphi in disassemblierter Form ansehe, kommt das Erwartete heraus.

Leider kann ich den Code dennoch nicht ausführen - denn schon bei der ersten Instruktion (MOV) erscheint schon eine Zugriffsverletzung:
Code:
---------------------------
Bfcompiler
---------------------------
Zugriffsverletzung bei Adresse 015f043c. Schreiben von Adresse 015f043c.
---------------------------
OK  
---------------------------
$015f043c ist die Adresse an der der reservierte Speicher für das Brainfuck-Programm anfängt.

Der relevante Code ist folgender:
Delphi-Quellcode:
  TBrainFuckCompiler = class(TBrainfuckParser)
  protected
    // In diesen Stream wird der Programmcode geschrieben
    FMemStream: TMemoryStream;
    procedure DoCompile; virtual;
    { ... }
  public
    procedure Compile;
    { ... }
  end;

  TBrainFuckRunner = class(TBrainfuckCompiler)
  protected
    // In diesem Array ist der Speicher für das Programm reserviert:
    FMemory: packed array[0..$10000] of Byte;
    procedure DoCompile; override;
  public
    procedure Run;
  end;

{ TBrainFuckRunner }

procedure TBrainFuckRunner.DoCompile;
var
  B: Byte;
  DW: Longint;
begin
  // Speicher-Adresse in ECX übergeben
  B := $B8 + 1; // MOV to ECX
  FMemStream.Write(B, 1);

  // Speicheradresse schreiben
  DW := LongInt(@(FMemory[0]));
  FMemStream.Write(DW, 4);

  // Programmcode kompilieren
  inherited;

  // RETurn (for execution)
  B := $C3; // RET
  FMemStream.Write(B, 1);
end;

procedure TBrainFuckRunner.Run;
var
  address: pointer;
begin
  address := FMemStream.Memory;
  asm
    call address;
  end;
end;
Die eigentliche Kompilierung findet in TBrainfuckCompiler.DoCompile statt - dabei habe ich es so gelöst, dass aktuelle "Zelle" des Brainfuckprogramms (Pointer auf die Speicheradresse) immer im Register ECX gehalten wird. Wenn dann eine Zelle weitergerückt wird, wird einfach ECX inkrementiert usw.
Natürlich muss ECX dafür zuerst mit der richtigen Adresse initialisiert werden, und das geschieht vor der eigentlichen Kompilierung in TBrainFuckRunner.DoCompile.

Die generierten Instruktionen sehen dann (laut Delphis Disassembler) für das Brainfuck-Programm "++>-<-->+>+++" z.B. so aus:
Code:
// $015f043c = Basis-Speicheradresse für das Brainfuck-Programm
01600460 B93C045F01       mov ecx,$015f043c // Und hier kratzt er dann auch schon ab...

01600465 8B01             mov eax,[ecx]
01600467 40               inc eax
01600468 8BC8             mov ecx,eax
0160046A 8B01             mov eax,[ecx]
0160046C 40               inc eax
0160046D 8BC8             mov ecx,eax
0160046F 41               inc ecx
01600470 8B01             mov eax,[ecx]
01600472 48               dec eax
01600473 8BC8             mov ecx,eax
01600475 49               dec ecx
01600476 8B01             mov eax,[ecx]
01600478 48               dec eax
01600479 8BC8             mov ecx,eax
0160047B 8B01             mov eax,[ecx]
0160047D 48               dec eax
0160047E 8BC8             mov ecx,eax
01600480 41               inc ecx
01600481 8B01             mov eax,[ecx]
01600483 40               inc eax
01600484 8BC8             mov ecx,eax
01600486 41               inc ecx
01600487 8B01             mov eax,[ecx]
01600489 40               inc eax
0160048A 8BC8             mov ecx,eax
0160048C 8B01             mov eax,[ecx]
0160048E 40               inc eax
0160048F 8BC8             mov ecx,eax
01600491 8B01             mov eax,[ecx]
01600493 40               inc eax
01600494 8BC8             mov ecx,eax
01600496 C3               ret
(Nicht perfekt, ich weiß - aber es ist auch mein erstes Projekt dieser Art und viel Erfahrung mit Assembler habe ich auch nicht )

Wie schon beschrieben, kratzt der bei der ersten Instruktion mit oben gezeigter Fehlermeldung ab. Was mich vor allem verwundert, ist, dass er sich wegen eines Schreibzugriffs beschwert - ich schreibe doch gar nicht an die Adresse, oder? Eigentlich soll nur dieser Wert ins Register ECX geschoben werden.

Kann mich jemand mit mehr Assembler-Erfahrung vielleicht erleuchten?
Vielen Dank schon mal!
Angehängte Dateien
Dateityp: zip brainfuck_189.zip (229,0 KB, 2x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: [asm/delphi] AV bei Ausführung von MOV-Instruction

  Alt 24. Jan 2010, 09:07
Du hast auf deinem Speicherbereich keine Ausführenberechtigung.

Entweder du holst dir de Speicherbereich mit VirtualAlloc oder du änderst die Berechtigungen mit VirtualProtect.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#3

Re: [asm/delphi] AV bei Ausführung von MOV-Instruction

  Alt 24. Jan 2010, 12:10
Zitat von sirius:
Du hast auf deinem Speicherbereich keine Ausführenberechtigung.
Ah, danke. Das hatte ich schon fast vermutet, nur hätte ich in dem Falle eine aussagekräftigere Fehlermeldung erwartet. Zumindest kann ich jetzt schon einige Befehle ausführen - danach kommt wieder eine Zugriffsverletzung, aber das liegt wohl an einem falschen Code.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: [asm/delphi] AV bei Ausführung von MOV-Instruction

  Alt 25. Jan 2010, 07:08
aus
mov ecx,eax sollte wohl besser
mov [ecx],eax werden
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#5

Re: [asm/delphi] AV bei Ausführung von MOV-Instruction

  Alt 25. Jan 2010, 15:10
Danke, aber das habe ich schon geändert

Mit einfachen Beispielprogrammen (wie z.B. dem Helloworld-Programm von Wikipedia oder dem Sierpinskidreieck) funktioniert der Compiler sogar schon ganz gut. Leider kommt es bei größeren Programmen (Hanoi, Mandelbrot etc.) vor, dass Sprünge auf falsche Adressen (bzw. nicht an den Anfang der Zielinstruktion sondern irgendwo in die Mitte) zeigen, was ich mir nicht erklären kann. Ich war gestern schon den ganzen Tag am debuggen, habe die generierten Codes auch schon ausgiebig in einem Disassembler unter die Lupe genommen, aber die Ursache leider trotzdem nicht gefunden

Ich glaube zwar nicht das jemand von euch sich die Mühe machen wird, sich durch den Code zu wühlen, den ich anscheinend selbst nicht verstehe, aber hänge die aktuelle Version trotzdem mal an, damit nicht noch weitere Hinweise auf Fehler kommen, die inzwischen nicht mehr aktuell sind.

Zum Testen Brainfuck-Sourcecode in das große Memo kopieren, die Buttons von oben nach unten der Reihe nach drücken, und die Ausgabe im Konsolenfenster ansehen (Ausgabe in ein Memo habe ich verworfen, weil es zu langsam war). Achja, und der Eingabe-Operator "," ist noch nicht implementiert.
Angehängte Dateien
Dateityp: zip brainfuck_766.zip (224,7 KB, 1x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz