Frage

Ich habe ein 10K-Zeilenprogramm geerbt, das in der Assemblersprache 8051 geschrieben wurde und einige Änderungen erfordert.Leider ist es in den besten Traditionen des Spaghetti-Codes geschrieben.Das als einzelne Datei geschriebene Programm ist ein Labyrinth aus CALL- und LJMP-Anweisungen (insgesamt etwa 1200), wobei Unterroutinen mehrere Ein- und/oder Ausstiegspunkte haben, sofern sie überhaupt als Unterroutinen identifiziert werden können.Alle Variablen sind global.Es gibt Kommentare;einige haben recht.Es gibt keine bestehenden Tests und kein Budget für Refactoring.

Ein kleiner Hintergrund zur Bewerbung:Der Code steuert einen Kommunikationsknotenpunkt in einer Verkaufsanwendung, die derzeit international eingesetzt wird.Es verarbeitet zwei serielle Streams gleichzeitig (mit Hilfe eines separaten Kommunikationsprozessors) und kann mit bis zu vier verschiedenen physischen Geräten kommunizieren, jedes von einem anderen Hersteller.Der Hersteller eines der Geräte hat kürzlich eine Änderung vorgenommen („Ja, wir haben eine Änderung vorgenommen, aber die Software ist absolut dieselbe!“), die dazu führt, dass einige Systemkonfigurationen nicht mehr funktionieren, und ist nicht daran interessiert, diese (was auch immer es war) unverändert zu lassen sie haben sich nicht verändert).

Das Programm wurde ursprünglich von einer anderen Firma geschrieben, an meinen Kunden übertragen und dann vor neun Jahren von einem anderen Berater modifiziert.Weder das ursprüngliche Unternehmen noch der Berater stehen als Ressourcen zur Verfügung.

Basierend auf der Analyse des Datenverkehrs auf einem der seriellen Busse habe ich einen Hack entwickelt, der zu funktionieren scheint, aber hässlich ist und nicht die Grundursache behebt.Wenn ich das Programm besser verstehen würde, glaube ich, dass ich das eigentliche Problem angehen könnte.Ich habe noch etwa eine Woche Zeit, bis der Code eingefroren wird, um ein Versanddatum zum Monatsende zu unterstützen.

Ursprüngliche Frage:Ich muss das Programm gut genug verstehen, um die Änderungen ohne Fehler durchführen zu können.Hat jemand Techniken entwickelt, um mit dieser Art von Chaos umzugehen?

Ich sehe hier einige tolle Vorschläge, bin aber zeitlich begrenzt.Möglicherweise habe ich jedoch in Zukunft eine weitere Gelegenheit, einige der komplizierteren Vorgehensweisen zu verfolgen.

War es hilfreich?

Lösung

Zunächst würde ich versuchen, mit den Leuten in Kontakt zu treten, die den Code ursprünglich entwickelt oder ihn zumindest vor mir gepflegt haben, und hoffentlich genügend Informationen zu erhalten, um ein grundlegendes Verständnis des Codes im Allgemeinen zu erlangen, sodass Sie beginnen können, nützliche Kommentare hinzuzufügen Es.

Vielleicht können Sie sogar jemanden bitten, die wichtigsten APIs (einschließlich ihrer Signatur, Rückgabewerte und Zweck) für den Code zu beschreiben.Wenn der globale Zustand durch eine Funktion geändert wird, sollte dies ebenfalls explizit angegeben werden.Beginnen Sie in ähnlicher Weise mit der Unterscheidung zwischen Funktionen und Prozeduren sowie Eingabe-/Ausgaberegistern.

Sie sollten Ihrem Arbeitgeber deutlich machen, dass diese Informationen erforderlich sind. Wenn er Ihnen nicht glaubt, bitten Sie ihn, sich tatsächlich mit Ihnen vor diesen Kodex zu setzen und Ihnen zu beschreiben, was Sie tun sollen und wie Sie es tun müssen es (Reverse Engineering).In diesem Fall kann es tatsächlich hilfreich sein, einen Arbeitgeber mit einem Hintergrund in Informatik und Programmierung zu haben!

Wenn Ihr Arbeitgeber nicht über einen solchen technischen Hintergrund verfügt, bitten Sie ihn, einen anderen Programmierer/Kollegen mitzubringen, der ihm Ihre Schritte erklärt. Dadurch zeigen Sie ihm tatsächlich, dass Sie es ernst und ehrlich meinen, denn es handelt sich um ein echtes Problem – nicht nur aus Ihrer Sicht (stellen Sie sicher, dass Sie Kollegen haben, die über dieses „Projekt“ Bescheid wissen).

Wenn verfügbar und machbar, würde ich auch sehr deutlich machen, dass die Beauftragung (oder zumindest die Kontaktaufnahme) mit ehemaligen Entwicklern/Betreuern (sofern diese nicht mehr für Ihr Unternehmen arbeiten) zur Unterstützung bei der Dokumentation dieses Codes eine Vorarbeit wäre -Erforderlich, um den Code innerhalb kurzer Zeit realistisch zu verbessern und sicherzustellen, dass er in Zukunft einfacher gewartet werden kann.

Betonen Sie, dass diese ganze Situation auf Mängel im vorherigen Softwareentwicklungsprozess zurückzuführen ist und dass diese Schritte zur Verbesserung der Codebasis beitragen werden.Die Codebasis in ihrer jetzigen Form stellt also ein wachsendes Problem dar und alles, was jetzt zur Bewältigung dieses Problems unternommen wird, ist eine Investition in die Zukunft.

Dies allein ist auch wichtig, um ihnen zu helfen, Ihre Situation einzuschätzen und zu verstehen:Das zu tun, was Sie jetzt tun sollen, ist alles andere als trivial, und sie sollten darüber Bescheid wissen – und sei es nur, um ihre Erwartungen klarzustellen (z. B.hinsichtlich Fristen und Komplexität der Aufgabe).

Außerdem würde ich persönlich damit beginnen, Unit-Tests für die Teile hinzuzufügen, die ich gut genug verstehe, damit ich langsam mit dem Refactoring/Umschreiben von Code beginnen kann.

Mit anderen Worten: Eine gute Dokumentation und Kommentare zum Quellcode sind eine Sache, aber eine umfassende Testsuite ist eine andere wichtige Sache. Von niemandem kann realistischerweise erwartet werden, dass er eine unbekannte Codebasis ohne etablierte Methode zum Testen der Schlüsselfunktionalität ändert.

Angesichts der Tatsache, dass der Code 10 KB groß ist, würde ich auch darüber nachdenken, Unterroutinen in separate Dateien auszugliedern, um die Komponenten besser identifizierbar zu machen, und dabei vorzugsweise Zugriffswrapper anstelle globaler Variablen und auch intuitive Dateinamen verwenden.

Außerdem würde ich nach Schritten suchen, um die Lesbarkeit des Quellcodes durch Verringerung der Komplexität weiter zu verbessern. Unterroutinen mit mehreren Einstiegspunkten (und möglicherweise sogar unterschiedlichen Parametersignaturen?) scheinen ein sicherer Weg zu sein, den Code unnötig zu verschleiern.

Ebenso könnten große Unterroutinen in kleinere umgestaltet werden, um die Lesbarkeit zu verbessern.

Eines der allerersten Dinge, die ich in Betracht ziehen würde, wäre also, die Dinge zu ermitteln, die es wirklich kompliziert machen, die Codebasis zu durchforsten und diese Teile dann zu überarbeiten, zum Beispiel durch die Aufteilung großer Unterroutinen mit mehreren Einstiegspunkten in verschiedene Unterroutinen, die sich stattdessen gegenseitig aufrufen.Wenn dies aus Leistungsgründen oder wegen des Aufrufaufwands nicht möglich ist, verwenden Sie stattdessen Makros.

Darüber hinaus würde ich, wenn es sich um eine praktikable Option handelt, in Betracht ziehen, Teile des Codes inkrementell in einer höheren Sprache umzuschreiben, entweder durch die Verwendung einer Teilmenge von C oder zumindest durch den übermäßigen Einsatz von Assembler-Makros, um den Code zu standardisieren Basis, sondern auch, um potenzielle Fehler zu lokalisieren.

Wenn ein inkrementelles Umschreiben in C eine praktikable Option ist, besteht ein möglicher Einstieg darin, alle offensichtlichen Funktionen in C-Funktionen umzuwandeln, deren Körper zunächst aus der Assemblydatei kopiert/eingefügt werden, sodass Sie am Ende C erhalten Funktionen mit viel Inline-Assembly.

Persönlich würde ich auch versuchen, den Code in einem auszuführen Simulator/Emulator Um den Code einfach durchzugehen und hoffentlich die wichtigsten Bausteine ​​zu verstehen (während Sie die Register- und Stack-Nutzung untersuchen), sollte Ihnen ein guter 8051-Simulator mit integriertem Debugger zur Verfügung gestellt werden, wenn Sie dies wirklich größtenteils auf Ihrem Computer tun müssen eigen.

Dies würde Ihnen auch dabei helfen, die Initialisierungssequenz und die Hauptschleifenstruktur sowie einen Aufrufgraphen zu erstellen.

Vielleicht können Sie sogar einen guten Open-Source-80851-Simulator finden, der leicht modifiziert werden kann, um auch automatisch einen vollständigen Callgraphen bereitzustellen, indem Sie einfach eine schnelle Suche durchführen, wie ich herausgefunden habe gsim51, aber es gibt natürlich noch mehrere andere Optionen, auch verschiedene proprietäre.

Wenn ich in Ihrer Situation wäre, würde ich sogar darüber nachdenken, den Aufwand für die Modifikation meiner Tools auszulagern, um die Arbeit mit diesem Quellcode zu vereinfachen, d. h.Viele SourceForge-Projekte akzeptieren Spenden und vielleicht können Sie Ihren Arbeitgeber überreden, eine solche Änderung zu sponsern.

Wenn nicht finanziell, vielleicht dadurch, dass Sie entsprechende Patches dafür bereitstellen?

Wenn Sie bereits ein proprietäres Produkt verwenden, können Sie möglicherweise sogar mit dem Hersteller dieser Software sprechen, Ihre Anforderungen detailliert darlegen und ihn fragen, ob er bereit ist, dieses Produkt auf diese Weise zu verbessern, oder ob er zumindest eine Schnittstelle zur Verfügung stellen kann, um dies zu ermöglichen Kunden können solche Anpassungen vornehmen (irgendeine Form einer internen API oder vielleicht sogar einfache Glue-Skripte).

Wenn sie nicht reagieren, weisen Sie darauf hin, dass Ihr Arbeitgeber schon seit einiger Zeit darüber nachdenkt, ein anderes Produkt zu verwenden, und dass Sie der Einzige waren, der auf der Verwendung dieses bestimmten Produkts bestand ...;-)

Wenn die Software bestimmte I/O-Hardware und Peripheriegeräte erwartet, möchten Sie vielleicht sogar darüber nachdenken, eine entsprechende Hardware-Simulationsschleife zu schreiben, um die Software in einem Emulator auszuführen.

Letztendlich weiß ich mit Sicherheit, dass es mir persönlich viel mehr Spaß machen würde, andere Software so anzupassen, dass sie mir hilft, ein solches Spaghetti-Code-Monster zu verstehen, als den Code manuell durchzugehen und selbst den Emulator zu spielen, egal wie viele Gallonen Kaffee ich kann erhalten.

Das Erhalten eines brauchbaren Callgraphen aus einem Open-Source-8051-Emulator sollte nicht viel länger als sagen wir mal ein Wochenende (höchstens) dauern, da es hauptsächlich darum geht, nach CALL-Opcodes zu suchen und deren Adressen (Position und Ziel) aufzuzeichnen, damit alles an einen ausgegeben wird zur späteren Einsichtnahme ablegen.

Der Zugriff auf die Interna eines Emulators wäre tatsächlich auch eine großartige Möglichkeit, den Code weiter zu untersuchen, beispielsweise um wiederkehrende Muster von Opcodes (z. B. 20–50+) zu finden, die in eigenständige Funktionen/Prozeduren einbezogen werden könnten Helfen Sie dabei, die Größe und Komplexität der Codebasis noch weiter zu verringern.

Der nächste Schritt wäre wahrscheinlich die Untersuchung der Stack- und Registernutzung.Und um die Art/Größe der verwendeten Funktionsparameter sowie deren Wertebereich zu bestimmen – damit Sie entsprechende Unit-Tests konzipieren können.

Die Verwendung von Tools wie dot/graphviz zur Visualisierung der Struktur der Initialisierungssequenz und der Hauptschleife selbst wird im Vergleich dazu, all diese Dinge manuell zu erledigen, eine reine Freude sein.

Außerdem erhalten Sie tatsächlich nützliche Daten und Dokumente, die langfristig als Grundlage für eine bessere Dokumentation dienen können.

Andere Tipps

Ich fürchte, es auf diese Art von Problem kein Allheilmittel ist. Ich finde, die einzige Lösung ist dann die ASM-Datei auszudrucken irgendwo ruhig zu gehen und durch die Linie im Kopf lief die Programmzeile zu simulieren (während des Inhalt der Register zu schreiben und Speicherstellen auf einem Notizblock). Nach einer Weile finden Sie diese lange nicht so übernehmen, wie man erwarten würde. dies zu tun und trinken Gallonen Kaffee bereit sein, viele Stunden zu verbringen. Nach einer Weile haben Sie eine Vorstellung davon, was es tut, und Sie können Änderungen in Betracht ziehen.

Ist die 8051 alle nicht verwendeten IO-Ports? Ist dies der Fall und man kann nicht funktionieren, wenn bestimmte Routinen aufgerufen werden dann Code hinzufügen, dieser Ersatz Ports hoch oder niedrig zu senden. Dann wenn das Programm läuft diesen Ports mit einem Oszilloskop beobachten.

Viel Glück

Ich weiß, das klingt verrückt .... aber ich bin arbeitslos (I falsche Zeit nahm den marjority Partner zu sagen, in der Hölle zu gehen) und einige freie Zeit hat. Ich wäre bereit, einen Blick auf sie zu nehmen. Ich benutzen Baugruppe für den Apfel schreiben] [und den Original-PC. Wenn ich mit dem Code auf dem Simulator für ein paar Stunden spielen, um konnte ich könnte Ihnen eine Idee geben, wenn ich eine Chance zu dokumentieren, die für Sie haben (ohne mein ungeplanten Urlaub runing). Da ich nichts über 8051 wissen, könnte dies für jemanden wie mich nicht möglich sein, aber der Simulator sah vielversprechend aus. Ich möchte kein Geld, dies zu tun. Sein genug, nur Exposition gegenüber 8051 Embedded-Entwicklung zu bekommen. Ich habe dir gesagt, das wäre verrückt klingen.

Finden ernsthaft eine andere Job-! Gelingt das nicht das Buch „arbeitet effektiv mit Legacy-Code“ könnte Hilfe- obwohl ich denke, es bezieht sich auf den Legacy-Code als Code ohne Komponententests.

Ich habe diese Art der Sache ein paar Mal getan. Einige Empfehlungen:

  • Starten Sie durch die schematische Überprüfung, Dies soll Ihnen helfen, zu verstehen, was Ports und Pins Ihre gewünschten Änderungen Auswirkungen.
  • Verwenden Sie grep alle Anrufe zu finden, Verzweigungen, Sprünge und kehrt zurück. Das kann helfen, den Fluss zu verstehen und zu identifizieren, die Stücke von Code.
  • Schauen Sie sich die Reset-Vektor und Interrupt-Tabelle zu identifizieren, die Hauptlinien.
  • Verwenden Sie grep einen Querverweis erstellen für alle Codeetiketten und Daten Referenzen (wenn Ihr Assembler Werkzeuge können nicht für Sie tun dies).

Beachten Sie Hofstadter Gesetz: Es dauert immer länger als erwartet, auch wenn Sie berücksichtigen Hofstadter Gesetz .

Viel Glück.

Wie gut verstehen Sie die Hardware-Plattform dieser Code läuft auf?

  • Ist es in Power-Down-Modus versetzt worden (Pcon = 2) um Strom zu sparen Wenn ja, wie wird es aufgeweckt worden. (Ein Reset oder auf Hardware-Interrupt)

  • Sie müssen Sie nach einem Strom zu Ställen für den Oszillator einen warten, bevor die serielle Kommunikation zu tun

  • Ist es in den Schlafmodus versetzt worden ist (Pcon = 1)

Gibt es verschiedene Versionen der Hardware auf dem Gebiet aus?

Achten Sie darauf, die verschiedenen Hardware-Varianten testen auf.

Vergeuden Sie nicht Ihre Zeit mit einem Simulator - es ist sehr schwer, mit zu arbeiten, und Sie müssen eine Menge von Annahmen über die Hardware machen. Holen Sie sich einen In-Circuit-Emulator (ICE) und laufen auf der Hardware.

Die Software wurde in Assembler für einen Grund, warum, um herauszufinden, müssen geschrieben. d.h. - Speichereinschränkungen - Geschwindigkeitsbeschränkungen

Es kann ein Grund dafür sein, dass dieser Code ist ein Chaos

Haben Sie einen Blick auf den Link Datei für:

XDATA SPACE, IDATA SPACE und CODE SPACE:

Wenn es kein freier Code-Raum oder Xdata oder IDaten?

Der ursprüngliche Autor Optimizationed es möglicherweise verfügbar in den Speicherraum zu passen.

Wenn das der Fall ist Sie müssen die ursprünglichen Entwickler sprechen, um herauszufinden, was er tat, .

Sie brauchen keine Sonderbudget für Refactoring und Tests - sie sparen Sie Geld und lassen Sie schneller arbeiten - um es zu bekommen. Es ist die Technik, die Sie verwenden sollen Änderungen Vermächtnis hinzuzufügen, Code geerbt, weil es die billigste Art und Weise, es zu tun, ohne „ohne Bruch“.

Die meiste Zeit, ich glaube, es ist ein Trade-off, wo Sie mehr Qualität im Austausch bekommen mehr Zeit zu verbringen, aber mit Legacy-Code, den Sie nicht kennen, ich denke, dass es schneller ist Tests zu machen - Sie müssen laufen der Code, bevor Sie versenden es, nicht wahr?

Dies ist eines der wenigen Male, die ich Ihnen stellen Sie Ihre Soft Skills empfehlen werde zu arbeiten, und präsentieren Sie Ihre PM / Manager / CXO mit Ihrer Argumentation hinter einer neu zu schreiben und die Zeit / Kosteneinsparungen beteiligt mit einer solchen ein Unternehmen

in Stücke schneiden.

Ich hatte einige sehr ähnliches Problem mit einer 8052-Software. So hat das Unternehmen geerbt ein solches Tier, Code ROM voll (64 Kbyte), ca. 1,5 MB Montage Spaghetti-Module sowie zwei 3000 Zeilen PL / M Module diese Kodierung Monstrosität zusammengesetzt. Die ursprünglichen Entwickler der Software waren lange tot (dies dort nicht bedeuten, waren niemand, aber in der Tat niemand, der es als Ganzes verstehen würde), die Compiler kompiliert diese aus den Mitte der 80er Jahre waren auf einem MDS-70-Emulator ausgeführt wird, und mehrere kritische Module waren die Grenzen dieser Compiler an. Wie fügen Sie ein weiteres globales Symbol, und der Linker würde abstürzen. In ein weiteres Symbol zu einer ASM-Datei, und der Compiler würde abstürzen.

So, wie man beginnen könnte dieses Zerschneiden?

Zuerst müssen Sie Werkzeuge. Notepad ++ zum Beispiel ist eine sehr schöne Sache, da es auf einmal suchen zu überqueren entlang mehrerer Dateien verwendet werden kann, ideal zu finden, welche Module ein globales Symbol verweisen. Dies ist wahrscheinlich das wichtigste Element.

Wenn möglich, erhalten alle Papiere, die Sie auf der Software finden. Das unmittelbarste Problem mit diesen Tieren zu lösen, ist zu verstehen, wie sie etwa zusammengesetzt sind, was ihre Architektur. Dies ist in der Regel nicht in der Software selbst enthalten ist, nicht einmal, wenn es sonst richtig kommentiert.

Um die Architektur zu erhalten Sie sich, zunächst können Sie versuchen, auf ein Graph der zeigt, bauen . Es ist einfacher zu tun, als grafische Darstellung eines Datenflusses, da in der Regel gibt es weniger Cross-Datei Anrufe und springt als globale Variablen. Für diese Aufforderung Graphen nur globale Symbole betrachten die Quelldateien unter der Annahme, sollen Module sein (was nicht unbedingt der Fall ist, aber in der Regel sie sein sollten).

Um dies zu tun, Ihr Werkzeug für Querdateisuche verwenden, erstellen Sie eine große Liste (zB in Openoffice Calc), wo Sie sammeln, welches Symbol in welcher Datei definiert ist, und welche Dateien auf dieses Symbol verweisen nennt es.

Dann einige große stehlen (!) Blätter aus dem Plotter, und starten Sie skizzieren. Wenn Sie sehr bewandert in irgendeiner Graph Software sind, können Sie es verwenden, aber wenn es so ist, ist es wahrscheinlicher, Sie zurück zu halten. So einen Anruf Graph skizziert auf der Datei haben Anrufe, die andere Dateien (nicht die Symbole selbst zeigen, mit 50 oder so Dateien, würden Sie nicht in der Lage sein, es zu verwalten).

Die meisten wahrscheinlich das Ergebnis wird dies ein Spaghetti sein. Das Ziel ist es, dies zu begradigen es eine hierarchische Struktur mit einer Wurzel zu bekommen (das ist die Datei, um den Programmeinstiegspunkt sein wird enthalten) ohne Schleifen. Sie können mehrere Blätter verschlingen iterativ während dieses Verfahrens das Tier Richt. Sie können auch bestimmte Dateien sind so viel inter verheddert feststellen, dass sie nicht ohne Schleifen dargestellt werden können. Dieser Fall ist es sehr wahrscheinlich, dass ein einzelnes „Modul“ bekam irgendwie in zwei Dateien getrennt, oder mehr begriffliche Module wurden verheddert. Gehen Sie zurück zu Ihrer Anrufliste, und gruppieren Sie die Symbole so zu zerschneiden, die problematischen Dateien in kleineren unabhängigen Einheiten (Sie müssen die Datei selbst überprüfen für hier lokale Sprünge Ihres angenommener Schnitt ist möglich zu sehen).

Zum Ende es sei denn, Sie arbeiten bereits an anderer Stelle für Ihre eigenen gut, werden Sie eine hierarchische Aufrufdiagramm mit konzeptionellen Modulen erhalten. Daraus ist es möglich, die Software der absichtliche Architektur und arbeitet weiter abzuziehen.

Das nächste Ziel ist die Architektur . Durch Ihre gemachte Karte vorher müssen Sie entlang der Software navigieren, herauszufinden, es Threads (Interrupt und Hauptprogrammaufgaben), und die groben Zwecke jedes der Module / Quelldateien. Wie können Sie dies tun, und Sie bekommen, was hier hängt mehr von der Anwendungsdomäne.

Wenn diese beiden fertig sind, die „Ruhe“ und nicht einfach ist. Durch diese sollten Sie im Wesentlichen wissen, was jeder Teil der Sache tun soll, und so wissen Sie, was Sie wahrscheinlich beschäftigen uns mit, wenn Sie auf einer Quelldatei zu arbeiten beginnen. Es ist jedoch wichtig, dass, wenn Sie etwas „faul“ in einer Quelle finden, dassdas Programm scheint etwas irrelevant, zu tun, um Ihre Architektur und Call-Graph zurück zu gehen und Korrekturen vornehmen, wenn nötig.

Für den Rest der genannten Methoden gilt unter anderem gut. Ich skizzierte gerade diese einen Einblick zu geben, was in wirklich abscheulichen Fällen geschehen. Ich wünschte, ich nur 10K Zeilen Code hatte dann mit zurück zu beschäftigen ...

Ich würde sagen, IanW Antwort (drucken Sie es einfach aus und halten Tracing) ist wahrscheinlich die beste. Das heißt, ich habe ein wenig von der Wand Idee:

Versuchen Sie den Code (wahrscheinlich die binär) durch einen dissembler ausgeführt wird, der C-Code rekonstruieren können (wenn Sie eine für die 8051 zu finden). Vielleicht wird es ein paar Routinen identifizieren Sie nicht (leicht).

Vielleicht wird es helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top