c - 为什么不经常用汇编编写程序?

c - 为什么不经常用汇编编写程序?

32 回答 32

This answer is useful

1930

地狱®,我是一个编译器。

当您阅读这句话时,我刚刚扫描了数千行代码。我浏览了数百万种使用数百种不同的优化技术优化你的单行的可能性,这些技术基于你将花费数年时间进行的大量学术研究。当我将三行循环转换为数千条指令以使其更快时,我不会感到任何尴尬,甚至不会感到轻微的不适。我不耻于进行大量优化或做最肮脏的把戏。如果你不希望我这样做,也许一两天,我会按照你喜欢的方式行事。我可以随时转换我正在使用的方法,甚至无需更改任何一行代码。我什至可以向您展示您的代码在汇编中的外观,如果您愿意,可以在不同的处理器架构和不同的操作系统以及不同的汇编约定中。是的,一切都在几秒钟内。因为,你知道,我可以;你知道,你不能。

PS哦,顺便说一句,您没有使用您编写的一半代码。我帮了你一个忙,把它扔掉了。

于 2010-04-21T18:28:15.003 回答

This answer is useful

331

ASM的易读性很差,与高级语言相比,它并不是真正可维护的。

此外,与其他更流行的语言(例如 C)相比,ASM 开发人员要少得多。

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

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

这个问题的反面是:编译器提供什么功能?

我怀疑您可以/想要/应该比gcc -O3可以更好地优化您的 ASM。

于 2010-04-21T15:41:10.150 回答

This answer is useful

99

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

于 2010-04-21T15:45:21.187 回答

This answer is useful

72

我喜欢用汇编语言编程,但它需要更多的代码来做与高级语言相同的事情,而且代码行数和错误之间存在直接关联。(这在几十年前的The Mythical Man-Month中得到了解释。)

可以将 C 视为“高级程序集”,但如果再往前走几步,您就会进入另一个世界。在 C# 中,您无需三思而后行:

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

这将是几十行甚至上百行的汇编代码,实现它的每个程序员都会采用不同的方法,下一个出现的人必须弄清楚。因此,如果您(和许多人一样)认为程序主要是为其他人阅读而编写的,那么汇编的可读性不如典型的 HLL。

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

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

于 2010-04-21T15:42:50.663 回答

This answer is useful

15

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

程序速度。

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

于 2010-04-21T15:53:02.593 回答

This answer is useful

13

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

即使您可以以相当快的速度手动编写所有这些(请记住,您必须编写的代码是其 8 倍),如果您想更改某些功能会发生什么?从这 100 万条指令中理解你几周前写的东西是一场噩梦!没有模块,没有类,没有面向对象的设计,没有框架,什么都没有。即使是最简单的事情,你也必须编写大量看起来相似的代码,充其量是令人生畏的。

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

于 2010-04-21T15:46:40.573 回答

This answer is useful

8

好吧,我“在过去”写了很多汇编,我可以向你保证,当我用高级语言编写程序时,我的工作效率会更高。

于 2010-04-21T15:43:30.650 回答

This answer is useful

6

合理水平的汇编程序能力是一项有用的技能,特别是如果您从事任何类型的系统级或嵌入式编程工作,与其说是因为您必须编写那么多汇编程序,不如说是因为有时了解盒子真正在做什么很重要. 如果您对汇编程序的概念和问题没有低层次的理解,这可能会非常困难。

但是,实际上在汇编程序中编写了很多代码,原因有几个。

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

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

用汇编程序编写,你必须处理问题的每一个方面,从详细的内存布局、指令选择、算法选择、堆栈管理等。高级语言会从你手中夺走所有这些,这就是为什么在LOC 条款。

本质上,以上所有内容都与您在汇编程序中可用的抽象级别与 C 或其他一些语言有关。汇编程序迫使您进行所有自己的抽象,并通过您自己的自律来维护它们,其中任何中级语言(如 C,尤其是高级语言)为您提供开箱即用的抽象,以及相对容易地创建新的能力。

于 2010-04-21T15:52:38.613 回答

This answer is useful

6

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

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

这是否回答你的问题?;-)

我不会说这话:我正是使用这样的汇编程序和系统进行了编程。更好的是,汇编器可以针对虚拟处理器,并且单独的翻译器为目标平台编译汇编器的输出。与 LLVM 的 IF 类似,但其早期形式比它早了大约 10 年。因此具有可移植性,以及在需要效率的情况下为特定目标汇编器编写例程的能力。

使用该汇编器编写代码的效率与 C 差不多,并且与 GCC-3(在我参与其中时差不多)相比,汇编器/翻译器生成的代码大致一样快,而且通常更小。规模真的很重要,公司的程序员很少,并且愿意在新员工做任何有用的事情之前教他们一门新语言。而且我们有支持,不了解汇编程序的人(例如客户)可以编写 C 语言并为相同的虚拟处理器编译它,使用相同的调用约定等,因此它可以巧妙地接口。所以感觉像是一场边际胜利。

那是在开发汇编技术、库等方面进行了多年的工作。诚然,其中大部分都用于使其可移植,如果它只针对一种架构,那么全唱全跳舞的汇编器会容易得多。

总而言之:你可能不喜欢 C,但这并不意味着使用 C 的努力比想出更好的东西的努力更大。

于 2010-04-21T16:12:36.523 回答

This answer is useful

6

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

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

最后,几乎任何语言都有时间和地点。人们使用他们最熟悉和最高效的东西。汇编程序可能总是在程序员的技能库中占有一席之地,但大多数程序员会发现他们可以用更高效的高级语言编写代码,而且时间要少得多。

于 2010-04-21T18:37:03.463 回答

This answer is useful

5

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

于 2010-04-21T15:45:03.670 回答

This answer is useful

5

同样的原因我们不再去外面的浴室,或者我们不说拉丁语或亚拉姆语。

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

编辑 - 为了停止冒犯他人,我删除了某些词。

于 2010-04-21T15:47:53.603 回答

This answer is useful

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 转换为本地代码(即几乎是汇编程序),使其更加神秘。

于 2010-10-22T17:11:18.737 回答

This answer is useful

3

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

于 2010-04-28T11:35:20.813 回答

This answer is useful

2

我敢肯定有很多原因,但我能想到的两个快速原因是

汇编代码肯定更难阅读(我很肯定它也更耗时)

当您有一个庞大的开发人员团队在开发产品时,将您的代码划分为逻辑块并受接口保护会很有帮助。

于 2010-04-21T15:43:46.500 回答

This answer is useful

2

早期发现之一(您可以在 Brooks 的Mythical Man-Month中找到它,它来自 1960 年代的经验)是人们在每天调试的代码行中使用一种语言或多或少地具有与另一种语言一样的生产力。这显然不是普遍正确的,并且当推得太远时可能会中断,但对于 Brooks 时代的高级语言来说通常是正确的。

因此,获得生产力的最快方法是使用单行代码完成更多功能的语言,并且确实如此,至少对于 FORTRAN 和 COBOL 等复杂的语言,或者给出更现代的示例 C。

于 2010-04-21T15:53:35.353 回答

This answer is useful

2

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

于 2010-04-21T15:53:59.667 回答

This answer is useful

2

随着汇编变得不那么普遍,出现了一个恶性循环:随着高级语言的成熟,汇编语言指令集的构建更少是为了程序员的方便,而更多的是为了编译器的方便。

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

我们的问题现在也大不相同了。1986 年,我试图弄清楚如何从涉及在屏幕上放置几百个像素的小程序中获得更快的速度。我希望动画不那么生涩。汇编语言的一个公平案例。现在我试图弄清楚如何表示围绕合同语言和抵押贷款服务政策的抽象,我宁愿阅读一些看起来接近业务人员所说的语言的东西。与 LISP 宏不同,Assembly 宏不会强制执行太多规则,因此即使您可以在一个好的汇编程序中获得相当接近 DSL 的东西,它也很容易出现各种怪癖。如果我用 Ruby、Boo、Lisp、C# 甚至 F# 编写相同的代码,不会给我带来麻烦。

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

于 2010-04-21T17:09:23.587 回答

This answer is useful

2

同上大多数其他人所说的。

在 C 被发明之前的美好时光里,当唯一的高级语言是 COBOL 和 FORTRAN 之类的东西时,有很多事情如果不求助于汇编程序是不可能完成的。这是获得全部灵活性、能够访问所有设备等的唯一方法。但是后来 C 被发明了,几乎所有在汇编中可能的东西在 C 中都是可能的。从那以后我写的汇编很少然后。

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

于 2010-04-21T17:39:42.210 回答

This answer is useful

2

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

无论如何,我的汇编程序是如此之快。而且我使用汇编的次数越多,编写代码所花费的时间就越少,因为它真的不那么难。此外,关于组件易读性差的评论也是不正确的。如果您正确地标记您的程序并在需要额外详细说明时发表评论,那么您应该一切就绪。事实上,对于程序员来说,汇编更清楚,因为他们看到了处理器级别发生的事情。我不了解其他程序员,但对我来说,我喜欢知道正在发生的事情,而不是在某种黑匣子里。

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

我个人认为市场非常支持高级语言。如果汇编语言是当今唯一存在的语言,那么他们的编程人员将减少约 70%,谁知道我们的世界会在哪里,可能要追溯到 90 年代。高级语言吸引了更广泛的人群。这允许更多的程序员来构建我们世界所需的基础设施。中国和印度等发展中国家从 Java 等语言中受益匪浅。这些国家将快速发展其 IT 基础设施,人们将变得更加相互联系。所以我的观点是,高级语言之所以流行,不是因为它们产生了优秀的代码,而是因为它们有助于满足世界市场的需求。

于 2012-03-03T20:47:08.367 回答

This answer is useful

1

我现在正在 comp org 中学习汇编,虽然它很有趣,但编写起来也非常低效。您必须在脑海中保留更多细节才能使事情正常进行,而且编写相同的东西也很慢. 例如,C++ 中一个简单的 6 行 for 循环可以等于 18 行或更多的汇编代码。

就个人而言,学习硬件级别的工作方式非常有趣,它让我更加了解计算的工作方式。

于 2010-04-21T15:59:34.747 回答

This answer is useful

1

C 比一个好的宏汇编器拥有的是 C 语言。类型检查。循环构造。自动堆栈管理。(几乎)自动变量管理。汇编程序中的动态内存技术是一个巨大的痛苦。与 C 或更好的列表 foo.insert() 相比,正确地做一个链表是非常可怕的。和调试——嗯,什么更容易调试没有争议。HLL 在那里赢得了胜利。

我几乎一半的职业生涯都是在汇编程序中编写的,这让我很容易在汇编程序中思考。它帮助我了解 C 编译器在做什么,这再次帮助我编写 C 编译器可以有效处理的代码。用 C 语言编写的经过深思熟虑的例程可以通过一些工作编写成在汇编程序中准确输出您想要的内容 - 而且它是可移植的!出于跨平台的原因,我已经不得不将一些旧的 asm 例程重写回 C,这并不好玩。

不,我将坚持使用 C 并处理偶尔的性能轻微放缓与我使用 HLL 获得的生产力时间。

于 2010-04-21T17:29:56.010 回答

This answer is useful

1

我只能回答为什么我个人不经常用汇编编写程序,主要原因是这样做比较乏味。另外,我认为在没有立即注意到的情况下更容易出现微妙的错误。例如,您可能会在一个例程中更改使用寄存器的方式,但忘记在某个地方进行更改。它会组装得很好,直到很久以后你才可能注意到。

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

于 2010-04-21T17:46:47.277 回答

This answer is useful

1

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

它几乎可以做所有汇编可以做的事情,它可以是可移植的,并且在大多数罕见的情况下它不能做一些你仍然可以使用嵌入式汇编代码的情况。这只剩下一小部分您绝对需要用汇编语言编写的程序,而除了汇编之外什么都没有。

更高层次的抽象和可移植性使得大多数人用 C 编写系统软件更值得。虽然你现在可能不需要可移植性,如果你投入大量时间和金钱来编写一些程序,你可能不想限制自己在你将来可以使用它的地方。

于 2010-04-23T19:31:04.883 回答

This answer is useful

1

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

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

代替

mov eax, 0x123

add eax, 0x456

push eax

call printInt

你也可以写

B823010000

0556040000

50

FF15.....

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

而你仍然更喜欢汇编程序的原因是其他人更喜欢 C 的原因......

于 2013-02-20T01:52:46.660 回答

This answer is useful

0

因为总是这样:时间流逝,美好的事物也会过去:(

但是当您编写 asm 代码时,感觉与编写高级语言时完全不同,尽管您知道它的效率要低得多。这就像你是一个画家:你可以自由地以你喜欢的方式绘制任何你喜欢的东西,绝对没有任何限制(嗯,仅限于 CPU 功能)......这就是我喜欢它的原因。可惜这种语言消失了。但是,尽管有人仍然记得它并对其进行编码,但它永远不会消亡!

于 2010-04-21T15:53:44.467 回答

This answer is useful

0

$$$

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

高级语言通常更擅长生成大量有用的代码。这并不是说集会没有它的位置,因为有些时候和地方没有别的办法。

于 2010-04-21T15:54:30.887 回答

This answer is useful

0

当您将汇编与比 C 更高级别的语言(例如 Java、Python 或 Ruby)进行比较时,HLL 的优势甚至更大。例如,这些语言都有垃圾收集:无需担心何时释放一块内存,也不会因释放过早而导致内存泄漏或错误。

于 2010-04-21T18:30:21.993 回答

This answer is useful

0

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

“...与 Pascal 等编程语言相比,更好地理解计算机如何在较低级别上真正工作。通过更深入地了解计算机的工作原理,读者通常可以更高效地使用 C 等高级语言开发软件和 C++。学习用汇编语言编程是实现这一目标的绝佳方式。”

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

于 2010-04-21T18:31:21.303 回答

This answer is useful

-2

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

这是一个古老的问题,经常出现,你得到相同的,大多是错误的答案。如果不是为了便携性,我仍然会自己组装所有东西。即使这样,我也几乎像在汇编中那样用 C 语言编写代码。

于 2010-04-22T22:46:39.753 回答

This answer is useful

-6

不同之处在于 - 汇编程序是一门代码艺术,是适当艺术家手中的一幅好画。你比蹩脚的编译器代码更聪明?如果您是,请使用它或使用 c 和汇编程序一起处理您的绘画。

于 2012-06-13T00:28:57.147 回答

This answer is useful

-8

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

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

我很确定美好的一天将会出现其他几种架构,它们也是关于优化(以及关于其他使编程更容易等),它们将能够覆盖更多或其他领域,而我,数据流可以'吨。

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

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

于 2013-02-19T12:25:01.330 回答