Domanda

Devo ottimizzare il codice per avere spazio per un nuovo codice. Non ho lo spazio per tutte le modifiche. Non riesco a utilizzare la commutazione del code bank (80c31 con 64k).

È stato utile?

Soluzione

Non hai davvero dato molto da fare qui, ma ci sono due livelli principali di ottimizzazioni che puoi prendere in considerazione:

Micro-Ottimizzazioni:   per esempio. XOR A invece di MOV A, 0   Adam ha affrontato alcuni di questi ben prima.

Macro-Ottimizzazioni:   Guarda la struttura del tuo programma, le strutture dei dati e gli algoritmi utilizzati, le attività eseguite e pensa MOLTO a come questi potrebbero essere riorganizzati o addirittura rimossi. Ci sono interi pezzi di codice che in realtà non vengono utilizzati? Il tuo codice è pieno di istruzioni di output di debug che l'utente non vede mai? Esistono funzioni specifiche per un singolo cliente che è possibile escludere da una versione generale?

Per capire bene ciò, dovrai capire DOVE la tua memoria è esaurita. La mappa di Linker è un buon punto di partenza con questo. Le ottimizzazioni macro sono dove si possono ottenere le GRANDI vittorie.

A parte questo, potresti - seriamente - provare a riscrivere parti del tuo codice con un buon compilatore C ottimizzante. Potresti essere sorpreso di quanto stretto possa essere il codice. Un vero hotshot assemblatore può essere in grado di migliorarlo, ma può essere facilmente migliore della maggior parte dei programmatori. Ho usato IAR circa 20 anni fa, e mi ha fatto saltare le calze.

Altri suggerimenti

Con il linguaggio assembly, dovrai ottimizzare a mano. Ecco alcune tecniche:

Nota: IANA8051P (non sono un programmatore 8501 ma ho fatto un sacco di assemblaggio su altri chip a 8 bit).

Scorri il codice alla ricerca di bit duplicati, non importa quanto piccolo e falli funzionare.

Scopri alcune delle istruzioni più insolite e vedi se puoi usarle per ottimizzare, ad es. Un bel trucco è usare XOR A per cancellare l'accumulatore invece di MOV A, 0 - salva un byte.

Un altro trucco pulito è se chiamate una funzione prima di tornare, saltateci sopra ad es. invece di:

CALL otherfunc
RET

Basta fare:

JMP otherfunc

Assicurati sempre di eseguire salti e rami relativi, laddove possibile, utilizzano meno memoria dei salti assoluti.

Questo è tutto ciò che riesco a pensare fuori dalla testa per il momento.

Mi dispiace, sto arrivando così tardi, ma una volta ho avuto esattamente lo stesso problema, ed è diventato un problema ripetuto che continuava a tornare da me. Nel mio caso il progetto era un telefono, su un processore della famiglia 8051, e avevo completamente esaurito la memoria ROM (codice). Continuava a tornare da me perché il management continuava a richiedere nuove funzionalità, quindi ogni nuova funzionalità è diventata un processo in due fasi. 1) Ottimizza le cose vecchie per creare spazio 2) Implementa la nuova funzionalità, utilizzando la stanza che ho appena creato.

Esistono due approcci all'ottimizzazione. Tattico e strategico. Le ottimizzazioni tattiche consentono di risparmiare qualche byte alla volta con un'idea di micro ottimizzazione. Penso che tu abbia bisogno di ottimizzazioni strategiche che comportino un ripensamento più radicale su come stai facendo le cose.

Qualcosa che ricordo ha funzionato per me e potrebbe funzionare per te;

Osserva l'essenza di ciò che il tuo codice deve fare e prova a distillare alcune operazioni primitive flessibili davvero forti. Quindi ricostruisci il tuo codice di livello superiore in modo che non faccia nulla di basso livello tranne chiamare le primitive. Idealmente usa un approccio basato su una tabella, la tua tabella contiene cose come; Stato di input, evento, stato di output, primitive .... In altre parole, quando si verifica un evento, cercare una cella nella tabella per quell'evento nello stato corrente. Quella cella ti dice in quale nuovo stato cambiare (facoltativamente) e quali primitive (se presenti) da eseguire. Potrebbero essere necessari più insiemi di stati / eventi / tabelle / primitivi per diversi livelli / sottosistemi.

Uno dei molti vantaggi di questo approccio è che puoi pensarlo come costruire un linguaggio personalizzato per il tuo problema particolare, in cui puoi creare in modo molto efficiente (ad esempio con un codice extra minimo) nuove funzionalità semplicemente modificando la tabella.

Mi dispiace, sono in ritardo di mesi e probabilmente non hai avuto il tempo di fare qualcosa di così radicale. Per quanto ne so, stavi già usando un approccio simile! Ma la mia risposta potrebbe aiutare qualcun altro un giorno a saperlo.

Nel reparto distrutto, potresti anche considerare di comprimere parte del tuo codice e mantenere solo una parte che viene utilizzata attivamente decompressa in un determinato momento. Ho difficoltà a credere che il codice richiesto per il sistema di compressione / decompressione sarebbe abbastanza piccolo una porzione della minuscola memoria dell'8051 per renderlo utile, ma ha funzionato a meraviglia su sistemi leggermente più grandi.

Ancora un altro approccio è quello di passare a un formato di codice byte o al tipo di codice basato su tabella che alcuni output di macchine utensili di stato - avere una macchina capire cosa sta facendo la tua app e generare un'implementazione completamente incomprensibile può essere un'ottima modo per risparmiare spazio :)

Infine, se il codice è effettivamente compilato in C, suggerirei di compilare con una gamma di opzioni diverse per vedere cosa succede. Inoltre, Ho scritto un pezzo sulla codifica C compatta per l'ESC nel 2001 è ancora abbastanza attuale. Vedi quel testo per altri trucchi per macchine piccole.

1) Laddove possibile, salvare le variabili in Idata, non in xdata
2) Guarda le tue dichiarazioni Jmp - usa SJmp e AJmp

Suppongo che tu sappia che non andrà bene perché hai scritto / rispettato e ottenuto la "memoria esaurita" errore. :) Sembra che le risposte rispondano alla tua domanda in modo abbastanza accurato; a corto di ottenere esempi di codice.

Vorrei tuttavia raccomandare alcune considerazioni aggiuntive;

  1. Assicurati che tutto il codice sia davvero in uso - test di copertura del codice? Un il sub inutilizzato è una grande vittoria - questo è un passo difficile - se sei l'originale autore, potrebbe essere più semplice - (beh, forse) :)
  2. Assicurati che il livello di "verifica" sia e inizializzazione - a volte noi hanno la tendenza ad essere troppo zelanti nell'assicurare abbiamo inizializzato variabili / memoria e abbastanza sicuro giustamente, quante volte abbiamo stato morso da esso. Non dire di no inizializzare (duh), ma se lo stiamo facendo una mossa di memoria, la destinazione per prima cosa non è necessario essere zero - questo combacia con

    1 -

  3. Valuta le nuove funzionalità - può un sub esistente essere migliorato per coprire entrambe le funzioni o forse un funzione esistente sostituita?
  4. Rompi il codice grande se un pezzo di il big code può salvare creando un nuovo piccolo codice.

o forse c'è un argomento per l'hardware versione 2.0 sul tavolo ora ... :)

Per quanto riguarda

Oltre alle già ovvie (più o meno) ottimizzazioni ovvie, eccone una davvero strana (e quasi impossibile da raggiungere): il riutilizzo del codice. E con Riutilizzo del codice non intendo il normale riutilizzo, ma per a) riutilizzare il codice come dati oppure b) per riutilizzare il codice come altro codice. Forse puoi creare un lut (o qualunque altro dato statico) che possa essere rappresentato dagli asm hex opcode (qui devi guardare harvard vs von neumann architecture).

L'altro riutilizzerebbe il codice dando al codice un significato diverso quando lo indirizzi diversamente. Ecco un esempio per chiarire cosa intendo. Se i byte per il tuo codice assomigliano a questo: AABCCCDDEEFFGGHH all'indirizzo X dove ogni lettera rappresenta un codice operativo, immagina di passare subito a X + 1. Forse otterrai una funzionalità completamente diversa in cui i byte separati ora dallo spazio formano i nuovi codici operativi: ABC CCD DE EF GH.

Ma attenzione: questo non è solo difficile da raggiungere (forse è impossibile), ma è un orrore da mantenere. Quindi, se non sei un codice demo (o qualcosa di simile esotico), consiglierei di utilizzare i modi già menzionati per salvare mem.

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