使用C而不是Assembly有哪些优点/缺点?[关闭]


15

我目前正在研究电信和电子领域的工程学,我们已经从微处理器编程的汇编程序迁移到了C语言。我怀疑这是个好主意。与汇编相比,C有哪些优缺点?

我看到的优点/缺点是:

优点:

  • 我可以说C语法比汇编器语法更容易学习。
  • 使用C可以更轻松地制作更复杂的程序。
  • 学习C比学习汇编器更有效率,因为围绕C的开发工作比汇编器要多。

缺点:

  • 汇编器是比C更底层的编程语言,因此它非常适合直接对硬件进行编程。
  • 暗示您可以使用内存,中断,微寄存器等的灵活性更高。

17
嗯...欢迎来到新世纪。您会在这里喜欢它。我们运行的微控制器.NETJava的Linux的,并使用甚至还有人蟒蛇编程的PIC
ZJR 2012年

@ZJR如何使用Python编写PIC?哪张图?
确实是2012年

2
@detly它不是成熟的python,只是核心的一个子集。如果需要,可以在控制器功能上使用python语法pyastra是我用谷歌搜索出来的第一个示例,但我还记得曾经阅读过另一个文档,也做了ATMEL。
ZJR 2012年

4
老实说,由于现代处理器的复杂性,如果许多程序员能够编写比现代C编译器无法生成的更紧凑,更高效的汇编器,我会感到惊讶。例如,我不想尝试在汇编器中对EPIC架构的 CPU 进行编程- 梅尔(Mel)恰好适合安腾(Itanium)。* 8')
Mark Booth 2012年

5
@ZJR这个新世纪听起来令人兴奋!但是,我很好奇,用什么语言为这些微控制器编写了.NET运行时,Java VM和Linux?像这样,实际的微控制器编程是用哪种语言完成的?哦...这个世纪也是C还是汇编程序...

Answers:


17

以下是一些可能对您有所帮助的堆栈溢出答案(这些是响应最高的,可接受的答案):

优点

/programming/143561/is-there-a-need-to-use-assembly-these-days(仅适用于1万用户)或存档

  • 组装是在引导程序的最早阶段使用的。当堆栈上的CPU电源不可用时,很难阻止C编译器尝试将内容保存到堆栈中。一旦完成了最早的初始化,引导加载程序的大部分就用C编写了。
  • 程序集用于编写互斥锁原语。基本上不可能让C编译器在所需位置发出内存屏障指令。
  • 诸如memset()或memcpy()之类的例程通常是在汇编中完成的。例如,我编写了一个具有大型展开循环的memset(),该循环可动态计算分支地址以跳入该循环的中间进行最后一次迭代。AC例程将生成更多代码,从而导致I $丢失。同样,CPU指令集通常包含高速缓存行加载或其他可以大大加速memcpy()的指令,而C编译器将不会使用这些指令。

缺点

/programming/2684364/why-arent-programs-write-in-assembly-more-often

  • 与高级语言相比,ASM的可读性较差,并且实际上无法维护。
  • 而且,与其他更流行的语言(例如C)相比,ASM开发人员更少。
  • 此外,如果您使用高级语言并且新的ASM指令可用(例如SSE),则只需更新编译器,您的旧代码就可以轻松地使用新指令。

下面的最后一篇文章是Stack Overflow文章,概述了一个场景,该场景将显示比C更快的汇编示例(执行相同功能时)。

/programming/577554/when-is-assembler-faster-than-c


20
  • 与汇编语言相比,C语言更易于编程。有明显的原因不值得重新哈希处理。

  • C易于使用,可让您更快地编写程序。通常,这些程序也更易于调试和维护。此外,使用C来管理大型复杂程序更加容易。

  • 通常,由编译器生成的代码(在速度和效率方面)与手写汇编器一样好-如果不是更好。

  • C是低级的,很少有人会想降低C。增加抽象层很少是一件坏事。

  • 当需要降低时,可以使用Assembly,否则可以使用C。

  • 您可以用C代码编写Assembly,但是不能用C代码编写C。


6
我会说,也许有时候您会看到C编译器优化的机器代码比您的手写汇编代码更好
用户

@crucified-在90年代中期到后期,这已经是一个普遍(并且通常是合理的)主张。编译器可靠且系统地应用优化-不仅仅是在发现机会时。
2012年

15

可以将AC程序编译为不同的微处理器体系结构。


4

在微处理器编程中,我们已从汇编程序迁移到C语言。我怀疑这是个好主意

不用担心,没有人再使用100%汇编程序开发新程序。如今,C甚至可以用于最微小,最糟糕的8位体系结构。但是,了解一些汇编程序会使您成为更好的C程序员。另外,程序中总是有一些小细节需要用汇编器编写。

我可以说C语法比汇编器语法更容易学习。

是的,语法肯定更容易。但是,学习整个C语言以及所有令人讨厌的细节比学习特定汇编程序的所有细节要复杂得多。C是一门更大更广泛的语言。但是话又说回来,您可能不需要学习所有细节。

使用C可以更轻松地制作更复杂的程序。

实际上,C提供了用于模块化程序设计的机制,例如封装和局部作用域/局部变量。C具有一个标准库,以及过去30年中编写的大量资源。最重要的是,C是可移植的。

学习C比学习汇编器更有效率,因为围绕C的开发工作比汇编器要多。

C具有大量的预制功能,库和资源,因此可以减少对轮子的重新发明。但除此之外,您的陈述是主观的。我相信这是个人喜好问题。

例如,我是一位经验丰富的C程序员,偶尔会编程C ++。我发现自己在C ++中的生产力远不如在C ++中高,因为我不了解C语言。但是仅仅因为我有这种感觉,并不一定意味着C语言中的编程比C ++中的编程更具生产力。有经验的C ++程序员肯定会有相反的看法。

“生产性”有很多方面。一个非常重要的方面是维护时间,尤其是修复由维护引起的错误所需的时间。C比汇编程序容易维护。

汇编器是比C更底层的编程语言,因此它非常适合直接对硬件进行编程。

硬件编程可以直接使用两种语言进行。在C语言中,您唯一无法做的就是访问CPU内核本身的堆栈指针和条件寄存器等。因此,如果通过硬件编程来表示与自己的CPU进行通信,那么是的,汇编器所允许的范围比C多得多。如果您的意思是访问外部硬件,那么汇编器对C而言就没有好处。但是也许有缺点,因为通常很难编写特定外部设备的通用汇编代码,而不是通用C代码。

暗示您可以使用内存,中断,微寄存器等的灵活性更高。

这是不正确的。尽管您可能不得不依赖于特定于编译器的C代码(例如interrupt关键字),但是C也允许您执行所有这些操作。


最后,您需要了解两种语言才能对MCU进行编程,重点是C。


整个C语言比某些更神秘的机器语言以哪种方式更复杂?两者都做完之后,我认为没有库的C的复杂程度要低得多。如果要引用C标准库,则还需要在汇编器中执行类似的操作。C可能是一门越来越大的语言,但是您不需要了解同样的细节。 a = b[i] + c;它比要加载b[i](需要计算)并c放入寄存器(必须使其可用),添加和存储的指令要简单得多。
David Thornley

1
@DavidThornley您对C的了解越多,您就越意识到它的复杂性。您是否知道数百种未定义/未指定/隐式定义行为的情况?您是否详细了解所有隐式类型提升规则(整数提升,通常的算术转换)?有关类型说明符的所有特殊规则和语法?所有各种形式的静态/动态多维数组,包括数组指针(不要与指向数组第1个元素的指针混淆)C99和C11的所有功能?等等。

1
@Lundin:关于C的重要一点是,您能够提出所有这些问题并找到具体答案。要求符合标准的编译器记录其在62种(而非“数百种”)实现定义的行为中的行为。程序集的绝对简单性使其成为您自己的午餐方案,从而将C处理的复杂性转移到您自己的代码上。我可以通过询问针对任何给定体系结构在汇编中编写了多少个浮点库以及为什么它们的行为是实现定义的来反驳您的观点。
Blrfl 2012年

1
@Lundin:62是GCC手册第4节中列出的编译器定义的行为数。由于没有标准的汇编库,因此省去了库定义的需求,可以进行逐个比较。文件要求是§J.3的第一句。自从C89批准以来,我就购买或使用了GCC和少量商业编译器(英特尔,Sun,IBM,波特兰集团)文档,因此,您“最烦恼”的人不会称自己为“合格”。说到标准,如何将采用Intel语法编写的x86组装到具有AT&T语法的汇编程序上,如何为您工作?
Blrfl 2012年

1
@Lundin:谢谢,我的车很棒。方向盘,油门,制动器,离合器和转向信号灯杆均位于标准位置,具有标准性能,其他控件均清晰地标有ISO标准符号。所有实现实现定义的内容,例如娱乐系统,HVAC,导航,巡航控制等,都记录在手套箱的一本胖子里。组装就像我的1973年普利茅斯(Plymouth):没有太多东西,但是以原始形式,它的能力还不及我现在所驾驶的。组装是一样的。复杂性在于您添加的内容。
Blrfl 2012年

1

根据您需要采用的嵌入式方式,C会生成大型,缓慢的程序。这将明显增加该部分产品的成本。整个产品可能只是沧海一粟,也可能会彻底改变产品。是的,有人可能会说软件开发和维护的成本要便宜一些,如果真是太深了,而且其目标是低功耗,小巧而廉价,那么您在谈论的不是很多代码,那么这是对还是错。该代码大部分特定于该供应商或特定芯片,因此使用C语言具有零可移植性优势,无论如何您都必须重写每个目标。有了ARM的cortex-m系列产品,我们现在才开始能够使C与asm竞争,而不是人们没有在嵌入式产品中使用C或其他高级语言,

从专业上讲,C与ASM的争论总是归结为用C编写并在可以证明其合理性的地方使用ASM。您可以证明这一点。在嵌入式世界中,存在性能和尺寸。

您必须在此讨论中包括目标。尽管许多人将C与Microchip一起使用(较老的图片,而不是mips的pic32),却付出了巨大的代价,但对于编译器而言,它是一个可怕的指令集,非常有教育意义和有趣的指令集,但编译器不友好。msp430,avr,arm,thumb,mips对编译器都有利。8051也不错。

甚至超过了语言工具。在担心代码开发和管理成为问题的情况下,Esp需要使用工具来实现今天和明天。从业务角度来看,拥有一个由一组管理的单一源工具,甚至包括一个gcc mod,都是有风险的。您可能会发现不止一个汇编器,而且值得加入该团队的任何人都可以在周末鞭打一个汇编器(只要您编写的汇编不满意,宏也不会高兴)。对于asm和C,您都希望使用开放源代码工具(或您自己的内部工具),尽管机会更多,即使这意味着使用虚拟机运行10年的Linux发行版,也可以使用这些工具产品的寿命。

底线再次使用/学习/教导C和asm,从C开始并在可以证明其合理性的地方使用asm。


这些论点在我看来是过时的。如果您使用的是过去十年编写的现代编译器,那么我相信您将很难编写一个比C程序更有效的汇编程序。除非您使用的是PIC或8051等已有30年历史的恐龙架构,否则无论您做什么都将拥有缓慢的程序……

修复由最现代的gcc和llvm生成的慢速汇编程序是微不足道的。与3.x系列相比,4.x gcc生成的代码更慢,效率更低(对于某些目标,至少是我评估过的目标,例如ARM)。我认为,消除编译器比人做得更好的想法很重要,因为它不是。即使它做到了,也只有在人们知道自己在做什么时,它才会这样做。如果您想有效地使用它们,请“了解您的工具”。以C开头并在需要时使用ASM(如果可以证明的话)...
old_timer 2012年

由于gcc是开源的,所以它是一个奇怪的野兽。也许那个港口做得不好。必须针对特定平台完成所有代码优化,这不是一件容易的事。比较手动汇编程序和该平台的商用编译器的性能会更加公平。

gcc是多目标的,因此平均而言,它做得很好,但对于任何特定目标而言,却做得不好。这就是所期望的。但是您关于现代编译器的观点(过去10年等等)并不成立。就代码产生而言,编译器并没有得到改善,就语言,目标和功能而言,编译器却以代码产生为代价而变得越来越好。任何现代编译器都能实现最佳代码的想法是错误的。非常真实的说,平均而言,它比手工编码的汇编器要好得多,很难使asm中的任何体面大小的项目都比C更好
old_timer 2012年

这就是为什么大多数人都说使用C直到出现问题,然后如果可以证明原因,请在asm中手动修复该问题。您是否真的需要一点点性能提升,是否真的是您的性能问题所在,您是否想在其中使用asm维护该代码,您是否会继续检查每个将来的编译器以查看其输出是否可以修复或减少您的问题?到可接受的水平,等等
old_timer

1

对于汇编,代码可维护性和性能之间不可避免地要折衷。您可以编写易于阅读/维护的程序集,也可以编写高度优化的代码。但是你不能两者都做。

对于C语言,折衷方案并没有完全消失,但它的影响要小得多-您可以编写易于阅读/维护的C语言,并对其进行合理优化。

一个优秀的汇编语言程序员几乎在所有时间都可以击败编译器,但是大多数时候,他们会故意选择编写易于阅读/维护的代码。因此,大多数时候,优秀的汇编语言程序员都会被编译器击败。

明智的方法是同时使用汇编语言和C语言(而不是仅使用汇编语言或仅使用C语言)-例如,对于优秀的汇编语言程序员会选择编写可维护/慢速代码的部分代码,请使用C语言,并在其中使用汇编语言。其余的(实际上是“高度优化且难以维护”的理由)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.