编写固件:汇编还是高级?

时间:2009-01-16 21:41:46

标签: c assembly embedded firmware

相关:

如果您正在为microcontroller编写代码,那么如果您使用汇编语言或C语言或其他高级语言编写,是否存在真正的区别?如果你编写C代码,你会如何编译它?

由于

17 个答案:

答案 0 :(得分:31)

几条评论:

1)绝对装配,除非性能或优化限制保证。以下指标通过汇编进行了讨论:

  • 编写代码的时间
  • 调试时间
  • 测试时间
  • 时间记录
  • 时间弄清楚(1年后)你编码时你在做什么
  • 犯错的可能性

2)我的偏好是C ++而不是C,因为它的命名空间封装和&它促进了编译时面向对象的实践。 C有太多的全局变量和命名空间冲突的机会。 (实时Java会很好,但据我所知,它的要求仍然很高)

或者更确切地说是C ++的一个子集:排除异常,虚函数,运行时类型识别,以及大多数情况下的动态内存分配 - 基本上是在编译时未指定的任何内容,因为它通常需要大量额外资源在运行时。这就是C ++的“膨胀”。

我已经使用TI和IAR的C ++编译器,分别用于TMS320和MSP430微控制器,并且通过适当的优化设置,他们可以很好地减少您对C ++的开销。 (特别是如果您通过明智地使用inline关键字)来帮助它

我甚至使用模板来获得一些编译时间的好处,这些好处促进了良好的代码重用:例如编写单个源代码文件来处理8位,16位和32位CRC;和compile-time polymorphism允许您指定类的通常行为,然后重用它但覆盖其某些功能。同样,TI编译器具有极低的开销,并具有适当的优化设置。

我一直在寻找Microchip PIC的C ++编译器;我找到的唯一一家生产IAR的公司就是IAR。 ($$$一直是个障碍,但我希望有时会买一份)Microchip C18 / C30编译器非常好,但它们是C语言,而不是C ++。

3)关于编译器优化的一个具体警告:它可以/将使调试变得非常困难;通常不可能单步执行优化的C / C ++代码,并且您的监视窗口可能会显示与您认为应该包含未优化代码的内容无关的变量。 (一个好的调试器会警告你一个特定的变量已经优化不存在或者进入寄存器而不是存储器位置。许多调试器没有。> :(

另外一个好的编译器可以让你通过#pragmas在功能级别选择/选择优化。我使用过的只允许您在文件级别指定优化。

4)将C代码连接到汇编:这通常很困难。最简单的方法是创建一个具有所需签名的存根函数,例如: uint16_t foo(uint16_t a, uint32_t b) {return 0; },其中uint16_t = unsigned short,我们通常将#位显式化。然后编译它并编辑它产生的程序集(只需确保离开代码的开始/退出部分)并且小心不要破坏任何寄存器而不在完成后恢复它们。

内联汇编通常会遇到问题,除非您正在执行 very 这样的简单操作,例如启用/禁用中断。

我最喜欢的方法是编译器内在函数/“扩展ASM”语法。 Microchip的C编译器基于GNU C编译器,并且它具有“extended ASM”,它允许您对内联汇编的位进行编码,但是您可以给它很多提示,告诉它您正在引用哪些寄存器/变量,它将处理所有寄存器的保存/恢复,以确保您的汇编代码与C“良好”.TM的TMS320 DSP编译器不支持这些;它确实有一组有限的内在函数可供使用。

我使用汇编来优化一些经常执行的控制循环代码,或者计算sin(),cos()和arctan()。但是否则我会远离集会并坚持使用高级语言。

答案 1 :(得分:21)

大多数微控制器制造商提供某种交叉编译器,您可以在PC上编译代码然后将其传输到微控制器。

为什么选择C?
C的一个优点是您的代码将来更容易移植到其他微控制器。计算的历史表明,代码通常比硬件实现更长久 第二个优点是控制结构(if,for,while)使代码更易读和可维护。

为什么使用汇编语言?
您可以手工优化。

<强>判决
与这类问题的情况一样,权衡取决于具体用途 请注意,通常可以通过在C代码中进行汇编调用来混合两者,这样您就可以找到适合您项目的余额。

特定于PIC硬件
seems你没有大多数PIC硬件的GCC选项。另一方面,作为评论者注意到,16位PIC24和dsPIC33的Microchip C30编译器是gcc。
SDCC尚不支持PIC 新信息:根据评论,SDCC对PIC有可行的支持。
还有其他一些开源options,但我对它们没有经验。

答案 2 :(得分:7)

最佳选择可能是用C编写代码,然后对于需要手动优化并且可以比编译器做得更好的极少数实例,您应该将程序集编码到c文件中。

答案 3 :(得分:6)

对于PC来说,汇编代码已成为过去,但在嵌入式代码中非常重要。

在嵌入式中编写程序集与在PC上编写程序集不同。 PC编译器在生成优化指令时“比人类更好”。嵌入式系统通常具有奇怪的架构,其优化编译器并不像PC优化编译器那样成熟。

答案 4 :(得分:5)

我在为微控制器编写程序集时遇到的一个问题是需要非常小心你的代码是如何布局的。有一个跨越内存边界的跳转表,并导致你的代码跳转到非常奇怪的地方是相当令人不安的。在C语言编码中,编译器为您提供了基础。

答案 5 :(得分:5)

我肯定会选择C.它更快,它可以创建更可靠的软件。大会几乎没有提供,在稀缺的场合。请记住在C:

  • 您可以轻松地从现有平台移植代码,甚至可以从PC上移植代码。
  • 您可以使用高级语言进行开发,而不会影响执行速度或代码大小。如果可以使用高质量的编译器(PIC18有很多选择),那么使用C语言可能比手工制作的装配更好。
  • 调试,测试和维护代码要容易得多。 C生成更可靠的代码。

另一件事与PIC18有关。您不必处理非直观的PIC架构和内存块等内容。

答案 6 :(得分:4)

我过去曾为8051的IAR C编译器提供过良好的经验。

我最近的做法一直是: -

使用优秀的编译器将其写入C语言,并且只有在大小或速度有问题时,才考虑在汇编程序中重写某些部分。

然而,由于采用这种方法,我从来没有需要来编写一行汇编程序......

答案 7 :(得分:4)

去找c!

我曾在一家大型CE制造商工作过。我最后一次看到装配是在1996年左右的一些小型中断服务程序中用于RC5和RC6解码和电视调谐算法。 之后总是使用c和C ++(只使用类,没有stl,异常或rtti)。 我对8051的旧KEIL编译器以及greenhills编译器(MIPS)和VxWorks工具集(基于PowerPC)有很好的经验。

正如Roddy所说,首先用C语言编写,然后稍后优化组装(如果需要)。

答案 8 :(得分:3)

在许多情况下,装配可以更快;当你在桌面上时,编译器往往被优化到手工装配很少是必需的程度,但在uC世界中,它往往是。此外,如果您需要编写中断处理例程和类似的东西,您通常无法在C中执行此操作。

至于编译,请浏览一下目标的C编译器。

答案 9 :(得分:2)

现在的问题是,嵌入式设备可以是任何东西,从具有6个引脚和几个字节RAM的ATTiny到运行嵌入式操作系统的多核SBC,这会让一些人的桌面计算机感到羞耻。

因此,语言/开发环境的选择需要考虑您需要多大的效率与系统的复杂程度。

首先关闭 - C无处不在,并且可以很好地扩展,越高越好,你最终会调用外部库等来处理复杂性。

对于非常小的微型(测量flash / ram,以字节为单位),最好使用ASM,当你达到kb范围时,可以使用C或任何其他传统语言,因为你不需要计算每个字节。一旦你有兆字节玩,你就有能力,并且越来越有可能要求使用RTOS来处理所有事情并缩短开发时间。当你拥有硬件时,你可以运行一个完整的操作系统,你可以从硬件中抽象自己,只需在像Java这样的填充单元格中编写所有东西,而不必过多担心这一切是多么浪费,以及你是如何不再是真正的程序员......;)

上述例外情况是,当您需要从硬件中获取所有性能时,您可能需要降低一两级以保持效率。

答案 10 :(得分:2)

绝对是C,除了

  • 程序存储器非常有限。在经过精心设计的汇编程序代码之后,您可以设法在这个1024字节的Flash中使用您的程序,剩下0个字节。在这种情况下,没有C编译器会有任何好处。

  • 您希望拥有绝对时间控制。如果任何数量的中断延迟太长,您将不得不依赖汇编程序。

答案 11 :(得分:1)

用汇编语言编写的代码确实非常快,而且占用空间小,但是用汇编语言编写的代码不是可重用的代码。代码的可重用性功能是软件设计中最重要的功能。例如,如果您具有用于x86处理器的汇编程序项目代码,则该代码只能用于x86处理器,而不能用于ARM处理器。 但是,如果您有用于x86处理器的项目C / C ++代码,则可以将此代码用于ARM处理器。因此,最好避免使用汇编程序进行软件开发。

答案 12 :(得分:1)

如果您编写的代码高度依赖于特定于设备的外设,并且您使用的工具链无法提供必要的内在函数来有效利用它们(如蹩脚的Freescale DSP563CC编译器),那么请使用汇编

除此之外,我认为使用汇编语言与高级语言的不成文规则与桌面软件开发的规则大致相同:保持代码清洁,可维护,并使用机器语言优化热代码。

答案 13 :(得分:1)

还有一次可能需要在汇编中进行写入:如果需要进行低级RAM测试或类似操作,则需要绝对控制数据的存储位置。

例如,确认SIL - 2(安全完整性等级)及以上的软件可能需要对RAM进行连续检查,以便检测任何可能的数据损坏。您正在检查的RAM区域在检查时无法更改,因此在汇编程序中编写测试可以确保这是真的,例如将任何局部变量存储在特定寄存器或RAM的另一个区域中。如果不是不可能的话,这在C中很难。

将RAM归零并初始化非零静态变量的启动代码也可以用汇编程序写入相同的代码,但通常会提供这种代码。

答案 14 :(得分:0)

到目前为止,还没有人提到过Forth或Scheme。两者都适用于小型环境,并且可以提高生产率。

答案 15 :(得分:0)

Plain C或Pascal,Modula2。但由于编译器的可用性意味着C。

由于动态分配和程序大小通常非常有限,因此C ++和类似物的附加功能仅仅是出于风格的考虑。

如果你的应用程序变得紧张,那么更复杂的运行时也会很痛苦。

汇编程序也很有用,但只有当你卖出非常大的数量时,较小的固件才意味着更小,更便宜的芯片(闪存更少)并且程序的大小是可以监视的(读:你有可能获得它无时间的bugfree)

答案 16 :(得分:0)

如果您使用C,这是底线,您可以稍后进行优化,我不会使用除C或汇编程序之外的任何东西(没有C ++等)。

关键是微控制器指令集,如果你使用的是PIC,甚至是8051我只使用汇编程序。如果它是一个编译器友好的像arm或avr或msp430那么使用C来保存一些输入,但你可能会因为各种原因在汇编程序中有一些例程。同样地,你可能想要避免使用C库,即使是newlib也可能过于笨重,从它们那里借用代码或想法,但不要只链接一个。哦,回到问题,看看C编译器可用于目标,再次胳膊和avr你不会有任何问题。可能msp也没问题。仅仅因为Keil或Iar会卖给你一个编译器并不意味着你应该购买它或使用它,付费和免费编译器的输出可能是可怕的。无论如何你需要精通asm并检查输出(你可能必须编写一个反汇编程序才能执行此操作)。

底线(另一个底线),没有全局答案(完全避免任何高于C的全局答案)它总是取决于平台是什么资源是什么你的任务是什么性能要求是什么可移植性要求是(如果​​它真的嵌入在微控制器上,大部分都是定义不可移植的)编译器,调试器,jtag等都是可用的,即使你正在开发的主机操作系统可能是一个重要因素