6

これは、私が取り組んでいる C プロジェクトから逆アセンブルされた AVR コードのスニペットです。この奇妙なコードが生成されていることに気付きましたが、それがどのように機能するのか理解できません。私はそれがある種のばかげた最適化であると仮定しています...

説明は何ですか?

92:         ticks++;         // unsigned char ticks;
+0000009F:   91900104    LDS       R25,0x0104     Load direct from data space
+000000A1:   5F9F        SUBI      R25,0xFF       Subtract immediate
+000000A2:   93900104    STS       0x0104,R25     Store direct to data space
95:         if (ticks == 0) {
+000000A4:   2399        TST       R25            Test for Zero or Minus
+000000A5:   F009        BREQ      PC+0x02        Branch if equal
+000000A6:   C067        RJMP      PC+0x0068      Relative jump

具体的には、2 番目の命令が R25 から 0xFF だけではなく 0xFF を減算するのはなぜINC R25ですか?

4

2 に答える 2

5

SUBI 命令は、任意の 8 ビット定数を 8 ビット値に加算/減算するために使用できます。コストは INC と同じです。つまり、命令サイズと実行時間です。そのため、SUBI はより一般的であるため、コンパイラによって優先されます。おそらく冗長になるため、対応する ADDI 命令はありません。

于 2009-08-27T05:53:49.800 に答える
5

tl;drコンパイラは、ここでより移植性が高く、効率的で一般的なソリューションを使用するように設計されています。

SUBI命令は、後続の命令で使用するためのC(キャリー) およびH(ハーフキャリー) CPU フラグを設定します ( ADDI8 ビット AVR BTW には存在しないため、即値を加算してx減算-xします)、そうではありINCません。SUBI&は両方ともINC2 バイトの長さを持ち、1 クロック サイクルで実行されるため、-OTOH を使用しても何も失うことはありませSUBIん。 16 ビットまたは 32 ビット サイズのカウンターがある場合は、非常に簡単な方法でインクリメントできます。. OTOHとBRCCBRCSINC0x00FF0x00000xFFINCSUBISUBI -1最下位バイトだけADC 0を処理し、次のバイトを処理して、すべての潜在的なキャリー ビットが確実に考慮されるようにします。

参考文献:

https://lists.gnu.org/archive/html/avr-gcc-list/2008-11/msg00029.html

http://avr-gcc-list.nongnu.narkive.com/SMMzdBkW/foo-subi-vs-inc

于 2009-08-26T22:27:25.970 に答える