Вот пример:
Код
#include <avr/io.h>
class DELAY{
public:
const uint8_t Cadd;
volatile uint8_t& port;
DELAY(const uint8_t c, volatile uint8_t& p):Cadd(c), port(p)
{
if ((Cadd%3)==0) asm volatile ("nop\n\t");
if ((Cadd%3)==1) asm volatile ("nop\n\t" "nop\n\t");
if ((Cadd%3)==2) asm volatile ("nop\n\t" "nop\n\t" "nop\n\t");
port=c;
}
};
int main(void)
{
DELAY mod1(4,PORTA);
DELAY mod2(5,PORTB);
while(1);
return 0;
}
в результате:
Код
...
0000006c <_ZN5DELAYC1EhRVh>:
6c: fc 01 movw r30, r24
6e: 26 2f mov r18, r22
70: da 01 movw r26, r20
72: 60 83 st Z, r22
74: 52 83 std Z+2, r21; 0x02
76: 41 83 std Z+1, r20; 0x01
78: 86 2f mov r24, r22
7a: 63 e0 ldi r22, 0x03; 3
7c: 0e 94 66 00 call 0xcc; 0xcc <__udivmodqi4>
80: 99 23 and r25, r25
82: 11 f4 brne .+4 ; 0x88 <_ZN5DELAYC1EhRVh+0x1c>
84: 00 00 nop
86: 0a c0 rjmp .+20 ; 0x9c <_ZN5DELAYC1EhRVh+0x30>
88: 91 30 cpi r25, 0x01; 1
8a: 19 f4 brne .+6 ; 0x92 <_ZN5DELAYC1EhRVh+0x26>
8c: 00 00 nop
8e: 00 00 nop
90: 05 c0 rjmp .+10 ; 0x9c <_ZN5DELAYC1EhRVh+0x30>
92: 92 30 cpi r25, 0x02; 2
94: 19 f4 brne .+6 ; 0x9c <_ZN5DELAYC1EhRVh+0x30>
96: 00 00 nop
98: 00 00 nop
9a: 00 00 nop
9c: 2c 93 st X, r18
9e: 08 95 ret
000000a0 <main>:
a0: df 93 push r29
a2: cf 93 push r28
a4: 00 d0 rcall .+0 ; 0xa6 <main+0x6>
a6: 00 d0 rcall .+0 ; 0xa8 <main+0x8>
a8: 00 d0 rcall .+0 ; 0xaa <main+0xa>
aa: cd b7 in r28, 0x3d; 61
ac: de b7 in r29, 0x3e; 62
ae: ce 01 movw r24, r28
b0: 01 96 adiw r24, 0x01; 1
b2: 64 e0 ldi r22, 0x04; 4
b4: 4b e3 ldi r20, 0x3B; 59
b6: 50 e0 ldi r21, 0x00; 0
b8: 0e 94 36 00 call 0x6c; 0x6c <_ZN5DELAYC1EhRVh>
bc: ce 01 movw r24, r28
be: 04 96 adiw r24, 0x04; 4
c0: 65 e0 ldi r22, 0x05; 5
c2: 48 e3 ldi r20, 0x38; 56
c4: 50 e0 ldi r21, 0x00; 0
c6: 0e 94 36 00 call 0x6c; 0x6c <_ZN5DELAYC1EhRVh>
ca: ff cf rjmp .-2 ; 0xca <main+0x2a>
000000cc <__udivmodqi4>:
cc: 99 1b sub r25, r25
ce: 79 e0 ldi r23, 0x09; 9
d0: 04 c0 rjmp .+8 ; 0xda <__udivmodqi4_ep>
000000d2 <__udivmodqi4_loop>:
d2: 99 1f adc r25, r25
d4: 96 17 cp r25, r22
d6: 08 f0 brcs .+2 ; 0xda <__udivmodqi4_ep>
d8: 96 1b sub r25, r22
000000da <__udivmodqi4_ep>:
da: 88 1f adc r24, r24
dc: 7a 95 dec r23
de: c9 f7 brne .-14 ; 0xd2 <__udivmodqi4_loop>
e0: 80 95 com r24
e2: 08 95 ret
...
наблюдаем генерацию кода, вычисляющего константное выражение(==делающего работу препроцессора), а также обращение к регистру ввода-вывода посредством косвенной адресации, а не спец-команд.
Второе, помимо неоправданного увеличения размера кода, приводит к ошибкам компиляции, если в ассемблерных вставках использовать результаты вычисления подобных константных выражений.
Но, если в исходном коде закомментировать объявление одного из объектов класса DELAY, или один из if() в конструкторе класса DELAY, то генерится вполне нормальный код:
Код
#include <avr/io.h>
class DELAY{
public:
const uint8_t Cadd;
volatile uint8_t& port;
DELAY(const uint8_t c, volatile uint8_t& p):Cadd(c), port(p)
{
// if ((Cadd%3)==0) asm volatile ("nop\n\t");
if ((Cadd%3)==1) asm volatile ("nop\n\t" "nop\n\t");
if ((Cadd%3)==2) asm volatile ("nop\n\t" "nop\n\t" "nop\n\t");
port=c;
}
};
int main(void)
{
DELAY mod1(4,PORTA);
DELAY mod2(5,PORTB);
while(1);
return 0;
}
-----------------------------------------------------------------------------------------
...
00000068 <__bad_interrupt>:
68: 0c 94 00 00 jmp 0; 0x0 <__vectors>
0000006c <main>:
6c: 00 00 nop
6e: 00 00 nop
70: 84 e0 ldi r24, 0x04; 4
72: 8b bb out 0x1b, r24; 27
74: 00 00 nop
76: 00 00 nop
78: 00 00 nop
7a: 85 e0 ldi r24, 0x05; 5
7c: 88 bb out 0x18, r24; 24
7e: ff cf rjmp .-2 ; 0x7e <main+0x12>
00000080 <_exit>:
80: f8 94 cli
...
Не пойму, что в первом варианте кода помешало все вычислить препроцессору? Ведь все константы известны изначально. И почему компилятор перестал использовать команды для работы с регистрами ввода-вывода IN,OUT и др.?