0

参考this:
通过C代码计算FLASH利用率

我决定检查实际组装说明的计算。
所以我的脚本计算汇编指令,位于功能启用代码的汇编列表文件中。
例如

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 字节,nmobj 文件为 1458 字节)。
为了进一步澄清,我创建了带有函数的文件的程序集,checkSize并与原始程序集文件进行了比较。我知道由于添加了checkSize功能,所以会有一些额外的东西,但是功能启用代码的指令预期是相同的(具有相同的编译器优化和其他选项)。
但他们不一样。

现在的问题是,为什么大函数内的特征代码的汇编指令存在如此差异,以及当我将其移动到仅包含特征代码的另一个文件时。
在这两种情况下,有什么可以预测额外尺寸的吗?

4

2 回答 2

1

这里可能会发生几件事。为了确保您将不得不阅读实际的汇编代码并弄清楚它在做什么。当您将其设置为高优化级别时,编译器非常聪明。例如,在您的第一个代码段中,编译器很可能在您的代码之外有汇编语句

// 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);

我过去做过这件事,它奏效了。没有尝试编译这个所以不知道你可能需要稍微弄乱它以获得你想要的东西。

于 2014-04-20T01:59:25.330 回答
0

优化很棘手。在一个大函数(和大文件)中,编译器具有更广泛的上下文,并且可以更积极地优化 - 重用常用表达式,选择较短形式的分支等(如果不知道您的目标架构,很难准确地说出)。

PS:我不太确定你如何从汇编计数到字节计数。

于 2014-04-17T23:42:29.477 回答