相关:
如果您正在为微控制器编写代码,如果您使用汇编或 C 或其他高级语言编写代码,是否有真正的区别?如果您编写 C 代码,您将如何编译它?
谢谢
几条评论:
1) 除非性能或优化限制允许,否则绝对不组装。以下指标随组装一起飞速发展:
2) 我的偏好是 C++ 而不是 C,因为它的命名空间封装及其对编译时面向对象实践的促进。C 有太多的机会出现全局变量和命名空间冲突。(实时Java会很好,但据我了解它的要求仍然很高)
或者更确切地说是 C++ 的一个子集:排除异常、虚函数、运行时类型识别,以及大多数情况下的动态内存分配——基本上是在编译时未指定的任何内容,因为它通常在运行时需要大量额外资源。这就是 C++ 的“膨胀”。
我已经将 TI 和 IAR 的 C++ 编译器用于 TMS320 和 MSP430 微控制器(分别),并且通过适当的优化设置,它们在减少 C++ 的开销方面做得非常出色。(特别是如果你通过明智地使用inline
关键字来帮助它)
我什至使用模板来实现它们的一些编译时优势,从而促进良好的代码重用:例如编写单个源代码文件来处理 8 位、16 位和 32 位 CRC;和编译时多态性,允许您指定一个类的通常行为,然后重用它但覆盖它的一些函数。同样,TI 编译器通过适当的优化设置具有极低的开销。
我一直在为 Microchip PIC 寻找 C++ 编译器;我发现唯一一家生产的公司是 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,我们通常将位数设为显式。然后编译它并编辑它生成的程序集(只需确保保留代码的开始/退出部分)并注意不要破坏任何寄存器而不在完成后恢复它们。
除非您正在做一些非常简单的事情,例如启用/禁用中断,否则内联汇编通常会出现问题。
我最喜欢的方法是编译器内在函数/“扩展 ASM”语法。Microchip 的 C 编译器基于 GNU C 编译器,它具有“扩展 ASM ”,可让您编写内联汇编的代码,但您可以给它很多提示,告诉它您正在引用哪些寄存器/变量,它会处理所有的保存/恢复寄存器以确保您的汇编代码与 C 语言“配合得很好”。TI 的 TMS320 DSP 编译器不支持这些;它确实有一组有限的内在函数,它们有一些用处。
我使用汇编来优化一些经常执行的控制循环代码,或者计算 sin()、cos() 和 arctan()。但否则我会远离汇编并坚持使用高级语言。
大多数微控制器制造商都提供某种交叉编译器,您可以在其中编译 PC 上的代码,然后将其传输到微控制器。
为什么选择 C?
C 的一个优点是您的代码将来更容易移植到其他微控制器。计算的历史表明,代码通常比硬件实现更持久。
第二个优点是控制结构(if、for、while)使代码更具可读性和可维护性。
为什么是汇编语言?
您可以手工优化。
结论
与这类问题的常见情况一样,权衡取舍很大程度上取决于具体用途。
请注意,通常可以通过在 C 代码中进行汇编调用来混合两者,这样您就可以找到适合您项目的平衡点。
特定于 PIC 硬件
似乎大多数 PIC 硬件都没有 GCC 选项。另一方面,正如评论者所指出的,用于 16 位 PIC24 和 dsPIC33 的 Microchip C30 编译器是 gcc。SDCC
也不支持 PIC 。新信息:根据评论,SDCC 对 PIC 有可行的支持。
还有一些其他的开源选项,但我没有使用它们的经验。
最好的选择可能是用 C 编写代码,然后对于极少数需要手动优化并且可以比编译器做得更好的实例,您应该将程序集编写到 c 文件中。
汇编编码对于 PC 来说已成为过去,但在嵌入式领域却非常重要。
在嵌入式中编写程序集不同于在 PC 上编写程序集。PC 编译器在生成优化指令方面“比人类更好”。嵌入式系统通常具有怪异的架构,并且它们的优化编译器不如 PC 优化编译器成熟。
我在为微控制器编写程序集时遇到的一个问题是需要非常小心你的代码是如何布局的。让一个跳转表跨越内存边界,并导致你的代码跳转到非常奇怪的地方是相当令人不安的。用 C 编码,编译器会为您覆盖该基础。
我肯定会选择 C。它更快,并且创建更可靠的软件。大会提供的东西很少,而且在稀缺的场合。请记住,在 C 中:
另一件与 PIC18 有特别关系的事情。您不必处理非直观的 PIC 架构和内存库之类的东西。
过去,我对 8051 的IAR C 编译器有很好的经验。
我最近的方法一直是这样的:-
使用良好的优化编译器用 C 语言编写它,只有在大小或速度存在问题时,才考虑在汇编程序中重写某些部分。
但是,自从采用这种方法以来,我从来不需要编写一行汇编程序......
去 c !
我曾在一家大型 CE 制造商工作。我最后一次看到汇编是在 1996 年左右,在一些小型中断服务例程中,用于 RC5 和 RC6 解码和电视调谐算法。之后总是使用 c 和 C++(只使用类,没有 stl、异常或 rtti)。对于 8051 的旧 KEIL 编译器、greenhills 编译器 (MIPS) 和 VxWorks 工具集(基于 PowerPC),我有很好的经验。
正如 Roddy 所说,首先用 C 编写,然后在汇编中优化(如果需要)。
在许多情况下,组装可以更快;当您在台式机上时,编译器往往会优化到手动组装很少需要的程度,但在 uC 世界中,通常是这样。此外,如果您需要编写中断处理例程之类的东西,您通常无法在 C 中完成。
至于编译,请为您的目标搜索 C 编译器。
肯定是 C,除非当
程序内存非常有限。说在经过艰苦的手工优化您的汇编代码之后,您设法将您的程序安装在这 1024 字节的闪存中,剩下 0 字节。在这种情况下,没有 C 编译器会有任何好处。
你想拥有绝对的时序控制。如果任何数量的中断延迟太长,您将不得不依赖汇编程序。
现在的问题是嵌入式可以是任何东西,从具有 6 个引脚和几个字节 RAM 的 ATTiny 到运行嵌入式操作系统的多核 SBC,这会让一些人的台式计算机感到羞耻。
因此,语言/开发环境的选择需要考虑到您需要的效率与系统的复杂程度。
首先 - C 在任何地方都可以工作并且可以很好地扩展,你走得越高,你最终会调用外部库等来处理复杂性。
对于非常小的 micros(以字节为单位测量 flash/ram),您最好使用 ASM,当您达到 kb 范围时,可以使用 C 或任何其他传统语言,因为您不需要计算每个字节。一旦你有兆字节可以使用,你就有能力并且越来越可能需要使用 RTOS 来处理所有事情并缩短开发时间。当你拥有硬件时,你可以在其上运行一个完整的操作系统,你可能可以将自己从硬件中抽象出来,只需将所有内容写在像 Java 或类似的填充单元中,而不必过多担心这一切是多么的浪费以及你是如何的不再是真正的程序员了... ;)
上述情况的例外是当您需要从硬件中获得的所有性能时,您可能需要降低一两个级别以保持效率。
这是底线,如果您使用 C,您可以稍后手动优化,我不会使用 C 或汇编程序以外的任何东西(没有 C++ 等)。
如果您使用的是 PIC 甚至 8051,关键是微控制器指令集,我只会使用汇编程序。如果它是编译器友好的 isa,如 arm 或 avr 或 msp430,则使用 C 来节省一些输入,但由于各种原因,您可能会在汇编程序中有一些例程。同样,您可能希望避免使用 C 库,即使 newlib 也可能过于庞大,请从它们那里借用代码或想法,但不要只链接其中一个。哦,回到问题,再次查看可用于目标的 C 编译器arm 和 avr 你不会有任何问题。可能 msp 也可以。仅仅因为 Keil 或 Iar 会向您出售编译器并不意味着您应该购买或使用它,付费编译器和免费编译器的输出可能是可怕的。
底线(另一个底线),没有全局答案(避免任何高于 C 的东西都是全局答案)它总是取决于平台是什么你的资源是什么你的任务是什么性能要求是什么便携性要求是(如果它真正嵌入在微控制器上,其中大部分是不可移植的)编译器、调试器、jtag 等可用,即使您正在开发的主机操作系统可能是一个重要因素。
还有一次可能需要用汇编语言编写:如果您需要进行一些低级 RAM 测试或类似的测试,这需要绝对控制数据的存储位置。
例如,确认SIL -2(安全完整性等级)及以上的软件可能需要对 RAM 进行持续检查,以检测任何可能的数据损坏。您正在检查的 RAM 区域在检查时不能更改,因此在汇编程序中编写测试可以确保这是真的,例如通过将任何局部变量存储在特定寄存器或 RAM 的另一个区域中. 在 C 语言中,这将是困难的,如果不是不可能的话。
将 RAM 清零并初始化非零静态变量的启动代码也可以用汇编程序编写,尽管通常会提供这种代码。
如果您编写的代码高度依赖于特定于设备的外设,并且您使用的工具链没有提供有效利用它们的必要内在函数(例如蹩脚的飞思卡尔 DSP563CC 编译器),那么请使用汇编。
除此之外,我认为使用汇编与高级语言的不成文规则与桌面软件开发的潜规则或多或少相同:保持代码干净、可维护,并使用机器语言优化热代码。
汇编语言的代码非常快且占用空间小,但是用汇编语言编写的代码不是可重用的代码。代码的这种可重用特性是软件设计最重要的特性。例如,如果您有 x86 处理器的汇编程序项目代码,它只能用于 x86 处理器,不能用于 ARM 处理器。但是,如果您有 x86 处理器的项目 C/C++ 代码,则可以将此代码用于 ARM 处理器。因此,最好避免使用汇编程序进行软件开发。
太糟糕了,到目前为止还没有人提到 Forth 或 Scheme。两者都适用于小型环境,并且可以带来令人印象深刻的生产力提升。
普通 C 或 Pascal,Modula2。但是由于编译器的可用性,这意味着 C.
额外的 C++ 和类似的东西只是出于风格的原因才有趣,因为动态分配和程序大小通常非常有限。
如果您的应用程序变得紧张,更复杂的运行时也会很痛苦。
汇编器也很有用,但前提是您销售的数量非常大,并且较小的固件意味着更小、更便宜的芯片(更少的闪存)并且程序的大小是可监督的(阅读:有一些机会你会及时得到它没有错误)