Какие методы доступны для оптимизации памяти на языке ассемблера 8051?

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


person Community    schedule 02.12.2008    source источник


Ответы (7)


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

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

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

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

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

person Community    schedule 02.12.2008
comment
К 2-м оптимизирующим компиляторам: У некоторых есть параметры для оптимизации не по скорости, а по пространству. - person flolo; 03.12.2008

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

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

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

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

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

CALL otherfunc
RET

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

JMP otherfunc

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

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

person Community    schedule 02.12.2008
comment
@jschmier: Некоторые другие приятные приемы не работают с TCO. Например, если процедура печати сообщения принимает адрес в DPTR и возвращает DPTR, указывающий на завершающий нуль, может быть полезно определить что-то вроде [может потребоваться настройка] PrImm: POP DPH / POP DPL / CALL PrintMsg / INC DPTR / PUSH DPL / PUSH DPH / RET. Каждый вызов Primm будет занимать только 3 байта плюс фактические символы для вывода. - person supercat; 24.02.2015

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

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

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

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

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

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

person Community    schedule 27.02.2009
comment
В подобных ситуациях (также с использованием чипов 8051) мне часто удавалось переписать ядро ​​кода во время перепроектирования оборудования. Самым большим выигрышем для меня является создание стандартных счетчиков (т. е. таких, которые содержат мс между 0..1000, других секунд 0..1000), а затем связывание с ними других функций. Это действительно экономит много оперативной памяти. Мне нравится ваш стандартный подход к функциям и таблицам, похожий на собственный интерпретатор байт-кода. Я использовал это для воспроизведения мелодий / вспышек на небольшой плате пользовательского интерфейса, которая воспроизводила песни для детей. - person Tom Leys; 05.05.2009

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

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

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

person Community    schedule 09.12.2008
comment
+1 за потрясающее название вашей статьи. Получение минимума от вашего компилятора C - person Tom Leys; 05.05.2009
comment
AFAIK 8051 не может запускать код из ОЗУ, поэтому этот подход не сработает. Однако байт-код — хорошая идея, если вы можете сделать интерпретатор достаточно компактным. - person Igor Skochinsky; 05.03.2013

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

person Community    schedule 02.12.2008

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

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

  1. Убедитесь, что весь код действительно используется — проверка покрытия кода? Неиспользованный саб — это большая победа — это трудный шаг — если вы оригинальный автор, это может быть проще — (ну, может быть) :)
  2. Ensure the level of "verification" and initialization -- sometimes we have a tendency to be over zealous in insuring we have initialized variables/memory and sure enough rightly so, how many times have we been bitten by it. Not saying don't initialize (duh), but if we're doing a memory move, the destination doesn't need to be zero'd first -- this dovetails with

    1 --

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

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

С уважением

person Community    schedule 03.12.2008

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

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

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

person Community    schedule 04.12.2008
comment
Дааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааа, эти оптимизации изрядно потрепаны. - person Paul Nathan; 04.12.2008
comment
Я проголосовал за вас обратно к нулю, потому что я думаю, что ваша идея оригинальна, хотя и немного непрактична. Я видел нечто подобное в очень небольшом масштабе; хитрый трюк для реализации конкретной функции в крошечном количестве байтов, а не метод общего назначения, чтобы помочь этому вопрошающему. - person Bill Forster; 28.02.2009