为什么不经常在汇编中编写程序?

时间:2010-04-21 15:39:17

标签: c programming-languages assembly

似乎主流意见认为汇编编程需要更长时间并且比C等更高级别的语言更难编程。因此,似乎建议或假设用更高级别的语言编写更好由于这些原因以及更好的便携性。

最近我一直在写x86程序集,我突然意识到这些原因可能不是真的,除了可移植性。也许这更多的是熟悉并且知道如何很好地编写装配。我还注意到汇编中的编程与HLL中的编程完全不同。也许一个优秀且经验丰富的汇编程序员可以像经验丰富的C程序员用C语言一样轻松快速地编写程序。

也许是因为汇编编程与HLL完全不同,因此需要不同的思维,方法和方法,这使得为不熟悉的程序编程似乎非常尴尬,因此给它编写程序的坏名称。

如果可移植性不是问题,那么真的,C会对NASM等好的汇编程序有什么影响?

修改: 只是要指出。在汇编时编写时,不必只是在指令代码中编写。您可以使用宏和过程以及您自己的约定来进行各种抽象,以使程序更加模块化,更易于维护和更易于阅读。这就是熟悉如何编写良好汇编的地方。

32 个答案:

答案 0 :(得分:1932)

Hell®,我是编译器。

我在阅读这句话时只扫描了数千行代码。我根据您将花费数年时间进行的大量学术研究,使用数百种不同的优化技术浏览了数百种优化单行产品的可能性。当我将三行循环转换为数千条指令以使其更快时,我不会感到任何尴尬,甚至不是轻微的ick。我不遗余力地进行大量的优化或做最肮脏的技巧。如果你不想要我,也许一两天,我会按照你喜欢的方式行事。我可以随时转换我正在使用的方法,甚至不用改变代码的一行。我甚至可以向您展示您的代码在汇编,不同处理器架构和不同操作系统以及不同的汇编约定中的外观(如果您愿意)。是的,几秒钟内完成。因为,你知道,我可以;而且你知道,你做不到。

P.S。哦,顺便说一句,你没有使用你编写的一半代码。我帮了你一个忙,把它丢了。

答案 1 :(得分:332)

与高级语言相比,ASM 可读性差无法维护

此外,还有很多较少的ASM开发人员,而不是其他更流行的语言,例如C.

此外,如果您使用更高级别的语言并且新的ASM指令可用(例如SSE),您只需要更新编译器,您的旧代码就可以轻松地使用新的指令。

如果下一个CPU有两倍的寄存器怎么办?

这个问题的反面是:编译器提供了哪些功能?

我怀疑你/可能/想要优化你的ASM比gcc -O3能更好。

答案 2 :(得分:99)

我为6502,Z80,6809和8086芯片编写了大量的汇编程序。一旦C编译器可用于我正在处理的平台,我就会停止这样做,并且立即变得至少提高了10倍。大多数优秀的程序员出于合理的原因使用他们使用的工具。

答案 3 :(得分:72)

我喜欢使用汇编语言进行编程,但是需要更多代码来执行与高级语言相同的操作,并且代码行和错误之间存在直接关联。 (几十年前在The Mythical Man-Month中解释过这一点。)

可以将C视为“高级装配”,但要比上面几步,你就处于一个不同的世界。在C#中,你不会三思而后行:

foreach (string s in listOfStrings) { /* do stuff */ }

这将是几十个,也许是数百行代码的汇编,每个程序员实现它将采取不同的方法,而下一个人出现将不得不弄明白。因此,如果你相信(尽可能多)程序主要是为其他人阅读而编写的,那么程序集的可读性就低于典型的HLL。

编辑:我积累了一个用于常见任务的个人代码库,以及用于实现类C控制结构的宏。但是当我成为常态时,我在90年代碰壁了。太多的时间花在了常规的事情上。

几年前,ASM必不可少的最后一项任务是编写代码来对抗恶意软件。没有用户界面,所以这是没有膨胀的所有有趣的部分。

答案 4 :(得分:15)

除了其他人的可读性,可维护性,更短的代码以及更少的错误以及更容易的答案之外,我还会添加一个额外的原因:

程序速度。

是的,在汇编中,您可以手动调整代码以充分利用每个最后一个周期,并使其尽可能快地完成。但谁有时间?如果你编写一个不完全愚蠢的C程序,编译器将很好地为你做优化。可能需要手动完成至少95%的优化,而不必担心跟踪其中的任何优化。这里肯定有一个90/10的规则,其中最后5%的优化将最终占用95%的时间。那么为什么要这么麻烦呢?

答案 5 :(得分:13)

如果一个普通的生产程序说100k行代码,并且每行大约是8-12个汇编指令,那将是100万个汇编指令。

即使您可以以合适的速度手动编写所有这些(请记住,它的代码是您必须编写的8倍),如果您想要更改某些功能会发生什么?几个星期前你在这100万条指令中理解你所写的东西是一场噩梦!没有模块,没有类,没有面向对象的设计,没有框架,没有任何东西。即使是最简单的事情,你必须编写的类似代码的数量也是令人生畏的。

此外,您无法像高级语言那样优化代码。例如,由于你描述你的意图,而不仅仅是你的代码,在汇编程序中你只编写代码,因此汇编程序无法真正对你的代码执行任何值得注意的优化,其中C执行疯狂的优化次数。你写的是你得到的,相信我,你不能可靠地优化你编写它时修补和修补的100万条指令。

答案 6 :(得分:8)

我过去一直在写很多集会,我可以向你保证,当我用高级语言编写程序时,我会更有效率。

答案 7 :(得分:6)

合理水平的汇编程序能力是一项有用的技能,特别是如果你在任何系统级别或嵌入式编程工作,而不是因为你必须编写那么多的汇编程序,但是因为有时候理解这个框是什么很重要是真的在做什么。如果您对汇编器概念和问题没有低级别的了解,那么这可能非常困难。

然而,至于在汇编程序中实际编写大量代码,有几个原因并没有做太多。

  • 根本没有(几乎)需要。除了非常早期的系统初始化以及隐藏在C函数或宏中的一些汇编程序片段之外,所有可能曾经用汇编语言编写的非常低级的代码都可以用C或C ++编写而没有任何困难。

  • 更高级语言(甚至C和C ++)中的代码将功能集中到更少的行中,并且有大量研究表明错误的数量与源代码行数相关。也就是说,在汇编程序和C中解决的同样问题将在汇编程序中出现更多错误,因为它更长。同样的论点促使人们转向更高级别的语言,如Perl,Python等。

  • 在汇编程序中编写时,您必须处理问题的每个方面,包括详细的内存布局,指令选择,算法选择,堆栈管理等。更高级别的语言会将所有这些都从您身边带走,这是为什么LOC的密度如此之高。

基本上,上述所有内容都与汇编程序与C或其他语言中可用的抽象级别有关。汇编程序强迫您完成所有自己的抽象,并通过自己的自律来维护它们,其中任何中级语言(如C语言,尤其是更高级语言)为您提供开箱即用的抽象,以及能够相对容易地创造新的。

答案 8 :(得分:6)

作为一名将大部分时间都花在嵌入式编程领域的开发人员,我认为汇编远非死亡/过时的语言。存在一定的接近金属级别的编码(例如,在驱动程序中),有时无法在更高级别的语言中准确或有效地表达。我们在汇编程序中编写了几乎所有的硬件接口例程。

话虽这么说,这个汇编代码被包装,以便可以从C代码调用它,并被视为库。出于多种原因,我们不会在程序集中编写整个程序。首要的是便携性;我们的代码库用于使用不同体系结构的多个产品,我们希望最大化可以在它们之间共享的代码量。其次是开发人员熟悉。简而言之,学校不像过去那样教授装配,而且我们的开发人员在C方面的工作效率远远高于装配方式。此外,我们有可用于我们的C代码的各种“附加功能”(如库,调试器,静态分析工具等),这些代码不适用于汇编语言代码。即使我们想编写一个纯汇编程序,我们也无法编写,因为几个关键的硬件库只能作为C库使用。从某种意义上说,这是一个鸡/蛋问题。由于没有尽可能多的库和开发/调试工具,人们被驱逐出组装,但libs /工具不存在,因为没有足够的人使用汇编来保证创建它们的努力。

最后,几乎任何语言都有时间和地点。人们使用他们最熟悉和最富有成效的东西。在程序员的汇编程序中可能总会有一个位置,但大多数程序员会发现他们可以用更高级别的语言编写代码,而这种语言在很短的时间内几乎同样有效。

答案 9 :(得分:6)

当你在汇编时写作时,你不必只用指令代码写。您可以使用宏和过程以及您自己的约定来进行各种抽象,以使程序更模块化,更易于维护和更易于阅读。

所以你基本上说的是,通过熟练使用复杂的汇编程序,你可以使你的ASM代码越来越接近C(或者你自己发明的另一种低级语言),直到最终你和C程序员一样富有成效。

这会回答你的问题吗? ; - )

我没有说这句话:我已经使用这样的汇编程序和系统进行了编程。更好的是,汇编程序可以定位虚拟处理器,并且单独的转换器为目标平台编译汇编程序的输出。与LLVM的IF一样,但在其早期形式中约会10年。因此具有可移植性,以及为特定目标合并器编写例程的能力。

使用该汇编程序进行编写与C一样高效,并且通过与GCC-3(我参与其中时)相比较,汇编程序/转换程序生成的代码大致同样快,通常更小。规模非常重要,该公司的程序员很少,并愿意在新员工做任何有用的事情之前教新员工。我们得到了备份,那些不了解汇编程序的人(例如客户)可以编写C并使用相同的调用约定等编译它来使用相同的虚拟处理器,以便它能够整齐地连接。所以这感觉就像是一场微不足道的胜利。

在开发汇编技术,库等方面需要多年的工作。不可否认的是,如果它只是针对一个架构,那么其中大部分都是可移植的,那么全能的全能舞蹈汇编器就会容易得多。

总结:你可能不喜欢C,但这并不意味着使用C的努力大于提出更好的东西的努力。

答案 10 :(得分:5)

组装在不同的微处理器之间不可移植。

答案 11 :(得分:5)

我们不再去外面的浴室,或者为什么我们不说拉丁语或亚拉姆语。

技术出现并使事情变得更容易和更容易获取。

编辑 - 为了停止犯罪的人,我删除了某些词语。

答案 12 :(得分:4)

为什么呢?简单。

比较一下:

        for (var i = 1; i <= 100; i++)
        {
            if (i % 3 == 0)
                Console.Write("Fizz");
            if (i % 5 == 0)
                Console.Write("Buzz");
            if (i % 3 != 0 && i % 5 != 0)
                Console.Write(i);
            Console.WriteLine();
        }

.locals init (
    [0] int32 i)
L_0000: ldc.i4.1 
L_0001: stloc.0 
L_0002: br.s L_003b
L_0004: ldloc.0 
L_0005: ldc.i4.3 
L_0006: rem 
L_0007: brtrue.s L_0013
L_0009: ldstr "Fizz"
L_000e: call void [mscorlib]System.Console::Write(string)
L_0013: ldloc.0 
L_0014: ldc.i4.5 
L_0015: rem 
L_0016: brtrue.s L_0022
L_0018: ldstr "Buzz"
L_001d: call void [mscorlib]System.Console::Write(string)
L_0022: ldloc.0 
L_0023: ldc.i4.3 
L_0024: rem 
L_0025: brfalse.s L_0032
L_0027: ldloc.0 
L_0028: ldc.i4.5 
L_0029: rem 
L_002a: brfalse.s L_0032
L_002c: ldloc.0 
L_002d: call void [mscorlib]System.Console::Write(int32)
L_0032: call void [mscorlib]System.Console::WriteLine()
L_0037: ldloc.0 
L_0038: ldc.i4.1 
L_0039: add 
L_003a: stloc.0 
L_003b: ldloc.0 
L_003c: ldc.i4.s 100
L_003e: ble.s L_0004
L_0040: ret 

它们的特征相同。 第二个甚至不是汇编程序,而是.NET IL(中间语言,类似于Java的字节码)。第二次编译将IL转换为本机代码(即几乎是汇编程序),使其更加隐秘。

答案 13 :(得分:3)

我猜甚至x86(_64)上的ASM在你通过利用编译器难以优化的指令获得大量收益的情况下也是有意义的。例如,x264使用大量的asm进行编码,速度提升很大。

答案 14 :(得分:2)

我现在已经在装配编程大约一个月了。我经常在C中编写一段代码,然后将其编译为汇编以帮助我。也许我没有利用C编译器的全部优化功能,但似乎我的C asm源包含不必要的操作。所以我开始看到一个好的C编译器的表现优于一个好的汇编编码器并不总是正确的。

无论如何,我的装配程序非常快。而且我使用汇编越多,我写出代码的时间就越少,因为它真的不那么难。关于组装易读性差的评论也是不正确的。如果您正确地标记您的程序并在需要进一步详细说明时进行注释,则应该全部设置。事实上,程序员对程序集更清晰,因为他们正在看到处理器级别正在发生的事情。我不了解其他程序员,但对我来说,我喜欢知道发生了什么,而不是处于某种黑盒子里。

据说,编译器的真正优势在于编译器可以理解模式和关系,然后在源中的适当位置自动编码。一个流行的例子是C ++中的虚函数,它要求编译器优化映射函数指针。但是编译器仅限于执行编译器的制造商允许编译器执行的操作。这导致程序员有时不得不诉诸于他们的代码做奇怪的事情,增加编码时间,当他们可以通过汇编完成。

我个人认为市场大力支持高级语言。如果汇编语言是当今唯一存在的语言,那么他们的编程人数将减少约70%,谁知道我们的世界会在哪里,可能早在90年代。更高级别的语言吸引更广泛的人群。这允许更多的程序员供应来构建我们世界所需的基础设施。像中国和印度这样的发展中国家受益于像Java这样的语言。这些国家将快速发展其IT基础设施,人们将变得更加互联。所以我的观点是高级语言很受欢迎,不是因为它们产生了优越的代码,而是因为它们有助于满足世界市场的需求。

答案 15 :(得分:2)

与其他人所说的大部分内容相同。

在C发明之前的好时光,当唯一的高级语言是像COBOL和FORTRAN这样的东西时,有很多东西在没有使用汇编程序的情况下是不可能完成的。这是获得全方位灵活性,能够访问所有设备等的唯一方法。但是C被发明了,几乎所有可能在装配中的任何东西都可能在C中。我写了很少的装配,因为然后

那就是说,我认为对于新程序员学习用汇编语言编写来说这是一个非常有用的练习。不是因为他们实际上会使用它太多,而是因为那样你才能理解计算机内部真正发生的事情。我已经看到很多编程错误和来自程序员的低效代码,他们显然不知道比特,字节和寄存器到底发生了什么。

答案 16 :(得分:2)

由于程序集变得不那么普遍,所以存在一个恶性循环:随着高级语言的成熟,汇编语言指令集的构建不仅为程序员提供了方便,而且为编译器的便利性而增加。

所以现在,实际上,可能很难做出正确的决定,例如,您应该使用哪些寄存器或哪些指令稍微更高效。编译器可以使用启发式算法来确定哪些权衡可能具有最佳收益。我们可以通过较小的问题思考并找到可能超过我们现在非常复杂的编译器的局部优化,但是在一般情况下,一个好的编译器在第一次尝试时会比一个优秀的程序员可能会做得更好。最终,像约翰亨利一样,我们可能会击败机器,但我们可能会严重焚烧自己到达那里。

我们的问题现在也完全不同了。 1986年,我试图弄清楚如何通过在屏幕上放置几百个像素的小程序来获得更高的速度;我希望动画不那么生涩。汇编语言的公平案例。现在我想弄清楚如何用抵押合同语言和服务商政策来表示抽象,我宁愿读一些看起来接近商业人士所说语言的东西。与LISP宏不同,汇编宏不会在规则方面强制执行,因此即使你能够在一个好的汇编器中得到一些合理接近DSL的东西,它也会容易出现各种各样的怪癖。如果我在Ruby,Boo,Lisp,C#甚至F#中编写相同的代码,都会给我带来问题。

如果您的问题很容易以高效的汇编语言表达,那么,您将获得更多权力。

答案 17 :(得分:2)

可移植性总是一个问题 - 如果不是现在,至少最终。编程行业每年花费数十亿美元来移植旧软件,这些软件在编写时“显然”没有任何可移植性问题。

答案 18 :(得分:2)

早期发现之一(你会在布鲁克斯的神话人月中找到它,这来自20世纪60年代的经验)是人们在一种语言中或多或少的生产力另一种是每天调试的代码行。这显然不是普遍真实的,并且在被推得太远时可能会中断,但对于布鲁克斯时代的高级语言来说通常是正确的。

因此,提高工作效率的最快方法是使用一个单独的代码行做得更多的语言,这确实有用,至少对于像FORTRAN和COBOL这样复杂的语言,或者给出一个更现代的例子C.

答案 19 :(得分:2)

我确信有很多原因,但我能想到的两个原因很简单

  1. 汇编代码肯定难以阅读(我很乐意写它也比较费时)。
  2. 当您拥有庞大的开发人员团队时,将代码划分为逻辑块并受接口保护是有帮助的。

答案 20 :(得分:1)

C对一个好的宏汇编程序的作用是语言C.类型检查。循环结构。自动堆栈管理。 (几乎)自动变量管理。汇编程序中的动态内存技术是一个巨大的痛苦。正确地执行链接列表与C相比可能是可怕的,或者更好的是列出foo.insert()。和调试 - 好吧,没有比较容易调试的比赛。 HLL在那里赢得了胜利。

我编写了近一半的汇编程序,这使我很容易在assmebler中思考。它帮助我看到C编译器正在做什么,这再次帮助我编写C编译器可以有效处理的代码。用C语言编写的经过深思熟虑的例程可以编写,只需要一点点工作就可以输出你想要的汇编程序 - 并且它是可移植的!出于跨平台的原因,我已经不得不将一些较旧的asm例程重写回C,这并不好玩。

不,我会坚持用C来处理偶然的​​性能轻微下降与HLL获得的生产力时间。

答案 21 :(得分:1)

我正在学习comp org中的汇编,虽然它很有意思,但写入它也是非常低效的。你必须在头脑中保留更多细节以使事情正常工作,而且写入速度也慢同样的事情。例如,C ++中一个简单的6行循环可以等于18行或更多的汇编。

就个人而言,它很有趣,可以了解硬件级别的工作原理,并让我更加了解计算的工作原理。

答案 22 :(得分:1)

我只能回答为什么我个人不经常在汇编中编写程序,主要原因是更乏味。此外,我认为在没有立即注意的情况下,更容易让事情巧妙地错误。例如,您可能会改变在一个例程中使用寄存器的方式,但忘记在一个地方更改它。它会组装得很好,你可能要到很晚才注意到。

那就是说,我认为仍有有效的装配用途。例如,我有许多非常优化的汇编程序用于处理大量数据,使用SIMD并遵循偏执的“每一点都是神圣的”[引用V.Stob]方法。 (但请注意,天真的程序集实现通常比编译器为您生成的更糟糕。)

答案 23 :(得分:1)

C是一个宏汇编程序!这是最好的一个!

它可以做几乎所有装配都可以,它可以是便携式的,并且在大多数罕见的情况下它无法做某事你仍然可以使用嵌入式汇编代码。这只留下了你绝对需要在汇编中编写的一小部分程序,而只需要汇编。

更高级别的抽象和可移植性使得大多数人在C语言中编写系统软件更有价值。虽然如果你花了很多时间和金钱来编写一些你可能不想要的程序,你现在可能不需要移植性限制自己将来可以使用它。

答案 24 :(得分:1)

人们似乎忘记了另一个方向。

为什么你首先在Assembler中写作?为什么不用真正的低级语言编写程序呢?

而不是

mov eax, 0x123
add eax, 0x456
push eax
call printInt

你也可以写

B823010000
0556040000
50 
FF15.....

具有很多许多的优点,你知道你的程序的确切大小,你可以重复使用指令的值作为其他指令的输入,你甚至不需要汇编程序来编写它,你可以使用任何文本编辑器...

你仍然更喜欢Assembler的原因,是其他人更喜欢C的原因......

答案 25 :(得分:0)

$$$

一家公司聘请开发人员帮助将代码转换为$$$。生成有用代码的速度越快,公司将代码转换为$$$的速度就越快。

更高级别的语言通常可以更好地生成大量有用的代码。这并不是说大会没有它的位置,因为有时候和其他地方都没有。

答案 26 :(得分:0)

当您将汇编语言与C语言比较高级语言进行比较时,HLL的优势甚至更大。 Java或Python或Ruby。例如,这些语言具有垃圾收集:无需担心何时释放大量内存,并且由于过早释放而没有内存泄漏或错误。

答案 27 :(得分:0)

正如其他人之前提到的,任何工具存在的原因都在于它的工作效率。由于HLL可以完成与许多asm代码行相同的工作,我想组装被其他语言取代是很自然的。对于接近硬件的摆弄 - 根据语言,C和其他变体的内联汇编。   Paul Carter博士在PC Assembly Language

中说
  

“...更好地理解如何   计算机真的工作在较低的水平   比编程语言更像   帕斯卡尔。通过获得更深层次   了解计算机的工作原理,   读者往往可以更多   高效的开发软件   更高级的语言,如C和   C ++。学习装配程序   语言是一种很好的方式   实现这一目标。“

我们在大学课程中介绍了装配。它有助于清除概念。但是我怀疑我们中的任何人都会在汇编中编写90%的代码。今天深入的装配知识有多重要?

答案 28 :(得分:0)

因为它总是这样:时间过去和好事也消失了:(

但是当你编写asm代码时,它与编写高级代码时的感觉完全不同,尽管你知道它的效率要低得多。这就像你是一个画家:你可以随心所欲地画出你喜欢的任何东西,完全没有限制(好吧,只有CPU功能)...这就是我喜欢它的原因。遗憾的是这种语言消失了。但是,虽然有人仍然记得并编码,但它永远不会死!

答案 29 :(得分:-2)

翻阅这些答案,我敢打赌9/10的响应者从未使用过汇编。

这是一个古老的问题,每隔一段时间就出现一次,你会得到相同的,大多是错误的答案。如果它不是为了便携性,我仍然会自己做所有的装配。即便如此,我在C中的编码几乎就像我在汇编中所做的那样。

答案 30 :(得分:-6)

不同之处在于 - 汇编程序是一种代码艺术,是一个适当的艺术家手中的好画。你比糟糕的编译器代码更聪明?如果你是,使用它或用c和汇编器一起照顾你的画作。

答案 31 :(得分:-8)

呵呵,我是一个数据流系统。这个我正在运行的应用程序,充满了各种各样的组件。它是一个分布式应用程序,它位于3台计算机上,位于功能强大的x86和两个较小的ARM上。大多数组件都是用C ++编写的,但是在ASM中为x86编写了一个关键的组件。此外,大多数组件有几种变体:针对不同的处理器进行编译,还有一些组件具有特殊的GPU版本。遗憾与否,我有一个脚本组件(一个包装器组件调用脚本),它打印报告,但每年只打印一次。它甚至不会伤害它只是一个脚本,一个缓慢的脚本。

作为智能数据流应用程序,我知道,我的架构仅适用于某些任务,其中信号/数据通过图形流动,例如自动化,视频/图像处理,音频处理(所有合成器使用数据流)但幸运的是,这些应用领域非常强大,其中优化是必不可少的。

我非常确定在一个美好的日子会出现其他几个架构,这也是关于优化(以及其他一些使编程更容易等等),并且它们将能够涵盖更多或其他领域,我,数据流不能。

因此,“C vs ASM”主题不是一个真正的困境。这就像争论数字或模拟合成器更好(正如我所提到的,我已经融入了合成器)。我建议,制作好音乐。或听。随你。 C不是与ASM相对的。无论如何,我从未见过被ASM攻击的C程序,反之亦然。

对不起英语不好,尽管我不是一个新的技术,但我并不广为人知,我还是个孩子。有前途的。来吧,看看我的profile