有哪些技术可用于8051汇编语言的内存优化?

时间:2008-12-02 21:35:55

标签: optimization assembly embedded intel 8051

我需要优化代码以获得一些新代码的空间。我没有所有变化的空间。我不能使用代码库切换(80c31与64k)。

7 个答案:

答案 0 :(得分:9)

你还没有真正付出很多努力,但你可以考虑两个主要的优化级别:

<强>微优化:   例如。 XOR A而不是MOV A,0   亚当早些时候很好地介绍了其中一些。

<强>宏观优化:   查看程序的结构,使用的数据结构和算法,执行的任务,并非常认真地考虑如何重新排列甚至删除它们。是否存在实际未使用的整个代码块?您的代码是否充满了用户从未看到的调试输出语句?是否存在特定于单个客户的功能,您可以将其从一般版本中删除?

为了更好地处理这个问题,你需要解决你的内存耗尽的问题。 Linker地图是一个很好的开始。宏观优化是BIG获胜的地方。

顺便说一句,您可以 - 认真尝试使用优秀的C编译器重写代码的一部分。您可能对代码的紧密程度感到惊讶。真正的汇编程序可能能够改进它,但它可以比大多数编码器更容易。大约20年前我使用了IAR一个,它吹掉了我的袜子。

答案 1 :(得分:7)

使用汇编语言,您必须手动优化。以下是一些技巧:

注意:IANA8051P(我不是8501程序员,但我在其他8位芯片上进行了大量组装)。

通过代码查找任何重复的位,无论多小,都可以使它们起作用。

了解一些更不寻常的说明,看看是否可以使用它们进行优化,例如。一个很好的技巧是使用XOR A来清除累加器而不是MOV A,0 - 它保存了一个字节。

另一个巧妙的技巧是,如果你在返回之前调用一个函数,只需跳转到它,而不是:

CALL otherfunc
RET

只是做:

JMP otherfunc

始终确保你在可能的情况下进行相对跳跃和分支,它们使用的内存少于绝对跳跃。

这就是我现在能想到的全部内容。

答案 2 :(得分:6)

抱歉,我迟到了,但我曾经遇到过完全相同的问题,而且这个问题一直存在。在我的情况下,该项目是8051系列处理器上的电话,我完全消耗了ROM(代码)内存。它一直回到我身边,因为管理层不断要求新功能,所以每个新功能都变成了两个步骤。 1)优化旧东西以腾出空间2)实现新功能,耗尽我刚刚制作的房间。

有两种优化方法。战术与战略。通过微优化思想,战术优化一次可以节省几个字节。我认为你需要进行战略优化,这需要更加彻底地重新思考你是如何做事的。

我记得曾为我工作的东西,可以为你工作;

查看代码必须执行的操作的本质,并尝试提取一些非常强大的灵活原始操作。然后重建你的顶级代码,这样除了调用基元之外它根本不会做任何低级别的代码。理想情况下使用基于表格的方法,你的表格包含的东西;输入状态,事件,输出状态,基元....换句话说,当事件发生时,在表中查找当前状态中该事件的单元格。该单元格告诉您要更改的新状态(可选)以及要执行的基元(如果有)。对于不同的层/子系统,您可能需要多组状态/事件/表/基元。

这种方法的许多好处之一是您可以将其视为为您的特定问题构建自定义语言,您可以非常有效地(即使用最少的额外代码)通过修改表来创建新功能。

抱歉,我已经迟到了几个月,你可能没有时间去做这种激进的事情了。据我所知,你已经使用了类似的方法!但是我的回答可能有一天会帮助其他人。

答案 3 :(得分:3)

在被打败的部门中,您还可以考虑压缩部分代码,并且只保留在任何特定时间点主动使用的部分解压缩。我很难相信压缩/解压缩系统所需的代码足够小,只需8051的微小内存的一部分就可以实现这一点,但是在稍微大一点的系统上却有了奇迹。

另一种方法是转向字节码格式或某些状态机工具输出的表驱动代码 - 让机器了解您的应用正在做什么并生成一个完全难以理解的实现可能是一个很好的节省空间的方法:)

最后,如果代码确实是用C编译的,我建议用一系列不同的选项进行编译,看看会发生什么。另外,I wrote a piece on compact C coding for the ESC back in 2001 that is still pretty current.请参阅该文本,了解小型机器的其他技巧。

答案 4 :(得分:2)

1)尽可能将变量保存在Idata而不是xdata中 2)查看你的Jmp语句 - 使用SJmp和AJmp

答案 5 :(得分:2)

我认为你知道它不合适,因为你写了/编译并得到了“内存不足”的错误。 :)看来答案很准确地解决了你的问题;没有获得代码示例。

但是,我会建议一些额外的想法;

  1. 确保所有代码确实 正在使用 - 代码覆盖率测试?一个 未使用的子是一个很大的胜利 - 这是一个 艰难的一步 - 如果你是原始的 作者,它可能更容易 - (好吧,也许):)
  2. 确保“验证”级别 和初始化 - 有时我们 有过于热心的倾向 保险我们已初始化 变量/内存还不够 这是正确的,我们有多少次 被它咬了。不是说不 初始化(duh),但如果我们正在做的话 记忆移动,目的地 不首先需要为零 - 这与...相吻合

    1 -

  3. 评估新功能 - 可以 现有的子要加强覆盖 两个功能或者也许是一个 现有功能已更换?
  4. 分解大码如果是一块 大代码可以保存创建一个新的 小代码。
  5. 或者现在桌子上有硬件版本2.0的论据......:)

    问候

答案 6 :(得分:2)

除了已经提到的(或多或少)明显的优化之外,这里有一个非常奇怪的(并且几乎不可能实现):代码重用。使用代码重用我不是指正常的重用,而是a)将代码重用为数据或b)将代码重用为其他代码。也许你可以创建一个它可以用asm hex操作码表示的lut(或任何静态数据)(这里你必须看看harvard vs von neumann架构)。

另一个会在代码不同的情况下通过赋予代码不同的含义来重用代码。这是一个清楚我的意思的例子。如果您的代码的字节如下所示:地址X处的AABCCCDDEEFFGGHH,其中每个字母代表一个操作码,想象您现在将跳转到X + 1。也许你会得到一个完全不同的功能,其中现在按空格分隔的字节组成新的操作码:ABC CCD DE EF GH。

但要注意:这不仅难以实现(也许是不可能的),而是维持的恐怖。因此,如果您不是演示代码(或类似异国情调的东西),我建议您使用其他已提及的方法来保存内存。