8051アセンブリ言語でメモリを最適化するために利用できるテクニックは何ですか?
-
22-07-2019 - |
質問
コードを最適化して、新しいコード用のスペースを確保する必要があります。すべての変更のためのスペースがありません。コードバンクスイッチング(64kで80c31)を使用できません。
解決
実際にここまで進むことはあまりありませんが、考慮できる最適化の主なレベルは2つあります:
マイクロ最適化: 例えば。 MOV A、0の代わりにXOR A Adamはこれらのいくつかを以前にうまく説明しました。
マクロ最適化: プログラムの構造、使用されているデータ構造とアルゴリズム、実行されたタスクを確認し、これらをどのように再配置または削除することができるかを非常によく考えてください。実際に使用されていないコードの塊がありますか?コードには、ユーザーに表示されないデバッグ出力ステートメントがいっぱいですか?一般リリースから除外できる単一の顧客に固有の機能はありますか?
その上で適切なハンドルを取得するには、メモリが使い果たされている場所を見つける必要があります。リンカーマップは、これから始めるのに適した場所です。マクロ最適化は、BIGが勝つことができる場所です。
余談ですが、真剣に-適切な最適化Cコンパイラでコードの一部を書き換えてみてください。コードがどれほどタイトであるかに驚くかもしれません。真のアセンブラーのホットショットはそれを改善することができるかもしれませんが、ほとんどのコーダーより簡単に優れている可能性があります。約20年前に IAR を使用し、靴下が吹き飛ばされました。
他のヒント
アセンブリ言語では、手動で最適化する必要があります。以下にいくつかのテクニックを示します。
注:IANA8051P(私は8501プログラマーではありませんが、他の8ビットチップで多くのアセンブリを行っています)。
コードを調べて、どんなに小さくても重複ビットを探し、それらを機能させます。
より一般的な手順のいくつかを学習し、それらを使用して最適化できるかどうかを確認します。すばらしいトリックは、MOV A、0の代わりにXOR Aを使用してアキュムレータをクリアすることです-バイトを節約します。
もう1つの巧妙なトリックは、戻る前に関数を呼び出して、次のようにジャンプするだけです。
CALL otherfunc
RET
やる:
JMP otherfunc
常に可能な限り相対的なジャンプと分岐を行っていることを確認し、絶対ジャンプよりも少ないメモリを使用します。
これで今のところ頭の外から考えることができます。
申し訳ありませんが、私はこれに遅れて来ていますが、かつてまったく同じ問題を抱えていたため、繰り返し問題になり、私に戻ってきました。私の場合、プロジェクトは8051ファミリプロセッサ上の電話であり、ROM(コード)メモリを完全に使い果たしていました。管理者が新しい機能を要求し続けたため、私に戻ってきました。そのため、新しい機能はそれぞれ2段階のプロセスになりました。 1)古いものを最適化して部屋を作ります2)新しい機能を実装し、今作った部屋を使い果たします。
最適化には2つのアプローチがあります。戦術的および戦略的。戦術的な最適化は、マイクロ最適化のアイデアにより、一度に数バイトを節約します。戦略的な最適化が必要だと思います。これには、あなたが物事をどのように行っているかについてのより根本的な再考が含まれます。
覚えている何かが私のために働いていて、あなたのために働くことができた;
あなたのコードがしなければならないことの本質を見て、いくつかの本当に強力で柔軟なプリミティブ操作を蒸留してみてください。次に、プリミティブの呼び出しを除いて、低レベルがまったく実行されないように、トップレベルのコードを再構築します。理想的にはテーブルベースのアプローチを使用します。テーブルには次のものが含まれます。入力状態、イベント、出力状態、プリミティブ…。つまり、イベントが発生した場合、現在の状態でそのイベントのテーブル内のセルを検索します。そのセルは、どの新しい状態に変更するか(オプション)および実行するプリミティブ(ある場合)を示します。異なるレイヤー/サブシステムの状態/イベント/テーブル/プリミティブの複数のセットが必要になる場合があります。
このアプローチの多くの利点の1つは、特定の問題に対してカスタム言語を構築することと考えることができることです。この方法では、テーブルを変更するだけで非常に効率的に(つまり最小限のコードで)新しい機能を作成できます。
すみません、私は数ヶ月遅れており、おそらくあなたはおそらくこの過激な何かをする時間を持っていませんでした。あなたがすでに同様のアプローチを使用していることを私は知っています!しかし、私の答えは、いつか知っている誰かを助けるかもしれません。
強引な部門では、コードの一部を圧縮し、特定の時点でアクティブに使用される一部のみを圧縮解除することも検討できます。圧縮/解凍システムに必要なコードは8051の小さなメモリの一部で十分に小さいと信じるのに苦労しますが、わずかに大きなシステムでは驚異的な働きをしました。
さらに別のアプローチは、一部のステートマシンツールが出力するバイトコード形式またはテーブル駆動型のコードに切り替えることです-マシンにアプリの動作を理解させ、完全に理解できない実装を生成することは素晴らしいことです部屋を節約する方法:)
最後に、コードが実際にCでコンパイルされている場合は、さまざまなオプションを使用してコンパイルし、何が起こるかを確認することをお勧めします。また、 2001年にESCのコンパクトCコーディングに関する記事を書きましたそれはまだかなり最新です。小型マシン用の他のトリックについては、そのテキストを参照してください。
1)可能であれば、変数をxdataではなくIdataに保存します
2)Jmpステートメントを見て– SJmpとAJmpを使用する
あなたが書いた/書いて「メモリ不足」になったために収まらないことがわかっていると思います。エラー。 :)答えはあなたの質問にかなり正確に答えているようです。コード例が不足しています。
ただし、いくつかの追加の考えをお勧めします;
- すべてのコードが本当にであることを確認してください 使用されている-コードカバレッジテスト?あ 未使用のサブは大きな勝利です-これは 難しいステップ-あなたがオリジナルなら 著者、それはもっと簡単かもしれません-(まあ、多分):)
- 「検証」のレベルを確認します。
および初期化-時々私たち
熱心すぎる傾向がある
初期化されていることを保証する
変数/メモリと十分に確か
そうですね、私たちは何回
それに噛まれた。言わないで
初期化(ダウ)しますが、
メモリ移動、宛先
最初にゼロ化する必要はありません -
これはありと
1-
- 新機能を評価する-できる 既存のサブをカバーするように拡張する 両方の機能またはおそらく 既存の機能が置き換えられましたか?
- 一部の場合、大きなコードを分割します 大きなコードは新しいものを作成する 小さなコード。
またはテーブルにハードウェアバージョン2.0の引数があるかもしれません...:)
よろしく
すでに述べた(多かれ少なかれ)明白な最適化に加えて、ここには本当に奇妙な(そして達成するのがほとんど不可能な)最適化があります:コードの再利用。また、コードの再利用では、通常の再利用を意味しませんが、a)コードをデータとして再利用するか、b)コードを他のコードとして再利用します。たぶん、asm hexオペコードで表すことができるlut(または静的データ)を作成できます(ここでは、ハーバードとフォンノイマンのアーキテクチャを調べる必要があります)。
もう1つは、別のコードに対処するときにコードに別の意味を与えることで、コードを再利用します。ここで私が意味することを明確にするための例。コードのバイトが次のように見える場合:各文字が1つのオペコードを表すアドレスXのAABCCCDDEEFFGGHHが、X + 1にジャンプすると想像してください。たぶん、スペースで区切られたバイトが新しいオペコードを形成する、完全に異なる機能を取得できます:ABC CCD DE EF GH。
しかし注意してください:これは達成するのが難しいだけでなく(おそらく不可能)、維持するのが恐ろしいことです。そのため、デモコード(またはエキゾチックな類似物)でない場合は、既に説明した他の方法を使用してmemを保存することをお勧めします。