![]() |
[asm/delphi] AV bei Ausführung von MOV-Instruction
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo ihr :hi: ,
angeregt durch die verschiedenen BF-Interpreter im ![]() 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:
$015f043c ist die Adresse an der der reservierte Speicher für das Brainfuck-Programm anfängt.
---------------------------
Bfcompiler --------------------------- Zugriffsverletzung bei Adresse 015f043c. Schreiben von Adresse 015f043c. --------------------------- OK --------------------------- Der relevante Code ist folgender:
Delphi-Quellcode:
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.
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; 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:
(Nicht perfekt, ich weiß - aber es ist auch mein erstes Projekt dieser Art und viel Erfahrung mit Assembler habe ich auch nicht :oops:)
// $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 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? :gruebel: Vielen Dank schon mal! |
Re: [asm/delphi] AV bei Ausführung von MOV-Instruction
Du hast auf deinem Speicherbereich keine Ausführenberechtigung.
Entweder du holst dir de Speicherbereich mit VirtualAlloc oder du änderst die Berechtigungen mit VirtualProtect. |
Re: [asm/delphi] AV bei Ausführung von MOV-Instruction
Zitat:
|
Re: [asm/delphi] AV bei Ausführung von MOV-Instruction
aus
Delphi-Quellcode:
sollte wohl besser
mov ecx,eax
Delphi-Quellcode:
werden
mov [ecx],eax
|
Re: [asm/delphi] AV bei Ausführung von MOV-Instruction
Liste der Anhänge anzeigen (Anzahl: 1)
Danke, aber das habe ich schon geändert :wink:
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz