在大会中学习的关键概念

时间:2008-09-28 22:25:00

标签: theory assembly

我坚信,从学习一门新语言中获得的最重要的事情之一不是如何使用新语言,而是从中获得的概念知识。我不是说你认为大会是多么重要或有用,如果我从未在任何真实的项目中使用它,我也不在乎。

我想知道的是,您认为大会的哪些概念对于任何一般程序员来说都是最重要的?它不必与Assembly直接相关 - 它也可能是你认为典型的程序员在高级语言中花费所有时间不会理解或理所当然的事情,例如CPU缓存。

9 个答案:

答案 0 :(得分:7)

注册分配和管理

汇编让您非常了解CPU可以同时处理多少变量(机器字大小的整数)。如果你可以打破你的循环,使它们只涉及一些临时变量,它们都将适合寄存器。如果没有,你的循环会在事情被换成内存时缓慢运行。

这对我的C编码真的有帮助。我尽量使用尽可能少的意大利面条,使所有的环都变得紧凑而简单。

x86是愚蠢的

学习几种汇编语言让我意识到x86指令集是多么蹩脚。可变长度指令?很难预测时间?非正交寻址模式?啊。

如果我们都运行MIPS,我认为,甚至是ARM或PowerPC,那么世界会更好:-)或者更确切地说,如果英特尔/ AMD利用其半导体专业知识并用它来制造多核,超快速,超 - 使用MIPS处理器代替x86处理器,并具备所有这些优点。

答案 1 :(得分:5)

我认为汇编语言可以教你很多小事,还有一些大概念。

我将在这里列出一些我能想到的东西,但是没有任何东西可以替代学习和使用x86和RISC指令集。

您可能认为整数运算最快。如果要查找整数的整数平方根(即floor(sqrt(i))),最好使用仅整数近似例程,对吗?

罗。数学协处理器(在x86上)有一个 fsqrt 指令。转换为float,取平方根,再次转换为int比全整数算法更快。

然后有一些东西,比如访问你可以遵循的内存,但是没有正确的推荐,直到你钻研到汇编。假设您有一个链表,并且列表中的第一个元素包含您需要经常访问的变量。该列表很少重新排序。好吧,每次需要访问该变量时,需要将指针加载到列表中的第一个元素,然后使用它,加载变量(假设您不能在使用之间将变量的地址保存在寄存器中) 。如果您将变量存储在列表之外,则只需要一次加载操作。

当然在这里节省几个周期,这些天通常不重要。但是如果你打算编写需要快速编写的代码,这种知识既可以应用于内联汇编,也可以应用于其他语言。

调用约定怎么样? (有些汇编程序会为你处理这个问题 - 真正的程序员不会使用它们。)调用者或被调用者是否清理堆栈?你甚至使用堆栈?您可以在寄存器中传递值 - 但由于有趣的x86指令集,最好在某些寄存器中传递某些内容。哪些寄存器将被保留? C编译器无法真正优化的一件事就是调用。

有一些小技巧,比如推送一个返回地址然后JMPing到一个程序;当程序返回时,它将转到PUSHed地址。这种偏离通常的函数调用思维方式是另一种“启蒙状态”。如果您曾经设计过具有创新功能的编程语言,那么您应该了解硬件能够实现的有趣内容。

汇编语言知识可以教您有关计算机安全性的特定于体系结构的知识。如何利用缓冲区溢出,或者进入内核模式,以及如何防止此类攻击。

然后是自修改代码的超低温,以及作为相关问题的机制,例如重定位和将补丁应用于代码(这也需要调查机器代码)。

但所有这些都需要正确的思想。如果你是那种可以放

的人
while(x--)
{
  ...
}

一旦你了解它的作用就会很好用,但会发现很难弄清楚它自己做了什么,那么汇编语言可能会浪费你的时间。

答案 2 :(得分:4)

了解汇编语言是为了更好地了解计算机如何在“引擎盖下”工作,这很好,当你调试一些东西时它会有所帮助,所有调试器都可以给你一个汇编代码清单,在至少让你有机会弄清楚问题可能是什么。但是,尝试将低级知识应用于高级编程语言,例如尝试利用CPU如何缓存指令然后编写不稳定的高级代码以强制编译器生成超高效的机器代码,可能是你正试图微观优化的迹象。在大多数情况下,通常最好不要试图超越编译器,除非你需要性能增益,在这种情况下,你也可以在汇编中编写这些位。

因此,为了更好地理解事物的工作原理,了解汇编是件好事,但所获得的知识并不一定直接适用于您在高级语言中编写代码的方式。然而,在那个问题上,我发现学习函数调用如何在汇编代码级工作(了解堆栈和相关寄存器,了解参数如何在堆栈上传递,学习自动存储如何工作等)更容易理解我在高级代码中遇到的问题,例如“堆栈空间不足”错误和“无效调用约定”错误。

答案 3 :(得分:3)

最重要的概念是SIMD,以及它的创造性使用。正确使用SIMD可以在各种各样的应用程序中提供巨大的性能优势,从字符串处理到视频处理到矩阵数学。在这里,你可以比纯C代码提高 10倍的性能提升 - 这就是为什么程序集仅在调试之后仍然有用。

我工作的项目中的一些示例(所有数字都是Core 2上的时钟周期计数):

反向8x8 H.264 DCT(频率变换):

c: 1332
mmx: 187
sse2: 127

8x8色度运动补偿(双线性插值滤波器):

c: 639
mmx: 144
sse2: 110
ssse3: 79

4 16x16绝对差值运算之和(运动搜索):

c: 3948
mmx: 278
sse2: 231
ssse3: 215

(是的,没错 - 比C快18倍!)

16x16块的均方误差:

c: 1013
mmx: 193
sse2: 131

16x16块的差异:

c: 783
mmx: 171
sse2: 106

答案 4 :(得分:2)

内存,寄存器,跳转,循环,移位以及可在汇编程序中执行的各种操作。我不会错过调试汇编语言类程序的日子 - 它们很痛苦! - 但它确实给了我一个很好的基础。

我们忘记了(或者从来不知道)我们今天使用的所有这些花哨的东西(我喜欢的东西!)归结为最终所有这些东西。

现在,我们当然可以在不了解汇编程序的情况下获得丰富而有利可图的职业,但我认为这些概念很有用。

答案 5 :(得分:1)

我会说在汇编中学习递归和循环教会了我很多。它让我理解了我正在使用的语言的编译器/解释器如何将事物推送到堆栈中的基本概念,并在需要时弹出它们。我还学会了如何利用臭名昭着的堆栈溢出。 (使用一些get-和put-命令在C语言中仍然令人惊讶地容易)。

除了在日常情况下使用asm之外,我认为我不会使用汇编教会我的任何概念。

答案 6 :(得分:0)

如今,x86 asm不是CPU的直接线,而是更多的API。你编写的汇编程序操作码本身被编译成一个完全不同的指令集,重新排列,重写,修复并且通常被破坏得无法识别。

因此,学习汇编程序并不能让您从根本上了解CPU内部的情况。恕我直言,比学习汇编程序更重要的是要很好地理解目标CPU和内存层次结构的工作原理。

This系列文章非常详尽地介绍了后一个主题。

答案 7 :(得分:0)

我想说寻址模式非常重要。

我的母校把这种情况推向极端,因为x86没有足够的,我们在PDP11的模拟器上研究了一切,其中至少有7个我记得。回想起来,这是一个不错的选择。

答案 8 :(得分:0)

定时

快速执行:

  • 并行处理
  • 简单说明
  • 查询表
  • 分支预测,流水线

快速减缓对存储的访问:

  • 寄存器
  • 缓存和各种级别的缓存
  • 内存堆和堆栈
  • 虚拟内存
  • 外部I / O