首页 文章

为什么不经常在汇编中编写程序? [关闭]

提问于
浏览
217

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

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

也许是因为汇编编程与HLL完全不同,因此需要不同的思维,方法和方法,这使得为不熟悉的程序编程看起来很尴尬,因此给它编写程序的坏名称 .

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

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

30 回答

  • 0

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

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

  • 2

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

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

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

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

  • 0

    $$$

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

    更高级别的语言通常更好地生成大量有用的代码 . 这并不是说汇编没有它的位置,因为有些时间和地方没有别的办法 .

  • 1

    其中一个早期发现(你是神话人月,来自20世纪60年代的经验)是人们在一种语言中或多或少地在一种语言中与另一种语言一样,在每天调试的代码行中 . 这显然不是't universally true, and can breaks when pushed too far, but it was generally true of the high-level languages of Brooks'时间 .

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

  • 333

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

  • 72

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

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

    更高级别的抽象和可移植性使得大多数人在C语言中编写系统软件更有 Value . 尽管如果你在编写某些程序时花费了大量的时间和金钱,现在可能不需要可移植性,你可能不想限制自己在将来你将能够使用它 .

  • 8

    与更高级别的语言相比,ASM具有 poor legibilityisn't really maintainable .

    此外,还有很多 fewer ASM developers 比其他更流行的语言,如C.

    此外,如果您使用更高级别的语言和 new ASM instructions become available (例如SSE),您只需更新编译器,旧代码就可以轻松使用新指令 .

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

    与此问题相反的是:编译器提供哪些功能?

    我怀疑你能否/希望/优化你的ASM比 gcc -O3 更好 .

  • 2

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

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

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

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

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

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

  • 5

    如果一个普通的 生产环境 程序说100k行代码,每行约8-12个汇编指令,那就是100万个汇编指令 .

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

    此外,您几乎不能像高级语言那样优化代码 . 例如,由于你描述了你的意图,而不仅是你的代码,在汇编程序中你只编写代码,因此C语言会执行疯狂的优化次数,汇编程序可以在编写时可靠地优化你修补和修补的100万条指令 .

  • 99

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

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

    编辑 - 为了停止违法的人,我删除了某些单词 .

  • 13

    为什么?简单 .

    比较一下:

    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转换为本机代码(即几乎是汇编程序),使其更加密码化 .

  • 5

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

    • 汇编代码肯定难以阅读(我很肯定它写起来也比较耗时)

    • 当您拥有庞大的开发人员团队时,将代码划分为逻辑块并受接口保护会很有帮助 .

  • 6

    Hell®,我是编译器 .

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

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

  • 15

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

  • 2

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

  • 1

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

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

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

  • 6

    我现在正在学习comp org中的汇编,虽然它很有趣,但写入它也是非常低效的 . 你必须在头脑中保留更多细节以使事情正常工作,并且编写相同的东西也会更慢 . 例如,C中的循环的简单6行可以等于18行或更多的汇编 .

    就个人而言,它有很多有趣的东西可以学习如何在硬件层面上工作,并且让我更加了解计算的工作原理 .

  • 2

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

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

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

    但是,如果您的问题很容易用高效的汇编语言表达,那么对您来说更有力量 .

  • 1

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

    你为什么一开始在Assembler写作?为什么不用真正的低级语言编写程序呢?

    代替

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

    你也可以写

    B823010000
    0556040000
    50 
    FF15.....
    

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

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

  • 2

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

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

  • 1

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

  • 1932

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

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

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

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

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

    这就是在开发汇编技术,库等方面需要多年的工作 . 不可否认,其中大部分都是为了便携,如果它只是针对一个架构,那么全能的全能舞蹈汇编程序会更容易 .

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

  • 0

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

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

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

  • 0

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

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

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

  • 6

    正如其他人之前提到的,任何工具存在的原因都在于它的工作效率 . 由于HLL可以完成与许多asm代码行相同的工作,我猜它是C语言中的内联汇编和其他语言的变体 . Paul Carter博士在PC Assembly Language中说道

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

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

  • -2

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

  • 1

    我只能回答为什么我个人不愿意这样做 . 我只能回答这个问题 . 另外,我认为这是 easier to get things subtly wrong 没有立即注意到 . 例如,您可能会改变在一个例程中使用寄存器的方式,但忘记在一个地方更改它 . 它组装好了,你可能要到很晚才注意到 .

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

  • 3

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

  • 4

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

    程序速度 .

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

  • 2

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

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

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

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

    • 用汇编语言编写,你必须处理问题的每一个方面,从详细的内存布局,指令选择,算法选择,堆栈管理等 . 更高级别的语言可以让你远离你,这就是为什么这么多密集在LOC方面 .

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

相关问题