0

コードの場合:

uint8_t count;

ISR(TIMER1_OVF_vect, ISR_NAKED)
{
    count++;
    reti();
}

生成されたアセンブリは次のとおりです。

--- F:\atmel-prj\compiler-test2\compiler-test2\Debug/.././compiler-test2.c -----
{
00000048  PUSH R1       Push register on stack 
00000049  PUSH R0       Push register on stack 
0000004A  IN R0,0x3F        In from I/O location 
0000004B  PUSH R0       Push register on stack 
0000004C  CLR R1        Clear Register 
0000004D  PUSH R24      Push register on stack 
    count++;
0000004E  LDS R24,0x0100        Load direct from data space 
00000050  SUBI R24,0xFF     Subtract immediate 
00000051  STS 0x0100,R24        Store direct to data space 
}
00000053  POP R24       Pop register from stack 
00000054  POP R0        Pop register from stack 
00000055  OUT 0x3F,R0       Out to I/O location 
00000056  POP R0        Pop register from stack 
00000057  POP R1        Pop register from stack 
00000058  RETI      Interrupt return 

現在、私が見ているように、少なくとも 1 つ、最大 2 つのプッシュ/ポップ ペアを排除できます。

  1. 1 回のプッシュ/ポップを節約するには、代わりに r0 を使用して r24 を削除します

    PUSH R1     Push register on stack 
    PUSH R0     Push register on stack 
    IN R0,0x3F      In from I/O location 
    PUSH R0     Push register on stack 
    CLR R1      Clear Register 
    count++;
    LDS R0,0x0100       Load direct from data space 
    SUBI R0,0xFF        Subtract immediate 
    STS 0x0100,R0       Store direct to data space 
    ...
    
  2. 値 0 に r1 を使用しているコードはないので、すべての目的で r1 のみを使用してください。

    PUSH R1     Push register on stack 
    IN R1,0x3F      In from I/O location 
    PUSH R1     Push register on stack 
    CLR R1      Clear Register 
    count++;
    LDS R0,0x0100       Load direct from data space 
    SUBI R0,0xFF        Subtract immediate 
    STS 0x0100,R0       Store direct to data space 
    ...
    

これらのいずれも、貴重なバイト数とマイクロ秒を節約します。

これらまたは同様の最適化を何らかの方法で atmel studio ツールチェーン/ライブラリに配置して、コンパイルされたコードがわずかに良く生成されるようにする方法はありますか?
割り込みと関数呼び出しを取り巻く多くのコードと、C からアセンブリへの変換の一部は、大幅に最適化できます。

4

1 に答える 1

1

また、生成されたアセンブリ コードを最適化できることもわかりました。-Onその時までにオプションを使用していませんでした。呼び出された関数 (レジスターでパラメーターを取る) のコードが見つかりました。それをスタックにコピーし(「自動」C変数としてクリーンなコピーを保持するため...ほとんどの場合役に立たない)、さらにこの値を元のレジスタにコピーして戻します!!! このレジスタは以前に読み取られたばかりであり、GCC はそれを認識している必要があります。

GCC であるデフォルト コンパイラで Atmel Studio を使用する場合、バイナリ コードの最適化はツールチェーンの動作 (したがって、コマンド ラインで指定されたオプション) に依存します。

最高の結果を得るために、avr-gcc を直接使用してソース ツリーをコンパイルすることができます (Atmel Studio が設定できないオプションを設定するため)。

別のツールチェーンを使用することは、(理論的に) 最高の結果を得る別の方法です。とにかく、他のツールチェーンが GCC よりも (全体的に) 良い結果をもたらすとは思えません。

于 2016-01-14T21:31:03.450 に答える