C 我怎样才能减少我的程序大小

C how can I decrease my program size

我正在为 uController 编写一个 c 程序,我设法用代码填充了 32kb。

该程序包含以下 'print' 功能:

void print(char *x)
{
    while(*x) {
        SerialWrite(*x++);}
}

SerialWrite 看起来像:

void SerialWrite(unsigned char c)

    {
        while(tx_buffer_size>250);
        ES=0;
        tx_buffer_size++;
        if (tx_buffer_empty == 0){
            txBuffer[tx_in++] = c;}
        else {
            tx_buffer_empty = 0;
            SBUF = c;}
        ES=1;
    } 

我用字符串文本作为参数调用打印函数,例如:

print("Hello World");

我只使用了 32kb 外部存储器中的 2.2kb,所以我的结论是 "Hello World" 移动到外部存储器而不是在主程序中硬编码。

不幸的是,我的尝试实际上让事情变得更糟,我做了以下事情:

char xdata *msg1 = "Hello World"; // <-- this made it worse, and the external memory space was not used at all
print(msg1);

比我试过:

char xdata msg1[] = "Hello World";
print(msg1);

这确实将外部存储器大小增加了 12 个,这是正确的,因为字符串包含 11 个字符 + 空值。但是程序内存也增加了3。我尝试了不同的字符串长度,但是程序内存一直增加3字节。

我该如何解决这个问题?

补充: 我正在使用 Keil 的 C 编译器,并且我在编译时会考虑程序大小。 uController 是一个 FPGA 芯片,它有一个仿真的 80C51 芯片。对于这个虚拟 80c51,我正在编写代码。我有 32kb 的主程序内存和 32kb 的变量

编辑:*msg[] 打错了,应该是 *msg

简而言之,将此行放在源文件的开头:

#pragma STRING (XDATA)

这些页面可以帮助您更好地理解:

http://www.keil.com/support/man/docs/c51/c51_le_const.htm http://www.keil.com/support/man/docs/c51/c51_string.htm

2018/06/25 编辑: 试试这一行:

#pragma O2 STRING (XDATA)

如上文第二个 link 和本页所述,应启用 OMF2 以使用 STRING 指令 http://www.keil.com/support/man/docs/c51/c51_omf2.htm

char xdata *msg1 = "Hello World";

char xdata msg1[] = "Hello World";

我不认为你可以用这种方式缩短你的程序,因为即使消息将被访问来自 xdata,它也会首先被 C 运行时复制到那里,从代码(初始化数据)中获取它

如果你真的有很多“print()”,那么你可以通过为其参数声明一个正确的指针类型来压缩一些字节。我解释一下:由于 8051 的奇怪架构,“高级”C“通用”指针需要三个字节 - 两个字节作为偏移量,第三个字节指定它是指向 XDATA 还是指向 CODE。那么每次调用print()都要构造这样一个指针。

例如,如果您声明:

void print(char xdata *x)

现在 print() 只接受指向 xdata 的指针,并且只需要两个字节长的指针。每次调用 print() 都会更简单。

看来你的大部分文字都是不变的,所以都是代码;所以你需要的指针类型是 不是 XDATA 而是 CODE (或者其他关键字是正确的).

一旦您像上面那样声明了 print() ,您将无法再打印不在代码段中的数据;也许你需要另一个功能,比如

printx(char* what)

它将接受来自任何段的 char*,就像以前一样,但您将仅在需要时才调用这个昂贵的 printx()。

希望这对您有所帮助; 8051 非常奇特,它的编译器很复杂(但 Keil 非常棒)。我建议查看生成的(低级)代码,也许您可​​以发现其他一些内存浪费。祝你好运!

附录:______________

有一次我没有足够的空间放文字。我通过应用一些文本压缩很好地解决了问题。鉴于所有文本都是纯 ASCII,我使用超过 127 个字符来指向文本中常见的重复单词。例如,如果字符串“Hello”重复几次,“Hello world”可以替换为 0x80 " world"。当然,打印例程必须检测那些特殊标记并管理解压缩 - 但这非常容易。