25.04.2013, 16:54
|
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
GCC: Как избежать избыточного пользования стеком в прерываниях
К примеру имеется прерывание:
Код:
|
ISR (INT0_vect)
{
uint8_t temp;
temp=PORTB;
OnSound (temp);
} |
avr-gcc 4.7.1. кодит его как:
Код:
|
ISR (INT0_vect)
{
23e: 1f 92 push r1
240: 0f 92 push r0
242: 0f b6 in r0, 0x3f ; 63
244: 0f 92 push r0
246: 11 24 eor r1, r1
248: 3f 93 push r19
24a: 4f 93 push r20
24c: 5f 93 push r21
24e: 6f 93 push r22
250: 7f 93 push r23
252: 8f 93 push r24
254: 9f 93 push r25
256: af 93 push r26
258: bf 93 push r27
25a: ef 93 push r30
25c: ff 93 push r31
uint8_t temp;
temp=PORTB;
25e: 88 b3 in r24, 0x18 ; 24
OnSound (temp);
260: e4 df rcall .-56 ; 0x22a ‹OnSound›
}
262: ff 91 pop r31
264: ef 91 pop r30
266: bf 91 pop r27
268: af 91 pop r26
26a: 9f 91 pop r25
26c: 8f 91 pop r24
26e: 7f 91 pop r23
270: 6f 91 pop r22
272: 5f 91 pop r21
274: 4f 91 pop r20
276: 3f 91 pop r19
278: 0f 90 pop r0
27a: 0f be out 0x3f, r0 ; 63
27c: 0f 90 pop r0
27e: 1f 90 pop r1
280: 18 95 reti |
собственно понятно, созранение всех задействованных регистров - перестраховка на случай если расстерянный программист в процедуре внутри прерывания изменит содержимое всех регистров. Если прерывание простое можно добавить аттрибут: "__attribute__((__naked__))" и iret и нет проблем.
А как сделать так чтобы компилятор сохранял только задействованные в конретном прерывании регистры ?
|
|
|
|
25.04.2013, 17:29
|
|
Заблокирован
Регистрация: 27.03.2007
Сообщений: 1,328
Сказал спасибо: 12
Сказали Спасибо 576 раз(а) в 460 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от MaxiMuz79
|
созранение всех задействованных регистров - перестраховка на случай если расстерянный программист
|
Ну, какая же перестраховка ? А какие регистры изменяет функция OnSound()? И в самой этой функции тоже, небось, есть вызовы других функций? Ведь после выполнения этой OnSound() программа опять вернётся в прерывание, и придётся всё восстанавливать.
Если функция простая, то лучше вместо её вызова написать само тело в прерывании. Тогда, может, компилятору будет легче разобраться - какие регистры нужно сохранять ...
А если вызов может быть отложен, то вообще не вызывать функцию в прерывании, а поднять флаг. И в основной программе, после проверки флага - вызвать эту функцию.
Последний раз редактировалось Yurkin2007; 25.04.2013 в 17:37.
|
|
|
|
25.04.2013, 17:33
|
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от Yurkin2007
|
А какие регистры изменяет функция OnSound()? И в самой этой функции тоже, небось, есть вызовы других функций? Ведь после выполнения этой функции программа опять вернётся в прерывание, и придётся всё восстанавливать.
|
пробывал вставлял пустую команду "nop" в функцию OnSound(), все равно пол регистрового файла в стек !
|
|
|
|
25.04.2013, 17:40
|
|
Заблокирован
Регистрация: 27.03.2007
Сообщений: 1,328
Сказал спасибо: 12
Сказали Спасибо 576 раз(а) в 460 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от MaxiMuz79
|
пробывал вставлял пустую команду "nop" в функцию OnSound(), все равно пол регистрового файла в стек !
|
Видимо компилятор не настолько продвинутый и в данный момент просто не видит, что внутри функции OnSound(). И на всякий случай перестраховывается ...
Напишите nop вместо функции, в самом прерывании.
Последний раз редактировалось Yurkin2007; 25.04.2013 в 17:43.
|
|
|
|
25.04.2013, 17:46
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от MaxiMuz79
|
пробывал вставлял пустую команду "nop" в функцию OnSound(), все равно пол регистрового файла в стек !
|
А убрать вызов самой функции их хендлера пробовал? Какой при этом результат? Сделать хендлер из одного нопа.
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
25.04.2013, 17:52
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от Yurkin2007
|
Видимо компилятор не настолько продвинутый и в данный момент просто не видит, что внутри функции OnSound(). И на всякий случай перестраховывается ...
Напишите nop вместо функции, в самом прерывании.
|
Кстати, я никогда не задумывался, с какого такого лешего он прячет только регистры прямого обращения. Регистры косвенного обращения его в данном примере не озаботили. Пачиму? Что-то в этом есть, в смысле виден подход компилятора..
А насчет вызова из обработчика - наверное это трудно (невозможно) в ограниченное к-во проходов компилятора пройти все прямые и вложенные функции. Отсюда и прячет гамузом все. А косвенные регистры его не заботят. Разработчик компилятора знает, что потеря их значений урона не принесет. Может так?
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
25.04.2013, 18:00
|
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от Yurkin2007
|
Видимо компилятор не настолько продвинутый и в данный момент просто не видит, что внутри функции OnSound(). И на всякий случай перестраховывается ...
Напишите nop вместо функции, в самом прерывании.
|
видимо если бы имело смысл просто поставить nop или чтото еще вместо функции я бы так и сделал! но размер свободной памяти не позволяет этого, да и в самой функции есть еще один вызов ...
Вместо вызова функции пробывал встатвить оператор goto на тот участок где выполняется нужная последовательность команд (уже сохраненные регистры не нужны), но компил. на метке куда совершается пререход выдал ошибку:
Код:
|
error: label 'm1' used but not defined |
|
|
|
|
25.04.2013, 18:29
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от MaxiMuz79
|
видимо если бы имело смысл просто поставить nop или чтото еще вместо функции я бы так и сделал! но размер свободной памяти не позволяет этого, да и в самой функции есть еще один вызов ...
Вместо вызова функции пробывал встатвить оператор goto на тот участок где выполняется нужная последовательность команд (уже сохраненные регистры не нужны), но компил. на метке куда совершается пререход выдал ошибку:
Код:
|
error: label 'm1' used but not defined |
|
Дык мы ведь не в качестве решения в проект предлагаем. Просто посмотреть после компиляции, что хендлер со стеком сделает, что в него спрячет. Я давно не пишу под АВР, просто интересно стало.
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
25.04.2013, 18:49
|
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от ut1wpr
|
Кстати, я никогда не задумывался, с какого такого лешего он прячет только регистры прямого обращения. Регистры косвенного обращения его в данном примере не озаботили. Пачиму? Что-то в этом есть, в смысле виден подход компилятора..
|
* Call-used registers (r18-r27, r30-r31):
May be allocated by gcc for local data. You may use them freely in assembler subroutines. Calling C subroutines can clobber any of them - the caller is responsible for saving and restoring.
* Call-saved registers (r2-r17, r28-r29):
May be allocated by gcc for local data. Calling C subroutines leaves them unchanged. Assembler subroutines are responsible for saving and restoring these registers, if changed. r29:r28 (Y pointer) is used as a frame pointer (points to local data on stack) if necessary. The requirement for the callee to save/preserve the contents of these registers even applies in situations where the compiler assigns them for argument passing.
я так понимаю любая подпрограмма по умолчанию может их изменить, а r2-r17 - сохраняются только в случае их задействования при передачи параметров для ф-ий.
Если нет вызова ф-ий то сохраняет только задействованные рег-ы
|
|
|
|
25.04.2013, 20:49
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: GCC: Как избежать избыточного пользования стеком в прерываниях
Сообщение от MaxiMuz79
|
* Call-used registers (r18-r27, r30-r31):
May be allocated by gcc for local data. You may use them freely in assembler subroutines. Calling C subroutines can clobber any of them - the caller is responsible for saving and restoring.
* Call-saved registers (r2-r17, r28-r29):
May be allocated by gcc for local data. Calling C subroutines leaves them unchanged. Assembler subroutines are responsible for saving and restoring these registers, if changed. r29:r28 (Y pointer) is used as a frame pointer (points to local data on stack) if necessary. The requirement for the callee to save/preserve the contents of these registers even applies in situations where the compiler assigns them for argument passing.
я так понимаю любая подпрограмма по умолчанию может их изменить, а r2-r17 - сохраняются только в случае их задействования при передачи параметров для ф-ий.
Если нет вызова ф-ий то сохраняет только задействованные рег-ы
|
Я работаю только с ИАР.
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 02:01.
|
|