C как я могу уменьшить размер моей программы
Я пишу AC-программу для uController, и мне удалось заполнить 32 КБ с кодом.
Программа заполнена следующей функцией печати:
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");
Я использовал только 2,2 КБ своей внешней памяти 32 КБ, поэтому мой вывод слишком перенести "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's C и компилирую с учетом размера программы. UController - это микросхема FPGA с эмулированным чипом 80C51. Для этого виртуального 80c51 я пишу код. У меня 32 КБ памяти для основной программы и 32 КБ для переменных
РЕДАКТИРОВАТЬ: * MSG [] была опечатка, это должно было быть * MSG
2 ответа
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* что)
который будет принимать char * из любых сегментов, как и раньше, но вы будете вызывать это дорогостоящим printx() только при необходимости.
Надеюсь это поможет; 8051 очень своеобразен и компиляторы для него сложны (но Кейл великолепен). Я бы посоветовал взглянуть на сгенерированный (низкоуровневый) код, может быть, вы обнаружите некоторые другие потери памяти. Удачи!
Приложение:______________
Однажды мне случалось иметь мало места для текстов. Я решил, применив некоторое сжатие текста. Учитывая, что все тексты были в простом ASCII, я использовал символы более 127, чтобы указать на общие, повторяющиеся слова в текстах. Например, "Hello world" можно заменить на 0x80 " world"
, если строка "Hello" повторяется несколько раз. Конечно, процедура печати должна обнаруживать эти специальные маркеры и управлять декомпрессией, но это очень легко.
Короче говоря, поместите эту строку в начале вашего исходного файла:
#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)
как указано во 2-й ссылке выше и на этой странице, OMF2 должен быть включен для использования директивы STRING http://www.keil.com/support/man/docs/c51/c51_omf2.htm