Domanda

Ho ereditato un 10K-line programma scritto in 8051 linguaggio assembly che necessita di alcune modifiche.Purtroppo è scritto nella migliore tradizione di spaghetti code.Il programma--scritto come un singolo file--è un labirinto di CHIAMATA e LJMP dichiarazioni (circa 1200 totale), con subroutine avere più voce e/o punti di uscita, se essi possono essere identificati come i sottoprogrammi a tutti.Tutte le variabili sono globali.Non ci sono commenti;alcuni sono corrette.Non ci sono le prove esistenti, e in assenza di un budget per il refactoring.

Un po ' di background sull'applicazione:Il codice controlla un hub di comunicazione in un distributore di un applicazione che è attualmente distribuito a livello internazionale.Gestisce due serie flussi contemporaneamente (con l'aiuto di un altro processore di comunicazione) e può parlare a un massimo di quattro dispositivi fisici diversi, ciascuno da un diverso fornitore.Il produttore di uno dei dispositivi che ha recentemente fatto un cambiamento ("Sì, abbiamo fatto una modifica, ma il software è assolutamente la stessa cosa!") che causa alcune configurazioni di sistema a non funzionare più, e non è interessato a immutabile è (cosa non cambia).

Il programma è stato originariamente scritto da un'altra società, il trasferimento per il mio cliente, poi modificato nove anni fa da un altro consulente.Né la società originale, né il consulente, sono disponibili come risorse.

Sulla base di analisi del traffico su uno dei bus seriali, ho creato un hack, che sembra funzionare, ma è brutto e non affrontare la causa principale.Se ho avuto una migliore comprensione del programma, io credo che per affrontare il problema effettivo.Ho circa una settimana in più prima che il codice è congelato a sostegno di un la fine del mese della data di spedizione.

Domanda originale:Ho bisogno di capire il programma abbastanza bene per fare le modifiche senza rotture.Qualcuno ha sviluppato le tecniche per lavorare con questo tipo di casino?

Ho visto alcuni grandi suggerimenti qui, ma sono limitate dal tempo.Tuttavia io possa avere un'altra possibilità in futuro di perseguire alcuni dei più coinvolti i corsi di azione.

È stato utile?

Soluzione

Primo, vorrei provare a entrare in contatto con quelle persone che originariamente sviluppato il codice o che almeno mantenuto davanti a me, speriamo di ottenere informazioni sufficienti per ottenere una conoscenza di base del codice generale, in modo che si può iniziare ad aggiungere utili commenti.

Forse si può anche chiedere a qualcuno di descrivere le principali Api (compresa la loro firma, il valore di ritorno e fine) per il codice.Se lo stato globale è modificato da una funzione, questo deve essere reso esplicito.Allo stesso modo, iniziare a distinguere tra funzioni e procedure, nonché di ingresso/uscita registri.

Si dovrebbe fare molto chiara per il datore di lavoro che questa informazione è necessaria, se non ti credo, li hanno effettivamente sedersi con voi davanti questo codice in fase di descrivere ciò che si suppone di fare e come devi farlo (reverse engineering).Avendo un datore di lavoro con un background in informatica e programmazione effettivamente essere utile in quel caso!

Se il vostro datore di lavoro non dispone di un tale background tecnico, chiedi a lui per portare un altro programmatore/collega di spiegare i tuoi passi verso di lui, così facendo in realtà lo spettacolo che si sono seri e onesti su di esso, perché è un problema reale - e non solo dal tuo punto di vista (assicurarsi di avere colleghi che sanno su questo "progetto").

Se è disponibile e se fattibile, vorrei farlo anche molto chiaro, che il contraente (o almeno contattare) ex sviluppatori/manutentori (se non sono più di lavoro per la vostra azienda, che è) per documentare questo codice dovrebbe essere un pre-requisito realisticamente migliorare il codice all'interno di un breve lasso di tempo e per garantire che possa essere più facilmente mantenuto in futuro.

Sottolineare che tutta questa situazione è, a causa di carenze nel precedente processo di sviluppo del software e che questi passaggi vi aiuteranno a migliorare il codice di base.Così, la base di codice nella sua forma attuale, è un problema crescente e tutto ciò che viene fatto ora, per gestire questo problema è un investimento per il futuro.

Questo, di per sé, è anche importante per aiutarli a valutare e capire la tua situazione:Per fare ciò che si suppone di fare, ora, è tutt'altro che banale, e si dovrebbe sapere su di esso - se solo impostare loro aspettative dritto (ad es.per quanto riguarda le scadenze e la complessità del compito).

Inoltre, personalmente mi sento di iniziare ad aggiungere i test unitari per le parti che ho capito abbastanza bene, in modo che io possa cominciare lentamente refactoring/riscrittura del codice.

In altre parole, una buona documentazione e codice sorgente commenti sono una cosa, ma avere una completa suite di test è un'altra cosa importante, nessuno può realisticamente aspettare di modificare un cambiamento di codice di base senza alcuna stabilita modo per testare la funzionalità del tasto.

Dato che il codice è 10K, vorrei anche prendere in considerazione di factoring fuori sottoprogrammi, in un file separato per realizzare componenti più identificabili, utilizzando preferibilmente l'accesso wrapper invece di variabili globali e anche intuitiva nomi di file.

Inoltre, vorrei guardare in misure per migliorare ulteriormente la leggibilità del codice sorgente diminuendo la complessità, avendo le routine sub con più punti di accesso (e forse anche di parametri diversi per le firme?) sembra un modo sicuro per offuscare il codice inutilmente.

Allo stesso modo, enorme sub routine potrebbe anche essere rielaborate in quelli più piccoli per contribuire a migliorare la leggibilità.

Così, una delle prime cose, mi piacerebbe guardare nel fare dovrebbe essere quello di determinare quelle cose che rendono davvero complicato capire il codice di base e poi rielaborare quelle parti, per esempio dividendo enorme sub routine con più punti di accesso in sottogruppi distinti di routine che si chiamano l'un l'altro, invece.Se questo non può essere fatto a causa di motivi di prestazioni o chiamare il sovraccarico, l'utilizzo di macro, invece.

Inoltre, se è una valida opzione, vorrei prendere in considerazione in modo incrementale di riscrivere parti di codice mediante un più alto livello di linguaggio, utilizzando un sottoinsieme di C, o almeno facendo abbastanza eccessivo uso di assemblaggio macro per aiutare a standardizzare il codice di base, ma anche per aiutare a localizzare potenziali bug.

Se un incrementale riscrivere in C è un opzione fattibile, un modo per iniziare sarebbe quello di girare tutte le ovvie funzioni in C funzioni i cui corpi sono -all'inizio - copiato/incollato dal file di assieme, in modo che si finisce con funzioni di C con un sacco di assembly inline.

Personalmente, vorrei provare anche con l'esecuzione di codice in un simulatore/emulatore facilmente il passaggio attraverso il codice e speriamo di iniziare a comprendere gli elementi costitutivi più importanti (mentre l'esame di registrare e stack di utilizzo), una buona 8051 simulatore di con un debugger integrato dovrebbe essere reso disponibile se si hanno veramente a fare questo in gran parte sul proprio.

Questo sarebbe anche aiutare a trovare la sequenza di inizializzazione e loop principale struttura come un callgraph.

Forse, si può anche trovare un buon open source 80851 simulatore che può essere facilmente modificato per fornire, inoltre, una completa callgraph automaticamente, solo facendo una rapida ricerca, ho trovato gsim51, ma ci sono ovviamente molte altre opzioni, diversi proprietari pure.

Se fossi nella tua situazione, vorrei anche prendere in considerazione l'outsourcing sforzo di modificare i miei strumenti per semplificare l'utilizzo di questo codice sorgente, cioèmolti sourceforge progetti di accettare donazioni e forse si può parlare con il vostro datore di lavoro in sponsorizzazione di tale modifica.

Se non finanziariamente, forse da voi fornendo il corrispondente le patch?

Se si sta già utilizzando un prodotto proprietario, si potrebbe anche essere in grado di parlare con il produttore di questo software e di dettaglio le vostre esigenze e chiedere loro se sono disposti a migliorare questo prodotto in quel modo o se hanno la possibilità di esporre un'interfaccia per consentire ai clienti di effettuare tali personalizzazioni (una qualche forma di API interno o forse anche semplice colla script).

Se non sono reattivo, indicano che il vostro datore di lavoro ha pensato di usare un prodotto diverso per qualche tempo e che tu eri l'unico a insistere su quel particolare prodotto per essere utilizzato ...;-)

Se il software si aspetta certo di I/O hardware e periferiche, si potrebbe anche voler guardare in scrittura di un corrispondente simulazione hardware ciclo per eseguire il software in un emulatore.

In definitiva, io so per certo che sarei personalmente molto più godere il processo di personalizzazione di altri software per aiutarmi a capire un codice degli spaghetti monster, che manualmente passo il codice e la riproduzione di emulatore di me stesso, non importa quanti litri di caffè che posso ottenere.

Ottenere un utile callgraph di un open source 8051 emulatore non dovrebbe richiedere molto più tempo di dire un fine settimana (al massimo), perché significa soprattutto cercare di CHIAMATA istruzioni e registrare i loro indirizzi (di posizione e di destinazione), in modo che tutto scaricato un file per il controllo successivo.

Di avere accesso a un emulatore interne sarebbe in realtà essere un grande modo per ispezionare ulteriormente il codice, per esempio per trovare modelli ricorrenti di istruzioni (diciamo il 20 e il 50+), che può essere preso in considerazione in standalone funzioni/procedure, questo potrebbe effettivamente contribuire a ridurre le dimensioni e la complessità del codice di base ancora di più.

Il passo successivo sarebbe probabilmente esaminare stack di registro e di utilizzo.E per determinare il tipo/dimensione e funzione di parametri utilizzati, così come il loro valore di gamma, in modo che si può concepire la corrispondente unità di test.

Utilizzando strumenti come dot/graphviz per visualizzare la struttura della sequenza di inizializzazione e il ciclo principale di per sé, sarà una gioia pura rispetto a fare tutto questo manualmente.

Inoltre, sarà in realtà finiscono con dati e documenti che possono servire come base per una migliore documentazione nel lungo periodo.

Altri suggerimenti

Ho paura che non esiste una ricetta magica per questo tipo di problema. Trovo l'unica soluzione è quello di stampare il file ASM poi andare da qualche parte tranquilla e di simulare l'esecuzione del programma riga per riga nella vostra mente (durante la scrittura il contenuto dei registri e locazioni di memoria su un blocco note). Dopo un po 'a trovare questo non ci vuole il tempo che ci si aspetterebbe. Preparatevi a trascorrere molte ore a fare questo e bere litri di caffè. Dopo un po 'si avrà una comprensione di ciò che sta facendo e si può prendere in considerazione le modifiche.

Fa il 8051 ha qualunque porte IO non utilizzati? Se lo fa e non si può capire quando alcune routine sono chiamati quindi aggiungere codice per inviare ad alta queste porte di ricambio o bassa. Poi quando il programma è in esecuzione guardare queste porte con un oscilloscopio.

In bocca al lupo

So che sembra folle .... ma io sono disoccupato (ho preso momento sbagliato per dire al partner di marjority di andare all'inferno) e avere un po 'di tempo libero. Sarei disposto a dare un'occhiata a questo. Ho usato per scrivere il montaggio per l'Apple] [e il PC originale. Se potessi giocare con il codice sul simulatore per un paio d'ore ho potuto dare un'idea se ho la possibilità di documentare per voi (senza runing la mia vacanza non pianificata). Dal momento che non so nulla di questo 8051 potrebbe non essere possibile per uno come me, ma il simulatore sembrava promettente. Non vorrei che i soldi per fare questo. La sua appena sufficiente per ottenere l'esposizione al 8051 lo sviluppo embedded. Ti ho detto che questo sarebbe sembrare pazzesco.

Trovare un altro di posti di lavoro serio! In mancanza di ciò il libro "lavorare in modo efficace con il codice legacy" potrebbe Help- anche se penso che si riferisce a codice legacy come codice senza test di unità.

Ho fatto questo genere di cose un paio di volte. Alcune raccomandazioni:

  • Inizia a esaminare lo schema, questo dovrebbe aiutare a capire che cosa porte e perni le modifiche desiderate impatto.
  • Usa grep per trovare tutte le chiamate, rami, salti e ritorna. Questo può aiutare a capire il flusso e identificare i pezzi di codice.
  • Guarda il vettore di reset e interrompere tabella per identificare la linee principali.
  • Usa grep per creare un riferimento incrociato per tutte le etichette di codice e dati riferimenti (se il vostro assemblatore strumenti non possono farlo per voi).

Tenete a mente la legge di Hofstadter: Ci vuole sempre più tempo del previsto, anche quando si prende in considerazione la legge di Hofstadter .

In bocca al lupo.

Come ben si capisce la piattaforma hardware di questo codice è in esecuzione su?

  • E 'stato messo in power down mode (PCON = 2) per risparmiare energia Se è così come è stato svegliato. (Un reset o su hardware interrupt)

  • Avete aspettare un per l'oscillatore a stalle dopo una potenza fino prima di fare comunicazione seriale

  • E 'stato messo in modalità sleep (PCON = 1)

Esistono diverse versioni dell'hardware sul campo?

Assicurarsi di avere tutte le diverse varianti hardware per testare su.

Non sprecate il vostro tempo con un simulatore - è molto difficile da lavorare e si deve fare un sacco di ipotesi riguardanti l'hardware. Procuratevi un In Circuit Emulator (ICE) ed eseguire su hardware.

Il software è stato scritto in assembler per un motivo avete bisogno di scoprire perché. cioè - vincoli di memoria - vincoli di velocità

Ci può essere una ragione per cui questo codice è un casino

Dai un'occhiata al file link:

XDATA SPACE, IDATA spazio e spazio di codice:

Se non v'è spazio di codice libero o Xdata o Idata?

L'autore originale potrebbe essere Optimizationed per adattarsi allo spazio di memoria disponibile.

Se questo è il caso è necessario parlare con lo sviluppatore originale per scoprire quello che ha fatto .

Non è necessario un budget speciale per il refactoring e prove - fanno risparmiare soldi e ti permettono di lavorare più velocemente - arrivare ad essa. E 'la tecnica si dovrebbe usare per aggiungere le modifiche al patrimonio, il codice ereditato perché è il modo più economico per farlo senza "senza rotture".

La maggior parte del tempo, penso che ci sia un trade-off in cui si ottiene più qualità in cambio di trascorrere più tempo, ma con il codice legacy che si ha familiarità con, penso che sia più veloce per fare prove - devi correre il codice prima che lo spediciate, giusto?

Questa è una delle poche volte che ho intenzione di raccomandare si mette le soft skills per lavorare, e presentare il vostro PM / Gestore / CXO con il tuo ragionamento dietro una ri-scrittura, e il risparmio di tempo / costo coinvolto con tale un'impresa

Tagliare a pezzi.

Ho avuto qualche problema molto simile con un software di 8052. Così l'azienda ha ereditato come una bestia, il codice ROM completo (64Kbytes), circa 1,5 mega di moduli di spaghetti di assemblaggio più due linee di 3000 moduli PL / M composte questa codifica mostruosità. Gli sviluppatori originali del software erano morti da tempo (questo non significa che non ci fosse nessuno, ma anzi nessuno che avrebbe capito nel suo insieme), i compilatori compilazione di questi sono stati da anni 80 centrali in esecuzione su un MDS-70 emulatore, e molti critici moduli erano i limiti di questi compilatori. Come aggiungere un altro simbolo globale, e il linker potrebbe andare in crash. Aggiungere più un simbolo a un file ASM, e il compilatore potrebbe andare in crash.

Quindi, come si potrebbe iniziare a tagliare questo?

In primo luogo è bisogno di strumenti. Notepad ++ per esempio, è una cosa molto bella in quanto può essere utilizzato per attraversare ricerca insieme più file contemporaneamente, ideale per trovare quale dei moduli si riferiscono un simbolo globale. Questo è probabilmente l'elemento più importante.

Se possibile, ottenere tutte le carte si possono trovare sul software. Il problema più immediato da risolvere con queste bestie è quello di capire il modo in cui sono più o meno composte, qual è la loro architettura. Questo di solito non è incluso nel software stesso, nemmeno se è correttamente altrimenti commentato.

Per ottenere l'architettura da soli, prima si può tentare di costruire un grafico delle chiamate . E 'più semplice da fare che un grafico flusso di dati dal momento che di solito ci sono le chiamate e salti di variabili globali meno cross-file. Per questo invito i grafici considerano solo simboli globali assumendo i file di origine si suppone siano i moduli (che non è necessariamente vero, ma di solito dovrebbero essere).

Per fare questo, usare lo strumento per la ricerca di file croce, creare un elenco di grandi dimensioni (per esempio in OpenOffice Calc), dove si raccolgono cui simbolo è definito, in cui file e quali file fare riferimento a questo simbolo chiamandolo.

Poi rubare alcuni grandi (!) Fogli dal plotter, e iniziare a disegnare. Se siete molto abili in alcuni software grafico, è possibile utilizzare, ma se non è così, è più probabile che tenere indietro. Quindi disegnare un grafico che mostra la chiamata che file ha chiamate a cui altri file (non mostrano i simboli stessi, con 50 o giù di file, non sarebbe in grado di gestirlo).

Molto probabilmente il risultato di questo sarà uno spaghetti. L'obiettivo è quello di raddrizzare questo fuori per ottenere una struttura gerarchica con una radice (che sarà il file che contiene il punto di ingresso del programma) senza loop. Si può divorare diversi fogli durante questo processo iterativo raddrizzare la bestia fuori. Si può anche trovare alcuni file sono molto inter-aggrovigliato che non possono essere rappresentati senza loop. Questo caso è molto probabile che un "modulo" single ottenuto in qualche modo separato in due file, o moduli più concettuali sono stati aggrovigliato. Torna alla lista delle chiamate, e di gruppo i simboli in modo per tagliare i file problematici in unità indipendenti più piccole (è necessario verificare il file stesso troppo per i salti locali qui per vedere il vostro taglio assunto è possibile).

Per la fine a meno che non si sta già lavorando da qualche altra parte per il tuo bene, si otterrà un grafico delle chiamate gerarchico con i moduli concettuali. Da ciò è possibile dedurre l'architettura intenzionale del software e lavorare ulteriormente.

Il prossimo obiettivo è il Architettura . Con la vostra carta fatta in precedenza è necessario per navigare lungo il software, capire che di discussioni (interrompere e compiti principali del programma), e gli scopi di massima di ogni file moduli / sorgente. Come si può fare questo e quello che si ottiene qui dipende più dominio di applicazione.

Quando questi due sono fatti, il "resto" è piuttosto semplice. Con questi si dovrebbe in sostanza sapere che cosa si suppone ogni parte della cosa da fare, e in modo da sapere cosa si sta probabilmente a che fare con quando si inizia a lavorare su un file sorgente. E 'importante però che ogni volta che si trova qualcosa di "pesce" in una fonte, cheil programma sembra fare qualcosa di irrilevante, di tornare alla propria architettura e la chiamata grafico, e fare le correzioni necessarie.

Per il resto i metodi altri citati si applicano bene. Ho appena delineato questi per dare una certa comprensione su ciò che può essere fatto in casi veramente orribili. Vorrei avere solo 10K righe di codice a che fare con allora ...

Direi che la risposta di IanW (basta stamparlo e mantenere tracing) è probabilmente il migliore. Detto questo, ho un po 'fuori l'idea parete:

Provare a eseguire il codice (probabilmente il binario) attraverso un simulatore in grado di ricostruire il codice C (se si può trovare uno per il 8051). Forse sarà identificare alcune routine non si può (facilmente).

Forse ti aiuto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top