Warum ist die CPU-Emulation langsam?

1286
user2543574

Unterschiedliche CPU-Vorgänge (IA-32, ARM9 usw.) sollten in ihrer Art (Verschieben, Lesen, Schreiben von Daten usw.) gleich sein. Es sollte nicht so schmerzhaft sein, dass verschiedene CPUs sich gegenseitig nachahmen. Aber es scheint nicht so einfach zu sein, da emulierte Software zu langsam läuft. Könnten wir einfach eine ausführbare Datei konvertieren und dann ausführen? Warum ist es sowieso so ressourcenabhängig (warum brauche ich eine leistungsfähige CPU, um eine andere CPU zu emulieren)? Ich muss sagen, ich habe keine großen Programmierkenntnisse auf niedrigem Niveau. Danke vielmals.

3

2 Antworten auf die Frage

5
LawrenceC

Unterschiedliche CPU-Vorgänge (IA-32, ARM9 usw.) sollten in ihrer Art (Verschieben, Lesen, Schreiben von Daten usw.) gleich sein.

Sie sollten sein, aber sie sind es nicht. Eine CPU-Architektur implementiert diese grundlegenden Operationen entsprechend den Vorstellungen ihrer Designer - und dies kann sehr unterschiedlich sein, je nachdem, was die Designer zu erreichen versuchen. Dinge, die auf einer CPU in einer Anweisung ausgeführt werden können, erfordern für viele andere Anweisungen.

Könnten wir einfach eine ausführbare Datei konvertieren und dann ausführen? Warum ist es sowieso so ressourcenabhängig (warum brauche ich eine leistungsfähige CPU, um eine andere CPU zu emulieren)?

Wenn Sie nur die CPU emulieren möchten, ist dies relativ einfach möglich. Das "Konvertieren" einer ausführbaren Datei im laufenden Betrieb wird als "Dyamic-Rekomplikation" bezeichnet, und viele Emulatoren tun dies bereits. Normalerweise möchte man jedoch eine gesamte Plattform nachbilden. Dies umfasst andere Hardware als die CPU, und manchmal ist es schwierig, diese Hardware zu emulieren (z. B. Atari 2600 TIA) oder schlecht dokumentiert (NES PPU-Videohardware oder sogar aktuelle GPU-Hardware) oder beides. CPUs arbeiten immer im Kontext einer Plattform, und normalerweise erwartet die Software, dass die CPU + -Plattform zusammenarbeitet. Die Anforderungen für die Emulation einer Plattform und die Einhaltung strenger Zeitvorgaben sind der harte und ressourcenintensive Teil.

Ja. Wäre da nicht das kleinste Detail der Peripheriegeräte in der Umgebung der CPU gewesen, wären zum Beispiel all die Anstrengungen, das IBM ROM-BIOS rückzuentwickeln, nicht erforderlich gewesen. Legen Sie einfach eine handelsübliche 8086 auf ein Motherboard und Sie hätten einen IBM-PC-Klon, der bereit ist, die Regale zu erreichen. In der Praxis war das natürlich nicht so einfach. Dasselbe gilt hier, allerdings in größerem Maßstab als ein 8-KiB-ROM-Chip mit veröffentlichtem, kommentiertem und kommentiertem Quellcode. a CVn vor 10 Jahren 0
@ MichaelKjörling Warum können wir nicht in Blackbox-Kategorien denken, da wir einige Eingabedaten und Aufgaben haben? Eingabedaten sollten einfach zu konvertieren sein. warum ist es nicht user2543574 vor 10 Jahren 0
@ user2543574 Da Ultrasawblade genau darauf hinweist, gibt es eine Menge nützlicher Emulation einer Plattform, als einfach die binären Opcodes der CPU von einer CPU zur anderen zu übersetzen. Einen brauchbaren (wenn auch vielleicht nicht sehr nützlichen) Altare 8800-Emulator zu schreiben, ist ziemlich einfach, da er wirklich wenig mehr war als eine 8080-CPU, eine Menge physischer E / A (Lichter und Schalter), eine RAM-Platte und ein RAM S-100-Bus zum Anschluss von Peripheriegeräten an die CPU. Einen nützlichen NES-Emulator zu schreiben, ist ein völlig anderes Unterfangen, obwohl die 6502-CPU auf einem ähnlichen Niveau wie die 8080 ist. a CVn vor 10 Jahren 0
4
user55325

Erstens gibt es zwar sehr ähnliche Anweisungen, es ist jedoch nicht so, dass einige Anweisungen vorhanden sind, die sich auf verschiedenen CPU-Architekturen immer gleich verhalten. Für eine genaue Emulation reicht es (normalerweise) nicht aus, jede Anweisung zu übersetzen - Sie müssen Speicherzugriffe, Timing, Interrupts ausführen ... und das ist nur für die CPU.

Anscheinend ist das, woran Sie denken, eine statische Neukompilierung, aber es ist sehr schwierig (tatsächlich denke ich, dass es auf das haltende Problem zurückzuführen ist, was es theoretisch unmöglich macht). In der Praxis können wir dies manchmal für eine Teilmenge von Programmen tun, aber Sie können keinen Compiler für allgemeine Zwecke schreiben, der Objektcode für eine Architektur als Eingabe verwendet und vollkommen äquivalenten Code für eine andere ausgibt. Es wäre beispielsweise schwierig, mit dieser Methode selbstmodifizierenden Code zu verarbeiten.

Dynamische Rekompilierung (die während der Ausführung des Programms während der Ausführung Code generiert) ist erfolgreicher (es ist jedoch nicht einfach, dies richtig zu tun). Die spezifischen Probleme hängen jedoch von der Architektur ab. In vielen Fällen ist das Emulieren der CPU nicht das Problem, sondern das Emulieren verschiedener Peripheriegeräte unter Beibehaltung einer genauen Zeitsteuerung (siehe z. B. Artikel von Emu über das Emulieren des SNES ).

Manchmal können Sie viele dieser Einschränkungen ignorieren und die Hardware dennoch gut genug nachahmen, um eine Teilmenge der Software zum Laufen zu bringen, aber es ist (soweit ich weiß) nie möglich, eine 100% ige Genauigkeit mit Null-Overhead zu erzielen, es sei denn, Sie verfügen über die eigentliche Hardware.

Wie unterscheidet sich die statische Rekompilierung von der dynamischen, da der Code trotzdem rekompiliert (konvertiert) wird? user2543574 vor 10 Jahren 0
Der Unterschied besteht darin, dass die dynamische Rekompilierung während der Ausführung des Codes erfolgt. Daher ist es jederzeit möglich, den Status des Systems zu kennen. Dadurch können Sie den Code je nach den aktuellen Bedingungen unterschiedlich übersetzen. Dies ist bei einem statischen Rekompiler nicht möglich. user55325 vor 10 Jahren 0