Т.е. есть маленькая программа, хотелось одну переменную поместить в регистр для ускорения доступа, причем изменение переменной возможно в прерывании. Если бы писал на асме, то просто разместил бы переменную в регистре по своему усмотрению и использовал бы всегда значение этого регистра, однако с WinAVR такой трюк не прошел

Поясню:
1) Пишу: volatile unsigned char Timer;
Результат: переменная размещена в ОЗУ (@ 0x0078), считывается каждый раз. Все логично.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
LDS R24,0x0078 // в цикле
CP R25,R24 // в цикле
BRCC PC+0x03 // в цикле
LDS R25,0x0078 // в цикле
CP R25,R24 // в цикле
BRCC PC+0x03 // в цикле
LDS R25,0x0078 // в цикле
2) Пишу: register unsigned char Timer asm("r15");
Результат: переменная размещена в регистре R15, но считывание оптимизировано. Тоже логично - компилятор "не знает", что она может менятся в прерывании.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
MOV R19,R15 // за циклом
...
CP R25,R19 // в цикле
BRCC PC+0x02 // в цикле
MOV R25,R19 // в цикле
...
...
CP R25,R19 // в цикле
BRCC PC+0x02 // в цикле
MOV R25,R19 // в цикле
...
3) Пишу оба модификатора: volatile register unsigned char Timer asm("r15");
Результат: практически тот же, что и в п.2. Компилятор "частично помнит" что переменная volatile и при копировании использует значение регистра R15, однако при сравнении в цикле все равно использует копию R15 в R19. В результате программа не работает как ожидалось.
Дизасм:
if (Timer > max) max = Timer; // внутри цикла
Код
MOV R19,R15 // за циклом
...
CP R25,R19 // в цикле
BRCC PC+0x02 // в цикле
MOV R25,R15 // в цикле
...
...
CP R25,R19 // в цикле
BRCC PC+0x02 // в цикле
MOV R25,R15 // в цикле
...
В результате пришлось использовать вариант 1. Расходы на чтение/запись ОЗУ в принципе небольшие - 1 команда LDS. Однако в цикле уже ощутимо, да и все же хочется иметь возможность "управлять" действиями компилятора.