Вычисление размера части кода файла C

Со ссылкой на это:
расчет использования FLASH кодом C

Я решил проверить расчеты фактических инструкций по сборке.
поэтому мой скрипт подсчитывает инструкции по сборке, лежащие в файле со списком сборок кода включения функции.
например.

if(TRUE == feature1_enable)
{
    // instruction counting starts here
    doSomething;
    .
    .
    .
    // instruction counting stops here
}

Это дает мне некоторые подсчеты x, из которых я могу определить размер кода.

Чтобы перепроверить результат, я решил nm объектный файл кода функции, но nm дает размер всей функции, а не отдельных операторов.
Поэтому я скопировал часть кода для этой функции в отдельный файл, сделал функцию он включает необходимые заголовки и объявленные переменные для компиляции этого файла (заботясь о том, чтобы локальные переменные оставались локальными, а глобальные оставались глобальными). поэтому новый файл выглядит так:

#include "header1.h"
#include "header2.h"

global_variables;
void checkSize( void )
{
    local_variables;

    // feature1_enable code
    doSomething;
    .
    .
    .
 }

Теперь функция checkSize содержит только код включения функции, поэтому после компиляции, если я nm скопирую файл obj, я смогу получить почти такой же результат, как и количество сборок (за исключением некоторого дополнительного размера, используемого при настройке функции). Но это не так, я получил огромную разницу. (1335 байт в случае инструкций по сборке и 1458 байт в случае nm obj-файла).
Чтобы получить дальнейшее разъяснение, я создал сборку файла с функцией checkSize и сравнил с исходным файлом сборки. Я понимаю, что есть некоторые дополнительные вещи из-за добавления функции checkSize, но инструкции кода включения функции должны быть такими же (с той же оптимизацией компилятора и другими параметрами).
Но они не были одинаковыми.

Теперь возникает вопрос, почему существует такая разница в инструкциях по сборке для кода функции внутри большой функции и когда я перемещаю его в другой файл только с кодом функции.
Есть ли что-нибудь, чтобы предсказать дополнительный размер в любом случае?


person Harsh Panchal    schedule 17.04.2014    source источник


Ответы (2)


Здесь может произойти несколько вещей. Чтобы быть уверенным, вам придется прочитать реальный ассемблерный код и выяснить, что он делает. Компилятор ОЧЕНЬ умный, когда вы устанавливаете его на высокий уровень оптимизации. Например, в вашем первом сегменте кода компилятор может иметь ассемблерные операторы за пределами вашего кода.

// instruction counting starts here
// instruction counting stops here

комментарии, выполняющие работу между комментариями. Во втором примере оптимизация невозможна, и вся работа должна выполняться в функции. Также не сбрасывайте со счетов количество места, которое занимают пролог и эпилог функций. В зависимости от набора инструкций вашего процессора, его стека и использования регистров он может быть довольно большим. Например, в Power PC нет команды push many registers, и вы должны выдвигать каждый отдельный регистр и извлекать каждый отдельный регистр из кадра стека при входе и выходе из функции. Когда вы имеете дело с 32 регистрами, это может быть довольно много кода.

Вы можете попробовать трюк, когда у вас установлены высокие уровни оптимизации для вашего компилятора. Компилятор не может оптимизировать операторы "asm", поскольку он не знает, что в них происходит. Что вы можете сделать, так это поместить некоторый фиктивный код в операторы «asm». Мне лично нравится создавать глобальные символы, которые находятся в объектном файле. Таким образом, я могу получить адрес начального и конечного символов и вычислить размер кода между ними. Это выглядит примерно так...

asm(" .globl sizeCalc_start");
asm(" sizeCalc_start: ");
// some code
asm(" .globl sizeCalc_end");
asm(" sizeCalc_end:");

Затем вы можете сделать что-то в такой функции, как

extern int sizeCalc_start;
extern int sizeCalc_end;
printf("Code Segment Size %d\r\n", &sizeCalc_end - &sizeCalc_start);

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

person Jong Chen    schedule 20.04.2014

Оптимизация сложная. Внутри большой функции (и большого файла) компилятор имеет более широкий контекст и может оптимизировать более агрессивно - повторно использовать общие выражения, выбирать более короткие формы ветвей и т. д. (трудно сказать точно, не зная целевой архитектуры).

PS: я не совсем уверен, как вы переходите от подсчета сборок к подсчету байтов.

person user58697    schedule 17.04.2014
comment
Целевой процессор PowerPC (MPC5556). А компилятор Windriver Diab. Таким образом, инструкции по сборке имеют фиксированный размер ОС 4 байта. - person Harsh Panchal; 18.04.2014