Какие методы доступны для оптимизации памяти на ассемблере 8051? - PullRequest
5 голосов
/ 03 декабря 2008

Мне нужно оптимизировать код, чтобы освободить место для нового кода. У меня нет места для всех изменений. Я не могу использовать переключение банка кода (80c31 с 64k).

Ответы [ 7 ]

9 голосов
/ 03 декабря 2008

Вы действительно не дали много, чтобы продолжить здесь, но есть два основных уровня оптимизации, которые вы можете рассмотреть:

Micro-оптимизации: например. XOR A вместо MOV A, 0 Адам освещал некоторые из них раньше.

Макро-оптимизации: Посмотрите на структуру вашей программы, используемые структуры данных и алгоритмы, выполненные задачи и ОЧЕНЬ тщательно продумайте, как их можно переставить или даже удалить. Есть ли целые куски кода, которые на самом деле не используются? Ваш код полон отладочных выходных операторов, которые пользователь никогда не видит? Существуют ли функции, характерные для отдельного клиента, которые вы могли бы исключить из общего выпуска?

Чтобы разобраться с этим, вам нужно разобраться, ГДЕ ваша память израсходована. Карта Linker - хорошее место, чтобы начать с этого. Макрооптимизация - это то, где можно получить БОЛЬШИЕ победы.

Кроме того, вы могли бы - серьезно - попробовать переписать части вашего кода с помощью хорошего оптимизирующего компилятора Си. Вы можете быть удивлены тем, насколько жестким может быть код. Настоящий горячий ассемблер может улучшить его, но он может быть лучше, чем большинство программистов. Я использовал IAR один около 20 лет назад, и он сдул мои носки.

7 голосов
/ 03 декабря 2008

С языком ассемблера вам придется оптимизировать вручную. Вот несколько приемов:

Примечание: IANA8051P (я не программист 8501, но я много собирал на других 8-битных чипах).

Пройдите по коду, ищите дублирующиеся биты, независимо от их размера, и сделайте так, чтобы они функционировали.

Изучите некоторые из более необычных инструкций и посмотрите, можете ли вы использовать их для оптимизации, например. Хорошая хитрость заключается в использовании XOR A для очистки аккумулятора вместо MOV A, 0 - он сохраняет байт.

Еще один полезный трюк: если вы вызываете функцию перед возвратом, просто перейдите к ней, например, вместо:

CALL otherfunc
RET

Просто сделай:

JMP otherfunc

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

Это все, что я могу думать о макушке на данный момент.

6 голосов
/ 28 февраля 2009

Извините, я прихожу так поздно, но однажды у меня была точно такая же проблема, и это стало повторяющейся проблемой, которая продолжала возвращаться ко мне. В моем случае это был телефон на процессоре семейства 8051, и я полностью исчерпал ПЗУ (код). Он возвращался ко мне, потому что руководство продолжало запрашивать новые функции, поэтому каждая новая функция становилась двухэтапной. 1) Оптимизируйте старые вещи, чтобы освободить место. 2) Реализуйте новую функцию, используя только что созданную мной комнату.

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

Что-то, что я помню, сработало для меня и могло бы сработать для вас;

Посмотрите на суть того, что должен делать ваш код, и попытайтесь выявить некоторые действительно сильные гибкие примитивные операции. Затем перестройте код верхнего уровня, чтобы он вообще ничего не делал, кроме вызова примитивов. В идеале используйте подход, основанный на таблицах, ваша таблица содержит такие вещи, как; Состояние ввода, событие, состояние вывода, примитивы ... Другими словами, когда происходит событие, ищите ячейку в таблице для этого события в текущем состоянии. Эта ячейка сообщает вам, какое новое состояние нужно изменить (необязательно) и какие примитивы (если есть) выполнить. Вам может потребоваться несколько наборов состояний / событий / таблиц / примитивов для разных слоев / подсистем.

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

Извините, я опоздал на месяцы, и у вас, вероятно, не было времени сделать что-то столь радикальное. Насколько я знаю, вы уже использовали подобный подход! Но мой ответ может когда-нибудь помочь кому-то, кто знает.

3 голосов
/ 09 декабря 2008

В отделенном отделе вы также можете рассмотреть возможность сжатия части вашего кода и сохранения только той части, которая активно используется, распакованной в любой конкретный момент времени. Мне трудно поверить, что код, требуемый для системы сжатия / распаковки, будет достаточно малой частью крошечной памяти 8051, чтобы сделать это стоящим, но он сотворил чудеса на немного больших системах.

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

Наконец, если код действительно скомпилирован в C, я бы предложил компилировать с различными вариантами, чтобы увидеть, что происходит. Кроме того, Я написал статью о компактном C-кодировании для ESC еще в 2001 году, которая все еще актуальна. См. Этот текст для других приемов для небольших машин.

2 голосов
/ 04 декабря 2008

Помимо уже упомянутых (более или менее) очевидных оптимизаций, здесь есть очень странная (и почти невозможная) оптимизация: повторное использование кода. И с повторным использованием кода я имею в виду не обычное повторное использование, а а) повторное использование вашего кода в качестве данных или б) повторное использование вашего кода в качестве другого кода. Возможно, вы можете создать лютню (или любые другие статические данные), которые они могут быть представлены шестнадцатеричными кодами операций asm (здесь вы должны посмотреть на архитектуру гарвард против фон Неймана).

Другой будет повторно использовать код, придавая коду другое значение, когда вы обращаетесь к нему по-другому. Вот пример, чтобы прояснить, что я имею в виду. Если байты для вашего кода выглядят так: AABCCCDDEEFFGGHH по адресу X, где каждая буква обозначает один код операции, представьте, что вы теперь перейдете к X + 1. Может быть, вы получите совершенно другую функциональность, когда теперь разделенные байтами символы образуют новые коды операций: ABC CCD DE EF GH.

Но будьте осторожны: это не только сложно достичь (может быть, это невозможно), но и ужасает поддерживать. Так что, если вы не демонстрационный код (или что-то похожее на экзотику), я бы порекомендовал использовать уже упомянутые способы сохранения памяти.

2 голосов
/ 03 декабря 2008

Полагаю, вы знаете, что он не подходит, потому что вы написали / выполнили и получили ошибку «недостаточно памяти». :) Похоже, что ответы отвечают на ваш вопрос довольно точно если не считать примеров кода.

Я, однако, рекомендую несколько дополнительных мыслей;

  1. Убедитесь, что весь код действительно используется - тест покрытия кода? неиспользованный саб это большая победа - это трудный шаг - если ты оригинал автор, это может быть проще - (ну, может быть):)
  2. Обеспечить уровень «проверки» и инициализация - иногда мы иметь тенденцию быть чрезмерным в страховании мы инициализировали переменные / память и конечно же правильно, сколько раз мы был укушен этим. Не говорю не инициализировать (дух), но если мы делаем движение памяти, место назначения не нужно , чтобы быть нулем первым - это ласточкин хвост с

    1 -

  3. Оцените новые функции - можете существующий суб будет расширен, чтобы покрыть обе функции или, возможно, заменена существующая функция?
  4. Разбить большой код, если часть Большой код может сохранить , создав новый маленький код.

или, возможно, в таблице есть аргумент для аппаратной версии 2.0 ...:)

привет

2 голосов
/ 03 декабря 2008

1) По возможности сохраняйте переменные в Idata, а не в xdata
2) Посмотрите на ваши утверждения Jmp - используйте SJmp и AJmp

...