汇编编程如何帮助实现优化
答案 0 :(得分:14)
汇编编程最有可能改进代码的方法是改进你:教你更多关于低级别发生的事情并获得优化的规则可以帮助你做出正确的决策高级语言。
至于实际帮助一个项目:正如其他人已经指出的那样,它很少值得。您可以将它用作一种高级配置文件驱动的优化:尝试多种变体,直到找到最适合您特定问题的变体。
从这开始:用C或C ++编写程序或者你通常使用的任何编译语言,启动你的调试器,并反汇编一个小但非平凡的函数,并考虑编译器为什么做它所做的事情。然后尝试自己编写一小部分内联汇编程序。在现代系统中,装配很容易嵌入C中,而不是从头开始。
或者,或者像PIC那样买一台小机器,让它闪烁一个LED ......
答案 1 :(得分:7)
现在,你必须非常善于组装以击败编译器。
我可以在一周中的任何一天进行,但只能先查看编译器的输出。
然后,如果它增加超过几个百分点,我会感到惊讶。
现在,我只是在编译器不能做某事时才进行汇编编程。
答案 2 :(得分:5)
原则上,您可以在汇编中编写高度优化的代码,因为编译器仅限于适用于许多程序的特定通用优化,而您可以创造性地使用您对此特定程序的了解。
举一个简单的例子,当我刚接触这个业务时,编译器在优化寄存器使用方面的能力非常有限。您知道要执行任何类型的算术或逻辑运算,CPU通常必须将其中一个值加载到寄存器中,然后在另一个上执行操作,然后保存结果?喜欢将两个数字加在一起 - 我将在这里使用伪汇编程序,因为我不知道你知道哪些汇编语言,而且我自己也忘记了大部分细节 - 你会写这样的东西:< / p>
LOAD A,value1
ADD A,value2
STORE a,destination
用于为每个操作生成负载的编译器。所以如果你的C程序说:
x=x+y;
z=z+x;
编译器会生成如下内容:
LOAD A,x
ADD A,y
STORE A,x
LOAD A,z
ADD A,x
STORE A,z
但是人类可以观察到,当我们到达第二个语句时,寄存器A已经包含x,并且加法是可交换的,所以我们可以将其优化为:
LOAD A,x
ADD A,y
STORE A,x
ADD A,z
STORE A,z
等等。人们可以经历各种微小的微观优化。在我年轻的时候,我曾经一直这样做,世界是绿色的。
但是多年来编译器变得更加智能,CPU变得更加强大,因此微优化并不重要。
因此,我还没有编写任何汇编语言代码,哇,大概15年。我曾经在调试时读取编译器生成的汇编,有时它会给出一个微妙问题的线索,但我现在也没有这么做了。
我认为编译器甚至不再用汇编编写。相反,你在其他计算机上用高级语言编写了编译器的初稿,即你编写了一个交叉编译器来实现自己。
我怀疑今天唯一真正使用的装配是针对极端受限的环境,嵌入式系统等等;以及必须与硬件密切配合的程序,如设备驱动程序。
我很想知道这个论坛上是否有任何汇编程序员关心告诉我们汇编程序员的原因。
答案 3 :(得分:2)
汇编编程本身不会优化代码。汇编的主要内容是它允许您进行非常低级别的访问,并准确选择处理器执行的指令。
由于您没有为您生成程序集的编译器,因此您可以在自己编写程序时执行代码优化(如果您知道如何)。
答案 4 :(得分:2)
那么,您认为自己比gcc
优化编译器更聪明吗?
如果没有,那就大声说吧(为了更好地进行优化,学习装配)。这类似于学习Scheme
语言以便在递归方面做得更好:)
答案 5 :(得分:2)
我唯一能想到使用汇编语言来优化代码的时候就是需要一些非常具体的东西,比如你需要微控制器上的GPIO来高低切换 正好 每9个时钟周期。使用中断管理的时间太短,而更高级别的语言编译器通常不会对指令流提供这种控制。
答案 6 :(得分:2)
通常,编译器在生成最佳代码方面会做得相当不错。但是,编写自己的程序集可能会导致代码更加优化(在空间和/或速度方面)。
通常情况下,当您知道编译器没有的目标系统时会发生这种情况。编译器设计用于各种系统;如果你想利用你的目标系统独有的东西,有时你必须自己去做。这是一个例子。几个月前,我正在为基于MIPS的嵌入式系统编写一些代码。有许多不同类型的MIPS CPU,有些支持某些操作码,而其他操作码则不支持。我的编译器将使用所有MIPS架构支持的汇编操作集生成MIPS代码。但是,我知道我的芯片可以做得更多。我有一个子程序,需要计算32位数字中前导零的数量。编译器将其合成为一个循环,需要大约10行组装。我通过使用旨在实现此目的的CLZ
操作码重新编写了一行。我知道我的芯片支持操作码,但编译器没有。不可否认,这种情况并不常见;然而,当它们弹出时,在组装中有足够的背景以利用它们是很好的。
答案 7 :(得分:2)
有时需要执行一项特别适合某些CPU指令的任务,但不适合任何高级语言结构。例如,在许多处理器上,可以使用以下内容轻松执行扩展精度算术:
add r0,r4 addc r1,r5 addc r2,r6 addc r3,r7
这将r3:r2:r1:r0和r7:r6:r5:r4视为数字四个字长,将第二个字添加到第一个字。四个很好的简单说明,任何了解装配的人都会知道他们做了什么。我知道没有办法在C中执行相同的任务,不仅它不仅生成更大更慢的目标代码,而且还是一个难以理解的源代码混乱。
一个更极端但更专业的现实示例:给定两个数组array1 [0..63]和array2 [0..63],计算array1 [0] * array2 [0] + array1 [1] * array2 [1] + array1 [2] * array2 [2] ... + array1 [63] * array2 [63]。在我使用的DSP上,计算可以在大约75个机器周期中的机器代码中完成(其中大约67个是重复的MAC指令)。 C代码无法靠近任何地方。
答案 8 :(得分:1)
通常你不会在程序集中编程。您可以在C中编程,然后查看生成的程序集以查看C编译器自动进行的优化(或不进行)。调整C代码(例如允许更好的矢量化)将允许编译器更好地重新安排代码,这将为您提供优化的程序集
答案 9 :(得分:1)
曾经有一本非常好的关于这个主题的书,名为Inner Loops by Rick Booth。我仍然认为这是一本非常有价值的书,因为它可以提高你对优化汇编代码时要注意什么的意识(指令的分类非常快,快,慢;当两条指令可以并行执行时;内存对齐,缓存错过,失速,罚款等等。)然而,本书仅涉及Pentium Pro / Pentium MMX的英特尔处理器,而且随着现有的新硬件架构,这本书现已相当过时。
这正是优化汇编语言的问题:您需要非常了解您所定位的架构;将其与可以针对不同平台的优化编译器(例如,对于C语言)进行对比,并且将相应地应用优化。许多知识和工作已经进入编译器的优化阶段,你必须先研究一个特定的架构才能击败一个好的编译器。
答案 10 :(得分:0)
更有可能在编写汇编代码时击败编译器。了解典型任务如何转换为汇编可能有助于您编写更好的高级语言代码。
通常,您不会求助于程序集以进行优化。如果可以的话,通常有人已经提供了可供您调用的基本代码,例如以线性代数库的形式。
同样,程序集提供了对处理器的直接访问(例如,用于原子性,时间测量,I / O),但是已经可以使用高级语言访问重要的访问。
答案 11 :(得分:0)
编译器可以很好地生成汇编程序。
然而,有一个错误的原因,为什么手写汇编程序更快。由于写起来比较难,所以你写的就少了。
如果程序员能够在最小的代码中完成同样的工作,而不管语言如何,那将是很好的。
答案 12 :(得分:0)
在编写汇编时,甚至只是汇编器输出的直接原始字节时,您可以编写使用计算机硬件特定功能的程序,或者制作其他非常仔细指定的内容。
如果你的程序比其他任何东西更频繁地完成优化部分,那么可能会有很大的好处。 在尝试优化之前始终设置基准。
结果是你的手写组件在较少的不同硬件上工作。它甚至可能最终被限制在硬件模型和版本中!
您很少能够或者需要编写汇编程序,因为通常编写的软件几乎可以在您找到的每个硬件和您的小猫上工作。
如果你知道装配,有一个有趣的应用。然后,您可以编写生成程序集例程的程序。虽然它只是有趣,除非你保持它很小,所以你可以轻松移植它。
答案 13 :(得分:0)
答案 14 :(得分:0)
答案 15 :(得分:0)