Страница 1 из 2

Почему так велик размер кода пустой программы (комп.WinAVR)?

Добавлено: Ср фев 13, 2008 05:00:37
vchik
Вот, наигравшись вдоволь с мигающими светодиодами и нажмающимися лапой кнопками на асемблере, решил попробовать запрогать что-нибудь на Си

Начитавшись всяких ссылок, ФАКов и справочников, для прогания на Си выбрал пакет 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 в различные регистры

скриншоты прилагаютса - все три скрина - куски одной программы

Добавлено: Ср фев 13, 2008 10:15:22
Базилио
у меня WinAVR генерирует всего 93 байта...
причина этого проста: компилятор генерирует "пролог" в начале любой программы: очищает память, устанавливает стек и т.п. (если надо), эта часть - неизбежное следствие применения Си. еще добавляется вызов пустой функции main, которая состоит из команды возврата, плюс пустой бесконечный цикл в конце всего. плюс, как было сказано, векторы прерываний...

Добавлено: Ср фев 13, 2008 12:50:35
MetEl
Ввобще очень бы хотелось разобраться во всём этом. Как причёсывать код после компиляции чтоб выбросить всё не нудное.

Или почему файл для прошивки в МК весит 500 кб и сама флеш МК 128кб ? И при этом оказывется занято всего 30% от флеша.

Добавлено: Ср фев 13, 2008 13:26:12
Базилио
не путай формат файла прошивки HEX и собственно содержимое памяти... HEX - это ТЕКСТОВЫЙ файл, удобный для просмотра человеком, а при прошивке он преобразуется в реальные двоичные байты, которые и пишутся во флешь... вот и получается, что HEX огромный, а реально там данных для 30% памяти...

Добавлено: Ср фев 13, 2008 14:50:41
MetEl
Кажется понял...
Типа ещё один компилятор, тьфу т.е транслятор, чтоли. К примеру ПониПрог сама транслирует текс в байты (команды, машинные коды, если точнее) ?

Добавлено: Ср фев 13, 2008 16:20:36
vchik
О! Я начинаю втыкать! Т.е. hex также не конечный файл?

Я шью МК через avreal32. Значит АВРеал его еще преобразовывает?

Добавлено: Ср фев 13, 2008 20:36:10
ARV
заставь свой компилятор выдать bin-файл - это и будет в чистом виде то, что нужно микроконтроллеру. hex-это ТЕКСТОВОЕ ПРЕДСТАВЛЕНИЕ того, что надо, причем с некоторыми дополнительными фичами. если интересуешься - у меня на сайте есть описание формата Intel-HEX на русском языке.

Добавлено: Ср фев 13, 2008 20:58:05
vchik
оо, пасибо ща полазием

Добавлено: Ср фев 13, 2008 23:13:00
vchik
Оу хоу! Фишка расшарена! Добавил в мейкфайл создание бинарника *.bin получилось 98 байт.


Итого, как сказал уважаемый тов. Кот Базилио, эти 98 байт составили инициализация прерываний, загрузка стека и еще какие-то пока мне не очень ясные операции с регистрами.

Вот насчет операций интересно бы разобраться:

Добавлено: Ср фев 13, 2008 23:28:56
vchik
вот что удалось выяснить, 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




// ===================

Мораль - а что это за махинации с регистрами там типа проверки записалось ли в них что-то или нет?
Выкладывайте длинные коды нормально - во вложении. Паятель.

Добавлено: Чт фев 14, 2008 09:00:11
ARV
не вижу смысла в подобном ковырянии. хотите разработать оптимальную простую программу? используйте ассемблер:

Код: Выделить всё

   org  0
   rjmp PC

будет всего 2 байта. хотите просто работать с Си - работайте, и простите компилятору от 5 до 15% лишнего кода. Может, и больше чем 15% - но простите все равно.

Добавлено: Чт фев 14, 2008 11:14:14
vchik
Я не против 15% лишнего кода. Но если компилятор его вставляет значит он делает это с какой-то целью и, видимо, благой, поэтому в идеальном случае это не лишний код а полезный.


Интересно разобраться, зачем он делает эти операции 0х17 по 0х29 строки.

Добавлено: Чт фев 14, 2008 11:16:17
vchik
vchik писал(а):Выкладывайте длинные коды нормально - во вложении. Паятель.


Понял. Буду знать :)

Добавлено: Чт фев 14, 2008 13:38:25
ARV
vchik писал(а):Интересно разобраться, зачем он делает эти операции 0х17 по 0х29 строки.
он готовит плацдарм для последующих реально нужных ему (компилятору) дел. но, так как никаких дел вы ему не поручаете, эта подготовка пропадает напрасно.
смысл примерно такой.

Добавлено: Чт фев 14, 2008 23:34:38
Brutaller
vchik писал(а):Но если компилятор его вставляет значит он делает это с какой-то целью и, видимо, благой, поэтому в идеальном случае это не лишний код а полезный.

Это не всегда так ))

vchik, сколько времени с ассемблером успел поработать, что он так быстро надоел?

Добавлено: Сб фев 16, 2008 00:53:46
vchik
Ура! Написал на международном форуме по AVR-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).

Добавлено: Сб фев 16, 2008 00:59:06
vchik
Brutaller писал(а):vchik, сколько времени с ассемблером успел поработать, что он так быстро надоел?


Семестр прогали лабы в инсте на ассемблере процессоров i8080 и i8086

Семестр девушке помогал с курсом по AVR-микроконтроллерам, после этого курса мне понравилась тема про микроконтроллеры и я начал испытывать на практике.

Но все же на асме писать трудновато, вместо привычных циклов строить конструкции c brne и метками, структура пропадает, это как использовать goto в С++ прогах - в конце концов становится не ясно что куда и с какой стати перемещается.

Потому сел разбираться с Си, по ходу это круто! Еслиб еще и ООП запихать можно было ваще бы было шоколадно

Добавлено: Сб фев 16, 2008 09:14:38
ARV
avr-gcc в последней версии поддерживает объектно-ориентированные расширения С++, однако чтобы этим нормально пользоваться, возможностей классических AVR-ов явно маловато. да и лишнее это, имхо

Добавлено: Сб фев 16, 2008 14:40:27
vchik
Согласен с ARV. Для маломерных приложений С нам в помощь!


Тему, думаю, можно закрывать.


Всем котам спасибо за участие и советы! Желаю им всегда полной плошки вкусных мясных ломтиков из пакетика!

Re: Почему так велик размер кода пустой программы (комп.WinA

Добавлено: Сб фев 16, 2008 15:57:48
tych
vchik писал(а):для прогания на Си выбрал пакет WinAVR.


Советую попробовать и CVAVR