Почему так велик размер кода пустой программы (комп.WinAVR)?
-
vchik
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Ср фев 13, 2008 04:31:23
- Откуда: Москва
- Контактная информация:
Почему так велик размер кода пустой программы (комп.WinAVR)?
Вот, наигравшись вдоволь с мигающими светодиодами и нажмающимися лапой кнопками на асемблере, решил попробовать запрогать что-нибудь на Си
Начитавшись всяких ссылок, ФАКов и справочников, для прогания на Си выбрал пакет WinAVR.
Пишу все в AVRStudio 4
Написал пустую программку в одну строку:
int main (void) { }
Компилируем, Билд, Запуск, Дизассемблируем и видим огромный набор инструкций как до функции мейн так и после нее. Итого hex-файл составляет 300 байт при пустой программе.
это строка на компиляцию
avr-gcc.exe -I"D:\AVR\Projects\My_C_prj\..\..\..\Program Files\WinAVR-20071221\avr\include\avr" -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -Os -fsigned-char -MD -MP -MT My_C_prj.o -MF dep/My_C_prj.o.d -c -mcall-prologues -mno-tablejump ../My_C_prj.c
Где почитать или разобратся как, почему и что запихивает GCC в пустую программу и какой от этого толк.
В начале там знакомые инструкции вроде объявления векторов прерываний, а все остальное какието беспорядочные ldi и out в различные регистры
скриншоты прилагаютса - все три скрина - куски одной программы
Начитавшись всяких ссылок, ФАКов и справочников, для прогания на Си выбрал пакет WinAVR.
Пишу все в AVRStudio 4
Написал пустую программку в одну строку:
int main (void) { }
Компилируем, Билд, Запуск, Дизассемблируем и видим огромный набор инструкций как до функции мейн так и после нее. Итого hex-файл составляет 300 байт при пустой программе.
это строка на компиляцию
avr-gcc.exe -I"D:\AVR\Projects\My_C_prj\..\..\..\Program Files\WinAVR-20071221\avr\include\avr" -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -Os -fsigned-char -MD -MP -MT My_C_prj.o -MF dep/My_C_prj.o.d -c -mcall-prologues -mno-tablejump ../My_C_prj.c
Где почитать или разобратся как, почему и что запихивает GCC в пустую программу и какой от этого толк.
В начале там знакомые инструкции вроде объявления векторов прерываний, а все остальное какието беспорядочные ldi и out в различные регистры
скриншоты прилагаютса - все три скрина - куски одной программы
- Вложения
-
- Clipboard02.png
- часть 1
- (5.37 КБ) 618 скачиваний
-
- Clipboard05.png
- часть 2
- (6.86 КБ) 595 скачиваний
-
- Clipboard07.png
- часть 3
- (3.23 КБ) 630 скачиваний
у меня WinAVR генерирует всего 93 байта...
причина этого проста: компилятор генерирует "пролог" в начале любой программы: очищает память, устанавливает стек и т.п. (если надо), эта часть - неизбежное следствие применения Си. еще добавляется вызов пустой функции main, которая состоит из команды возврата, плюс пустой бесконечный цикл в конце всего. плюс, как было сказано, векторы прерываний...
причина этого проста: компилятор генерирует "пролог" в начале любой программы: очищает память, устанавливает стек и т.п. (если надо), эта часть - неизбежное следствие применения Си. еще добавляется вызов пустой функции main, которая состоит из команды возврата, плюс пустой бесконечный цикл в конце всего. плюс, как было сказано, векторы прерываний...
Покуда есть на свете дураки...удачу мы не выпустим из рук.
не путай формат файла прошивки HEX и собственно содержимое памяти... HEX - это ТЕКСТОВЫЙ файл, удобный для просмотра человеком, а при прошивке он преобразуется в реальные двоичные байты, которые и пишутся во флешь... вот и получается, что HEX огромный, а реально там данных для 30% памяти...
Покуда есть на свете дураки...удачу мы не выпустим из рук.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
заставь свой компилятор выдать bin-файл - это и будет в чистом виде то, что нужно микроконтроллеру. hex-это ТЕКСТОВОЕ ПРЕДСТАВЛЕНИЕ того, что надо, причем с некоторыми дополнительными фичами. если интересуешься - у меня на сайте есть описание формата Intel-HEX на русском языке.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
vchik
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Ср фев 13, 2008 04:31:23
- Откуда: Москва
- Контактная информация:
Оу хоу! Фишка расшарена! Добавил в мейкфайл создание бинарника *.bin получилось 98 байт.
Итого, как сказал уважаемый тов. Кот Базилио, эти 98 байт составили инициализация прерываний, загрузка стека и еще какие-то пока мне не очень ясные операции с регистрами.
Вот насчет операций интересно бы разобраться:
Итого, как сказал уважаемый тов. Кот Базилио, эти 98 байт составили инициализация прерываний, загрузка стека и еще какие-то пока мне не очень ясные операции с регистрами.
Вот насчет операций интересно бы разобраться:
-
vchik
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Ср фев 13, 2008 04:31:23
- Откуда: Москва
- Контактная информация:
вот что удалось выяснить, c 0x17 инструкции начинаютися странные вещи
// ====
объявление прерываний, прыгаем вперед по первому (RESET) на 0x11-ую инструкцию, по остальным на 0x2C
+00000000: RJMP PC+0x0011
+00000001: RJMP PC+0x002B
+00000002: RJMP PC+0x002A
+00000003: RJMP PC+0x0029
+00000004: RJMP PC+0x0028
+00000005: RJMP PC+0x0027
+00000006: RJMP PC+0x0026
+00000007: RJMP PC+0x0025
+00000008: RJMP PC+0x0024
+00000009: RJMP PC+0x0023
+0000000A: RJMP PC+0x0022
+0000000B: RJMP PC+0x0021
+0000000C: RJMP PC+0x0020
+0000000D: RJMP PC+0x001F
+0000000E: RJMP PC+0x001E
+0000000F: RJMP PC+0x001D
+00000010: RJMP PC+0x001C
// =======
Начало предустановок
// Очистили SREG
+00000011: CLR R1
+00000012: OUT 0x3F,R1
// Инициализировали стек
+00000013: LDI R28,0x5F
+00000014: LDI R29,0x02
+00000015: OUT 0x3E,R29
+00000016: OUT 0x3D,R28
// ????? Загрузили странные числа
+00000017: LDI R17,0x00
+00000018: LDI R26,0x60
+00000019: LDI R27,0x00
+0000001A: LDI R30,0x62
+0000001B: LDI R31,0x00
// перешли к 0x1F
+0000001C: RJMP PC+0x0003
// какие-то махинации
+0000001D: LPM R0,Z+
+0000001E: ST X+,R0
// ????? Проверили а точно ли в R26 лежит 0x60 после команды LDI? =)
+0000001F: CPI R26,0x60
// ??? А точно ли 0 = 0? =)
+00000020: CPC R27,R17
// И если 0 не равен 0 то прыгнули на 0x1D
+00000021: BRNE PC-0x04
// Снова загружаем в регистры те же значения
+00000022: LDI R17,0x00
+00000023: LDI R26,0x60
+00000024: LDI R27,0x00
// Прыг на 0x27
+00000025: RJMP PC+0x0002
+00000026: ST X+,R1
// Опять проверки а равен ли ноль нулю
+00000027: CPI R26,0x60
+00000028: CPC R27,R17
+00000029: BRNE PC-0x03
// Вызов мейн
+0000002A: RCALL PC+0x0003
// Переход к концу
+0000002B: RJMP PC+0x0005
// Дефолтовый обработчик прерываний - вернутся назад
+0000002C: RJMP PC-0x002C
// main();
@0000002D: main
// Зачем-то обнулили регистры
+0000002D: LDI R24,0x00
+0000002E: LDI R25,0x00
// Конец мейн
+0000002F: RET
// Конец программы - бесконечный цикл
+00000030: RJMP PC-0x0000
// ===================
Мораль - а что это за махинации с регистрами там типа проверки записалось ли в них что-то или нет?
Выкладывайте длинные коды нормально - во вложении. Паятель.
// ====
объявление прерываний, прыгаем вперед по первому (RESET) на 0x11-ую инструкцию, по остальным на 0x2C
+00000000: RJMP PC+0x0011
+00000001: RJMP PC+0x002B
+00000002: RJMP PC+0x002A
+00000003: RJMP PC+0x0029
+00000004: RJMP PC+0x0028
+00000005: RJMP PC+0x0027
+00000006: RJMP PC+0x0026
+00000007: RJMP PC+0x0025
+00000008: RJMP PC+0x0024
+00000009: RJMP PC+0x0023
+0000000A: RJMP PC+0x0022
+0000000B: RJMP PC+0x0021
+0000000C: RJMP PC+0x0020
+0000000D: RJMP PC+0x001F
+0000000E: RJMP PC+0x001E
+0000000F: RJMP PC+0x001D
+00000010: RJMP PC+0x001C
// =======
Начало предустановок
// Очистили SREG
+00000011: CLR R1
+00000012: OUT 0x3F,R1
// Инициализировали стек
+00000013: LDI R28,0x5F
+00000014: LDI R29,0x02
+00000015: OUT 0x3E,R29
+00000016: OUT 0x3D,R28
// ????? Загрузили странные числа
+00000017: LDI R17,0x00
+00000018: LDI R26,0x60
+00000019: LDI R27,0x00
+0000001A: LDI R30,0x62
+0000001B: LDI R31,0x00
// перешли к 0x1F
+0000001C: RJMP PC+0x0003
// какие-то махинации
+0000001D: LPM R0,Z+
+0000001E: ST X+,R0
// ????? Проверили а точно ли в R26 лежит 0x60 после команды LDI? =)
+0000001F: CPI R26,0x60
// ??? А точно ли 0 = 0? =)
+00000020: CPC R27,R17
// И если 0 не равен 0 то прыгнули на 0x1D
+00000021: BRNE PC-0x04
// Снова загружаем в регистры те же значения
+00000022: LDI R17,0x00
+00000023: LDI R26,0x60
+00000024: LDI R27,0x00
// Прыг на 0x27
+00000025: RJMP PC+0x0002
+00000026: ST X+,R1
// Опять проверки а равен ли ноль нулю
+00000027: CPI R26,0x60
+00000028: CPC R27,R17
+00000029: BRNE PC-0x03
// Вызов мейн
+0000002A: RCALL PC+0x0003
// Переход к концу
+0000002B: RJMP PC+0x0005
// Дефолтовый обработчик прерываний - вернутся назад
+0000002C: RJMP PC-0x002C
// main();
@0000002D: main
// Зачем-то обнулили регистры
+0000002D: LDI R24,0x00
+0000002E: LDI R25,0x00
// Конец мейн
+0000002F: RET
// Конец программы - бесконечный цикл
+00000030: RJMP PC-0x0000
// ===================
Мораль - а что это за махинации с регистрами там типа проверки записалось ли в них что-то или нет?
Выкладывайте длинные коды нормально - во вложении. Паятель.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
не вижу смысла в подобном ковырянии. хотите разработать оптимальную простую программу? используйте ассемблер:
будет всего 2 байта. хотите просто работать с Си - работайте, и простите компилятору от 5 до 15% лишнего кода. Может, и больше чем 15% - но простите все равно.
Код: Выделить всё
org 0
rjmp PC
будет всего 2 байта. хотите просто работать с Си - работайте, и простите компилятору от 5 до 15% лишнего кода. Может, и больше чем 15% - но простите все равно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
он готовит плацдарм для последующих реально нужных ему (компилятору) дел. но, так как никаких дел вы ему не поручаете, эта подготовка пропадает напрасно.vchik писал(а):Интересно разобраться, зачем он делает эти операции 0х17 по 0х29 строки.
смысл примерно такой.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
vchik
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Ср фев 13, 2008 04:31:23
- Откуда: Москва
- Контактная информация:
Ура! Написал на международном форуме по AVR-GCC ответили так:
и еще дали вот такую интересную ссылку я так понял на какой-то исходник GCC отвечающий за стартблок:
This code initialises RAM that holds initialized values and set the remaining area to zero.
The code isn't weird at all. It's just two for loops. The termination check is done first before the first iteration through the body, but usually compilers place the loop termination check at the end, so on entry a jump over the body is needed.
The checkings are so see if it has copied enough. Addresses are compared. CPI/CPC combo's are 16 compares. Not comparing zero to zero
и еще дали вот такую интересную ссылку я так понял на какой-то исходник GCC отвечающий за стартблок:
libgcc.S source-
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/avr/libgcc.S?rev=1.14.102.1&content-type=text/x-cvsweb-markup
look toward the bottom for '__do_copy_data' (the already created library- libgcc.a -is what the compiler uses)
If you have an avr >64k, then libc takes care of it with gcrt1.S (crt*.o precompiled for you).
-
vchik
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Ср фев 13, 2008 04:31:23
- Откуда: Москва
- Контактная информация:
Brutaller писал(а):vchik, сколько времени с ассемблером успел поработать, что он так быстро надоел?
Семестр прогали лабы в инсте на ассемблере процессоров i8080 и i8086
Семестр девушке помогал с курсом по AVR-микроконтроллерам, после этого курса мне понравилась тема про микроконтроллеры и я начал испытывать на практике.
Но все же на асме писать трудновато, вместо привычных циклов строить конструкции c brne и метками, структура пропадает, это как использовать goto в С++ прогах - в конце концов становится не ясно что куда и с какой стати перемещается.
Потому сел разбираться с Си, по ходу это круто! Еслиб еще и ООП запихать можно было ваще бы было шоколадно
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
avr-gcc в последней версии поддерживает объектно-ориентированные расширения С++, однако чтобы этим нормально пользоваться, возможностей классических AVR-ов явно маловато. да и лишнее это, имхо
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- tych
- Э...
- Сообщения: 2792
- Зарегистрирован: Ср апр 04, 2007 08:39:14
- Откуда: Москва
- Контактная информация:
Re: Почему так велик размер кода пустой программы (комп.WinA
vchik писал(а):для прогания на Си выбрал пакет WinAVR.
Советую попробовать и CVAVR
Думайте сами, решайте сами ... а вот он-лайн перевод на корявый русский http://translate.ru