Ich bin halt 'ne faule Sau.
Ich bin halt 'ne faule Sau.
Den Assembler zu verstehen ist heute auch nicht schrieriger. Nur sind die Programme locker um den Faktor zehntausend größer als damals, was die Analyse enorm erschwert.
Nun ja, es stimmt zwar, daß das Instruction Set vom Prinzip her immer noch dasselbe ist, vielleicht ein/zwei Dutzend neue Befehle und die Zahl der Register hat sich verdoppelt bis verdreifacht, aber das ist in der Tat nichts grundlegend anderes. Jedoch Du darfst nicht vergessen, daß sich die Architektur der CPU extrem verkompliziert hat:
- Früher gab es eine CPU, die wie ein absolutistischer Herrscher über "den" RAM verfügen konnte. Heute ist das kleinste, was man noch so kriegt, schon ein Quad-Core. Jede CPU hat ihren eigenen L2-Cache, die alle mit dem RAM synchron gehalten werden müssen, d.h. der Code für den eigentlichen Algorithmus ist "vermengt" mit allerhand Synchronisierungs-Code, der dafür sorgt, daß zu den kritischen Read/Write-Zeitpunkten die Caches aktuell sind.
- Dazu kommt dann, daß die heutigen Compiler extrem komplexe Optimierungen durchführen, die die Instructions auch noch mal gehörig durcheinanderwirbeln, so daß die Denkkapazität des menschlichen Gehirns schnell die Übersicht verliert. (Ein Computer hat halt ein Millionenfaches an Merk-Kapazität als das menschliche Gehirn, daher kann der Compiler sich ein Millionenfaches an Ersetzungen, Umsortierungen und Abkürzungen merken und wieder so zusammen-dröseln, daß es hinterher immer noch stimmt.) Z.B. wenn der Compiler merkt, daß der zu berechnende Algorithmus es verlangt, daß 10 Zeilen weiter unten eine Variable inkrementiert werden muß, und sich diese Variable jetzt gerade in einem Register befindet, weil sie grad im Rahmen einer anderen Operation dort benötigt wurde, und desweiteren ein paar Sachen ohne Nebenwirkungen so umsortiert werden können, daß innerhalb dieser nächsten 10 Zeilen nicht mehr lesend auf die Variable zugegriffen werden muß, dann führt der Compiler das Inkrement bereits jetzt aus, macht die Umsortierungen, und der menschliche Leser hat keinen blassen Schimmer mehr, was das alles bedeuten soll. (Hier gibt es übrigens signifikante Unterschiede zwischen den verschiedenen Compilern. Wir haben z.B. gemerkt, daß, wenn man das identische C++ Programm einmal mit dem Intel-Compiler für eine spezielle Intel-CPU compiliert und einmal z.B. mit einem "General Purpose" Compiler wie dem GNU Compiler übersetzt, dann läuft das vom Intel-Compiler generierte Executable durchschnittlich 10% schneller als das andere.)
- Dazu kommt dann die wesentlich komplexere Segmentierung. Früher gab es im wesentlichen das Code-Segment, das Data-Segment und das Stack-Segment. Heute gibt es die verschiedensten Technologien, die eingeführt wurden, um fehlerhafte Programme einigermaßen gegen auf Buffer-Overflow und Stack-Corruption basierende Hacker-Attacken zu schützen. Stichworte "Executable space protection", "Data Execution Prevention" auf Windows oder "Address space layout randomization". Außerdem werden u.U. unbenutzte "Puffer-Segmente" eingefügt, um das Überschreiben der dahinterliegende Daten zu verhindern (oder wenigstens zu erkennen). Kurz und gut, der menschliche Geist wird ruck-zuck die Übersicht verlieren, an welchen Adressen seine Variablen nun eigentlich stehen...
- Dazu kommt dann noch ein Vielfaches an IO-Möglichkeiten. Früher gab es (neben Tastatur, Maus und Bildschirm) im wesentlichen nur noch ein Disketten-Laufwerk, den LPT-Port und zwei bis drei COM-Ports. Schon PCs mit einer Netzwerkkarte waren eine Seltenheit. Heute kommen da noch dutzende USB-Ports, DVD/ROM-Laufwerk/Brenner, SD-Karten-Leser, Lautsprecher/Mikrophon, WLAN-Empfänger usw usw dazu. Wenn Du nur den Maschinen-Code siehst, der auf irgendwelche Interrupts reagiert oder in irgendwelche BIOS-Routinen oder Treiber abspringt, wirst Du ne Weile herumpuzzeln müssen, um heraus zu finden, mit welchem Gerät da eigentlich kommuniziert wird...
Kurz und gut, ich sage nicht, daß es unmöglich ist, aber ich wage zu behaupten, daß Assembler/Maschinen-Code, der von einem heutigen Compiler generiert wurde, nur noch von absoluten Spezialisten verstanden werden kann, die sich jahrelang mit dem Thema beschäftigt haben, und daß es extrem zeitaufwändig wäre, sobald es sich um ein "hinreichend nicht-triviales" Programm handelt...
Geändert von Lanzelot (23. Januar 2013 um 11:16 Uhr)
Sir Lanzelot
@Lanzelot
Hast du aktuell mal mit einem Disassembler gearbeitet?
Das stimmt sicherlich alles; ich hatte es bloß verkürzt auf "zehntausendmal mehr Kode".
Na ja, für eine reine Anwendung ist es vielleicht nicht ganz so schlimm, weil man ja nur das Programm und nicht gleich das ganze Betriebssystem verstehen muß. Die Analyse von Assemblerprogrammen empfinde ich hauptsächlich als extrem zeitaufwendig, aber nicht als besonders schwierig. Wenn man natürlich nichtmal Namen und Addressen der Funktionen kennt, und das Werk auch noch in kompliziertestem C++ geschrieben wurde, dann wird es so richtig eklig.
Das hat er sicherlich wie jeder, der jemals in Assembler programmiert hat. Meinst Du vielleicht einen Reassembler?
Kommt auf die Definition von "aktuell" an... Aber wie gesagt: mein letzter (produktiver) Kontakt mit Assembler war 1987... Daher ist natürlich mein Wissen auf dem Gebiet total veraltet.
Aber d7 trifft es recht gut: "Wenn man natürlich nichtmal Namen und Addressen der Funktionen kennt, und das Werk auch noch in kompliziertestem C++ geschrieben wurde, dann wird es so richtig eklig."
Beides trifft sicher auf Civ 3 zu...
Sir Lanzelot
Wozu Betrachtungen über das Verschanzen von Schiffen führen können!
Ich wäre bei beidem nicht so ohne weiteres sicher. Es kann gut sein, daß der Hersteller die Debuginformationen mit ausgeliefert hat, oder wenigstens die Funktionsnamen noch da sind. Und angesichts der vielen Fehler in Civ3, die anscheinend mit einer defekten Verwaltung von Listenstrukturen zusammenhängen, könnte ich mir auch vorstellen, daß da keine C++-Bibliothek zum Einsatz gekommen ist, was die Sache vereinfachen könnte.
(P.S.: Civ3 ist natürlich _auch_ Schnee von gestern. )
Der Krempel mit Segmenten und Segmentregistern ist übrigens Schnee von gestern. Die x86-Prozessoren arbeiten schon lange direkt mit 32- oder 64-Bit-Adressen; die Segmentregister sind daher heutzutage überflüssing, und auch die Schreibweise der Instruktionen in Disassemblerlistings wurde generalüberholt und ist mit dem unleserlichen Schmotter aus Dos-Zeiten nicht mehr zu vergleichen (zum Glück, das war wirklich eine Plage).
P.S.: Hab' mal die Civ3Conquests_nocd.exe durchwühlt und finde da nur ein paar Namen von Bibliotheksfunktionen. Das Zeug scheint in C++ geschrieben zu sein (zumindest wird die CC+-Laufzeitbibliothek erwähnt), aber Referenzen zur C++-Standardbibliothek finde ich nicht.
g e s p e r r t
C3C
[Küchenschlacht Remastered] | Persien kämpft gegen fünf weitere Spieler auf einer unfairen Karte
Tut mir Leid, aber ihr habt mich abgehängt
Battlestar Galactica - Das Forenspiel
X (beendet) | XI (beendet) | XII (beendet) | XIII (gestartet)
Twilight Imperium - Das Forenspiel
I (gestartet)
ihr seid klasse
JEDE Verallgemeinerung ist schlichtweg falsch.