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

具体来说,为什么第二条指令从 R25 中减去 0xFF 而不是INC R25

4

2 回答 2

5

tl;dr编译器旨在在这里使用更便携、更高效和更通用的解决方案。

用于后续指令的SUBI指令集C(进位)和(半进位)CPU 标志(在 8 位 AVR BTW 中没有,所以要添加我们从中减去的立即值),而没有。由于&都有 2 个字节的长度并在 1 个时钟周期内执行,因此使用- OTOH 不会丢失任何内容,如果使用 8 位大小的计数器,则可以轻松检测它是否已翻转(通过/ ),并且如果您有一个 16 位或 32 位大小的计数器,它允许您以非常简单的方式递增它 - 只需,将增加到,因此您必须检查最低字节是否在ing之前. OTOH,与HADDIx-xINCSUBIINCSUBIBRCCBRCSINC0x00FF0x00000xFFINCSUBI您只是SUBI -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 回答
5

SUBI 指令可用于在 8 位值中添加/减去任何 8 位常量。它的成本与 INC 相同,即指令大小和执行时间。所以编译器首选SUBI,因为它更通用。没有相应的 ADDI 指令,可能是因为它是多余的。

于 2009-08-27T05:53:49.800 回答