我正在为uController编写一个c程序,我设法用代码填充了32kb。
程序已满,具有以下“打印”功能:
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函数,例如:
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是具有仿真80C51芯片的FPGA芯片。对于此虚拟80c51,我正在编写代码。我的主程序有32kb的内存,变量有32kb的
编辑:* msg []是一个错字,必须是* msg
答案 0 :(得分:0)
简而言之,将此行放在源文件的开头:
#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)
如上面第二个链接和本页中所述,应启用OMF2以使用STRING指令 http://www.keil.com/support/man/docs/c51/c51_omf2.htm
答案 1 :(得分:0)
char xdata * msg1 =“ Hello World”;
char xdata msg1 [] =“ Hello World”;
我认为您永远不能以这种方式缩短程序,因为即使从xdata访问 消息,C运行时也会首先将其复制到那里,并来自代码(初始化数据)。
如果确实有很多“ print()”,则可以通过声明其参数的正确指针类型来压缩一些字节。我要解释一下:由于8051的体系结构很奇怪,“高级” C“通用”指针需要三个字节-两个字节作为偏移量,以及第三个字节来指定它是指向XDATA还是指向CODE。然后,每次调用print()都必须构造一个指针。
例如,如果您声明:
无效打印(char xdata * x)
现在print()仅接受指向xdata的指针,并且仅需要两个字节长的指针。每次调用print()都会更简单。
您的大多数文本似乎都是常量,因此它们将在代码中;因此您需要的指针类型是不是XDATA而是CODE(或其他正确的关键字)。
一旦您像上面那样声明了print(),您将再也不能打印不在代码段中的数据了;也许您将需要另一个功能,例如
printx(char *什么)
它将像以前一样接受任何段中的char *,但是只有在需要时才调用此昂贵的printx()。
希望这会有所帮助; 8051非常独特,编译器也很复杂(但Keil非常出色)。我建议您看一下生成的(低级)代码,也许您可以发现其他一些内存浪费。祝你好运!
附录:______________
发生一次我几乎没有文本的余地。通过应用一些文本压缩,我很好地解决了问题。鉴于所有文本均为纯ASCII,我使用了127个以上的字符来指向文本中常见的重复单词。例如,如果字符串“ Hello”重复几次,则可以用0x80 " world"
替换“ Hello world”。当然,打印例程必须检测这些特殊标记并管理减压-但这很容易。