Цитата(kv_addr @ Aug 27 2011, 20:15)

В пункте Register Utilization я могу зарезервировать от одного (R15) до 12 (R4...R15) операционных регистров под глобальные переменные. Поскольку работать с переменными, расположенными в регистрах, можно быстрее, чем с переменными расположенными в ячейках ОЗУ, в критичных по времени функциях пытаюсь использовать такую возможность, что в моем случае вполне оправдано. Но компилятор генерирует не совсем оптимальный код, пример которого привел выше.
Резервирование это одно, а компиляция через инструкцию IN - другое. Резервирование означает только то, что компилятору запрещается использовать эти регистры при генерации C-кода (причем за библиотеки компилятор отвественности не несет, т.к. получает их уже скомпилированными). Нечего кроме этого операция резервирование не означает. Т.е. только от этого память не станет регистром, а регистр не станет памятью.
С точки зрения компилятора
регистр отличается от памяти способом адресации. Хотя с точки зрения электронщика это может быть одно и тоже

. В отношении регистра компилятор использует команды IN и OUT, тогда как к памяти обращается по ее адресу. В этом и состоит это отличие.
Регистры объявлены в хидере с помощью определения SFR_B или ему подобных, описанных в iomacro.h. Эти определения сильно компиляторозависимые, а потому не стоит повторять те приемы, которыми они там определятся как регистры, хотя самим SFR_B пользоваться вполне можно. Например так:
SFR_B(Old_PINB, 14)
SFR_B(New_PINB, 15)
Но лучше, все-таки так не делать, а найти в хидере уже определенные имена регистров из области 14-го и 15-го байта. Там должно быть что-то вроде этого:
SFR_B(?????, 0xE)
SFR_B(?????, 0xF)
Вот с этими именами, которые у меня записаны, как "?????", и нужно определить тождество через #define и тогда такие клоны тоже будут использоваться компилятором, как регистры.
Попытки же использовать зарезервированное среди регистров место по адресу (@14 или @15) приводит лишь к тому, что это место используется, как память. Т.е. обращение к нему будет происходить по адресам 14 или 15, а не регистровыми опрациями IN/OUT.
Цитата(kv_addr @ Aug 27 2011, 20:15)

Объясните, пожалуйста, если я хочу старое и новое значения байтов, полученных из порта PINB, хранить именно в РОН и дальше в функции работать именно с данными в этих регистрах (естественно, учитывая ограничения для нижних 16 РОН у AVR), то чем Ваши вышеуказанные дефайны могут мне помочь?
Дефайны помогают тем, что отожествляют ваши имена Old_PINB и New_PINB с именами регистров, а не с памятью. А это позволяет обращаться к ним, как к регистрам, используя команды IN/OUT. А ваше определение этих имен, как переменных, с указанными для них адресами (@14 или @15), является определением для ячеек памяти. По этой причине компилятор в их отношении команды IN/OUT не использует.
Я понимаю, что вы хотели бы, чтобы компилятор сам догадался, что по адресам 14 и 15 находятся регистры. Однако догадаться об этом он не может. Причина в том, что эти адреса считаются от начала
сегмента кода! А где начинается сегмент кода знает только линкер, а компилятор этого не знает и знать не должен. Поэтому в данном случае вина лежит целиком на вашем корявом программировании, а не на компиляторе замечательной фирмы IAR.
Цитата(kv_addr @ Aug 27 2011, 20:15)

У меня Old_PINB и New_PINB являются однобайтовыми глобальными переменными, расположенными в регистрах R14 и R15 соответственно, а отнюдь не регистры портов PORTE и PORTF.
А в моем AT90USB647 по адресам 14 и 15 находятся именно регистры PORTE и PORTF! Вы ведь поленились назвать тип вашего МК? А раз так, то не имеете права выставлять мне претензий за то, что я ваши 14-ю и 15-ю ячейки неправильно отнесла. Телепатическими способностями в отношении вас я не обладаю, поэтому в своем прошлом ответе ограничилась вежливой формулировкой "имена регистров ищите в хидере, соответствующему вашему типу МК". Почему бы вам и в самом деле не посмотреть, как называются у вашего МК регистры, находящиеся в 14-ом и 15-ом байтах?