Arduino, why C code and problem, for-loop


short URL https://goo.gl/xVY56d

problem & observation https://xiaolaba.wordpress.com/2015/05/27/arduino-c-code-and-problem-for-loop-do-while-loop/

further to test, C code

結論是, ATMEGA2560 (或所有 AVR 8 bit MCU CORE),

1) 沒有 8 bit 常數加法指令 ADD, 只有16 bit 的 adwi, 所以這GCC編譯器加法執行用減法指令 subi, 例如 +1 = -(-1) = -(0xff)

2) 只有用 brne 指令, 所以 “小於或等於" 或 “不大於" 並沒有使用對應指令, <= 無法執行, 除非比較 n+1, 因此 <=0xfe, 編碼試驗 <= (0xfe+1), 實際與 0xff 比較, 無法用 8 bit counter 配合 for-loop 達成 0 至 255 的計數 (256), 需要改用16 bit counter 或棄用 for-loop, 改用 do-while-loop, 並且 i++ 與 ++i 並沒有分別, 實際編碼都是先加值, 再比較. 所以用 asm 編寫 8 bit for-loop, 與C編譯器生成的編碼嚴重分歧. 也解釋了C程序跑飛的實際原因. 到底有甚麼法方法呢 ? 還是 GCC 配 AVR8 就只能這樣 ?

/*
test routine to understand what is the for-loop and code generation
2015-05-28 xiaolaba
AVR8
arduino 0022. GCC version ?
 */

void setup() {
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  //pinMode(13, OUTPUT);     
}

void loop() {
/*
//C code, works fine
byte i =0;

do {
    i++;
    __asm ("nop");
    __asm ("pop r21");
  }   while (i != 10) ;

//C code, works fine
i =0;

do {
    i++;
    __asm ("nop");
    __asm ("pop r23");
  }   while (i != 0) ;

    __asm ("nop");

i =0;

do {
    i++;
    __asm ("nop");
    __asm ("pop r23");
  }   while (i != 0); 

//C code, works fine
    for (int i = 0; i < 512; i += 2) {     // OK
    __asm ("nop");
    __asm ("pop r24");
    }

*/

 //C code, not working but why !!!
  for (byte i = 0; i < 0xff; i++) {
    __asm ("nop");
    __asm ("pop r25");
  }

  for (byte i = 0; i <= 0xfe; ++i) {
    __asm ("nop");
    __asm ("pop r26");
  }

  for (byte i = 0; i <= 0x10; ++i) {
    __asm ("nop");
    __asm ("pop r27");
  }   

  for (byte i = 0; i != 0xff ; ++i) {
    __asm ("nop");
    __asm ("pop r28");
  }

}

this ASM code, generated for such loop test

0000012e <loop>:
 12e:	80 e0       	ldi	r24, 0x00	; 0
 130:	00 00       	nop
 132:	9f 91       	pop	r25
 134:	8f 5f       	subi	r24, 0xFF	; 255
 136:	8f 3f       	cpi	r24, 0xFF	; 255
 138:	d9 f7       	brne	.-10     	; 0x130 <loop+0x2>

 13a:	80 e0       	ldi	r24, 0x00	; 0
 13c:	00 00       	nop
 13e:	af 91       	pop	r26
 140:	8f 5f       	subi	r24, 0xFF	; 255
 142:	8f 3f       	cpi	r24, 0xFF	; 255
 144:	d9 f7       	brne	.-10     	; 0x13c <loop+0xe>

 146:	80 e0       	ldi	r24, 0x00	; 0
 148:	00 00       	nop
 14a:	bf 91       	pop	r27
 14c:	8f 5f       	subi	r24, 0xFF	; 255
 14e:	81 31       	cpi	r24, 0x11	; 17
 150:	d9 f7       	brne	.-10     	; 0x148 <loop+0x1a>

 152:	80 e0       	ldi	r24, 0x00	; 0
 154:	00 00       	nop
 156:	cf 91       	pop	r28
 158:	8f 5f       	subi	r24, 0xFF	; 255
 15a:	8f 3f       	cpi	r24, 0xFF	; 255
 15c:	d9 f7       	brne	.-10     	; 0x154 <loop+0x26>

 15e:	08 95       	ret


rem This is asm.bat, uses avr-objdump to obtian assembler listing
rem change buildxxxxxxxxxxxxxx.tmp, every time arduino IDE has a different path
rem change xxxx.xxx.xxxx.elf, every project has own project name
 

set build=build7733546659278691547.tmp

set elf_file=loop_test.cpp.elf

set input=C:\DOCUME~1\user\LOCALS~1\Temp\%build%\%elf_file%

set output=%elf_file%.txt

avr-objdump -d %input% > %output%
廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s