要成为一名优秀的程序员,是否有必要了解硬件方面的情况?


24

我是一个自学成才的程序员,以防万一CS 101中回答了这个问题。

似乎在遇到麻烦编程时,我总是碰壁。例如,我只是在另一个论坛上问了一个问题,该问题是如何处理函数返回的数组指针。最初,我以为我只是不了解C ++的设计人员为应对这种情况而设置的适当技术。但是,从随后的回答和讨论中,我发现当事情“归还”时,我并没有真正明白会发生什么。

一个好的程序员必须对编程过程有多深的理解?


3
我的建议:学习一些x86程序集(DOS或其他方式)。然后学习阅读一些C小代码的汇编输出。如果您不理解输出,请提问。重复。这将迫使您了解CPU级别的情况
Earlz 2011年


Earlz-您的意思是我应该学习使用x86指令集进行编程吗?那是“ CPU级别”吗?
2011年

Job-thx,那很有趣。实际上,他犯了一些错误,仅是仅供参考。
2011年

Answers:


33

否。没有人了解硬件方面的情况。

计算机系统就像洋葱一样-有很多层,每一层都取决于它下面的层作为支撑。如果您是在外层之一上工作的人,则不要太在意洋葱中间发生的事情。那是一件好事,因为洋葱的中间总是在变化。只要支持您的特定图层的一个或多个图层继续看起来相同并支持您的图层,就可以了。

但话又说回来...

是。我的意思是,您不需要了解洋葱内部的实际情况,但是对于典型洋葱内部的心理模型很有帮助。也许不是最深的部分,即由晶体管等构成的门,或者下一两层,即具有微码,时钟,指令解码单元等的下一层。不过,下一层是有寄存器,堆栈和堆。这些是最深的层,您会对发生的事情有很大的影响-编译器将您的代码转换为在此级别上运行的指令,如果您愿意,通常可以单步执行这些指令并找出“真正的”情况。

大多数经验丰富的程序员在脑海中都会略有童话般的层次。它们可以帮助您理解编译器在告诉您“无效的地址异常”或“堆栈溢出错误”之类的内容时在谈论什么。

如果您有兴趣,请阅读有关计算机体系结构的书。它甚至不必是一本特别的新书-长期以来,数字计算机一直以几乎相同的方式工作。您对洋葱的内部了解得越多,您就会惊讶于所有这些东西都起作用!学习(大约)底层的操作将使编程既不那么神秘,也更神奇。真的,更有趣。

您可能要注意的另一件事是嵌入洋葱。嗯,我的意思是嵌入式系统。有许多易于使用的嵌入式平台:ArduinoBASIC Stamp是两个示例。这些基本上是具有许多内置功能的小型微处理器。您可以将它们视为洋葱,其层数比典型的台式PC少,因此可以从硬件到软件,对整个系统中发生的事情有一个透彻的了解。


2
谢谢。这基本上回答了我的问题。我是一名电子工程师,他已经完成了寄存器,加法器,多路复用器等的芯片级(即晶体管级)设计,所以我获得了最低级(除非我们在谈论量子力学)。我也可以使用我熟悉的语言。在中间层(堆栈,堆),我只是有一个很大的差距,您可以说编译器在此工作。正如您所说的那样,既然我希望我的编程经验是“少一点神秘,而...更多些神奇”。看来我应该研究仍然未知的水平。
2011年

@bev:在这种情况下,您确实应该检查一下像Arduino这样的平台。
迦勒

很抱歉,我很迟钝,但是我签出了Arduino,但我真的看不出它的使用方式如何帮助我理解编译器如何不同地对待指针和数组。我没看到什么?
2011年

@bev:如果您只是想了解函数的调用方式,则可能需要花费30分钟的时间来阅读并完成操作。如果您想更好地了解所有事情如何协同工作,那么使用小型系统将是最简单的。这是一次将整个洋葱放入脑中的最佳方法。AVR是Arduino所基于的芯片家族,它是一个不错的,通用的,易于使用的系统,其指令集足够小,无需太多麻烦即可学习。
Caleb

喔好吧。主页对其产品的那方面有些模糊。我再看一次
2011年

10

您不是在谈论硬件级别,而是在谈论编译器实际执行的功能以及您要执行的操作。

您最肯定需要具备一定的了解水平,以便找出在不明显的地方出了什么问题,尤其是在处理内存阻塞情况时。


洛伦-是的!感谢简单的事实。现在,我需要找出学习c ++编译器如何处理其数据类型的最佳方法。顺便说一句,作为EE,我知道这实际上不是硬件级别。我只是不知道您的CS怪才怎么称呼它。(仍然不是这个问题。编译器级别?)
2011年

顺便说一句-内存脚?
2011年

@Bev:您只是在这里证明了我的意思-如果您什至不知道是什么原因,那么您将很难找到一个错误。内存重踩是指某些东西写入到它不应该写的位置,并擦除(踩到)发生的任何事情。如果幸运的话,击中的任何东西都会立即变得至关重要,至少会炸毁。如果您不走运,该程序只会在数据中留下一些漏洞。
洛伦·佩希特尔

感谢您的澄清。它还显示了我不知道的多少,因为据我所知,我只是在没有更好的控制的情况下写到堆或堆栈中。
2011年

@Bev:问题出在当您写某处而不认为自己在写的时候。您在堆栈上有东西,并指向它。您离开了例程-项消失了,指针没有消失。现在,当您写入该指针时会发生什么?或者您有100个项目的数组-当您写入项目#200时会发生什么?
罗伦·佩希特尔

6

了解程序存储器!=了解硬件

了解内存层次结构==了解硬件


要回答您的一般性问题:这取决于。了解硬件不会有什么坏处,但是了解硬件并不能在所有情况下都有用。

根据您的示例,您只需要了解有关在运行程序时如何划分内存以及如何组织内存的更多信息。在这方面,了解硬件将无济于事,因为由于虚拟内存的神奇作用,内存(对于程序可见)甚至无法真正代表硬件。

如果您根据访问内存的顺序对性能问题感到好奇,现在您将受益于了解硬件,内存层次结构,高速缓存未命中,页面错误以及所有来自硬件的美好特性。


占星师-目前我还不担心性能问题。很快,希望如此。感谢您的评论。
2011年

5

如果您确实决定学习一些汇编程序,则可能应该在Commodore 64(当然是模拟的)上学习诸如6502汇编程序,或者在Amiga上学习诸如68000。

您可以在此处对Commodore 64有所了解...

http://thepiratebay.org/torrent/4609238/Tag3-Saal2-Slot16_00--ID2874-the_ultimate_commodore_64_talk-Main

这里描述的经典的一切您需要知道的书...

http://reprog.wordpress.com/2010/03/12/programming-books-part-3-programming-the-commodore-64/

如果环顾四周,您可能会找到PDF扫描。

IMO,6502比Z80更容易,而68000比8086更容易-更常规的指令集等。

但是CPU只是硬件的一个方面。而且,现代CPU是完全不同的野兽,即使从编译器的角度来看,它所做的事情也是透明的-例如提供虚拟地址空间。

C64上的6502的一个特殊优势是,不仅CPU简单,而且使用硬件也很容易破解。我以前在玩SID音乐芯片时玩得很开心。

所以-如果您不花太多时间在它上面,那可能是一个值得的练习。在Commodore Basic之后的14岁左右,我学习了6502汇编程序作为第二语言。但是大多数情况下,它都具有非常简单的工作模型,因此您可以在不引起任何误解的情况下向其添加更复杂的想法。

您可以在汇编程序中学习一些有用的东西...

  • CPU寄存器的工作方式。
  • 内存寻址如何工作,包括间接寻址。
  • CPU堆栈的工作方式。
  • 位逻辑的工作原理。
  • CPU如何控制I / O设备。
  • 中断的工作方式。

我建议这样做的一个特殊原因是,可以更好地了解简单步骤完全确定性地,机械地,完全地在没有智能或常识的情况下进行操作的方式。基本上以最纯粹和最顽固的无知形式习惯了命令式执行模型。

但是,现在准确地了解大多数这些事情到底有多有用,这是一个难题。

您不会学到的一件事是如何在记忆层次结构中表现良好。那些旧机器大多具有简单的内存模型,没有缓存层,也没有虚拟内存。您也不会对并发学到很多东西-它们当然是处理并发的方法,但这主要意味着中断。您无需担心互斥锁等。

有时,关于这些东西曾经如何工作或汇编程序如何工作的思维模型甚至可能会产生误导。例如,将C指针视为地址可能导致未定义的行为问题。AC指针通常以包含地址的整数的形式实现,但不能保证绝对是正确的。例如,在某些奇怪的平台上,不同的指针可能指向不同的地址空间。当您想使用两个指针进行算术或按位逻辑时,这变得很重要。

除非您拥有这些离奇的平台之一,否则您可能不会认为自己在乎这一点-但如今的编译器越来越有可能利用未定义标准的行为来进行优化。

因此,系统体系结构的思维模型可能会有用,但是对语言规范进行编码仍然很重要,而不是对您的语言和平台可能不尊重的假设模型进行编码。

最后,从了解编译器如何生成代码的思想中获得了许多有用的思维模型知识-现代语言的代码生成与当时可用的相当琐碎的编译器有很大不同。

这是我最喜欢的一本书...

http://dickgrune.com/Books/MCD_1st_Edition/

除了有关解析和AST等内容外,它还涵盖了用于多种语言范例(命令式,OOP,功能,逻辑,并行和分布式)以及内存管理的代码生成。如果您想了解多态方法调用的工作原理而又不陷入CPU指令集的详细信息,那么像这样的书就是您的朋友-而且即将发布新版本。


史蒂夫-哇。对于您对我问题的回答的完整性和重点,我几乎无言以对。非常感谢您抽出宝贵的时间写这本书。我一定会接受你的建议。
2011年

1
我建议PDP-11汇编程序比上面提到的所有其他汇编程序都要好学习。所有其他人所教导的是由更有限的硬件资源和/或更有限的硬件设计和前瞻性所施加的限制。就像一个太常见的8051系列之类的东西,可以说明编程模型在如此有限的硬件上有多么奇怪(例如,史蒂夫提到不同的地址空间就发挥了作用)。
格雷格·伍兹

@Greg-恐怕我从来没有玩过PDP-11。也没有8051-我做了一段时间的嵌入式工作,但是那是使用8096系列芯片。我只是在这里看看-很有趣。一段时间之前,我听说过哈佛架构,但我不知道有什么类似的东西非常流行并且仍在使用。
2012年

4

二十年前,它很重要,但现在不那么重要-软件和现代硬件之间有更多的抽象层。

知道需要多个线程以利用多个内核或使用比系统上现有内存更多的内存是一件坏事,这很有用,但除此之外,除非编写这些抽象是您的工作,否则您实际上并不需要它。层。

您剩下的问题表明,您可能更关心编译器,而不是硬件,这有所不同。您可能会遇到很重要的情况,但是这些情况要么是琐碎的事情(无限递归不能很好地工作),要么是您可能会感觉很好解决但可能永远不会遇到相同问题的边缘情况再次。


是的,您是对的,我更关心编译器。另外,感谢您对多个线程,多个内核等的建议。它已放入我的toLearn注释文件中。
2011年

@bev多线程很容易学习,除非确实需要,否则就不要这样做。根据我的经验,麻烦多于其价值。
Skeith,2011年

@Skeith-感谢您的提示。我会记住的。
2011年

4

它对了解和理解硬件提供的抽象有很多帮助,而对于如何创建这种幻觉也有一些一般性的想法-但要真正了解现代硬件的真正工作原理,您需要做大量的工作。很可能只会看到最小的回报。

如果您可以原谅小小的转移:这让我想起了几年前我注意到的事情。几十年前(直到1970年代末),大多数人认为计算机离魔术只有一步之遥-几乎不受物理定律的影响,能够处理几乎没有任何实际意义的各种事物,等等。当时,我花了很多时间(几乎没有成功)试图说服人们,他们不是魔术。它们确实是相当普通的机器,可以非常快速,可靠地完成有限的工作,但在其他方面却非常平凡。

如今,大多数人对计算机的看法已经改变。现在他们已经很普通了,以至于很多非常普通的人对它们有了实际的了解。举例来说,前几天我吃晚饭时,我看到/听到一个侍应生在休息时讨论她应该在新计算机上得到什么。他给出的建议是完全合理和现实的。

我对计算机的看法也发生了变化。我去过热门芯片,在那之前的微处理器论坛可以追溯到1990年代中期。我大概知道更多关于微处理器硬件比程序员的至少99% -而且知道我做什么,我会说:他们是平凡了。他们险些破门物理定律。我已经做了很多低级测试,我可以肯定地说一遍:超越CPU产生的幻觉,进入展示硬件真正工作方式的层次通常非常困难。我希望我可以用不低于4个逻辑分析仪将计算机埋在电缆下面的方式发布其中一种设置的图片,以正确地测量一个 高速缓存在现代CPU上如何工作的一个方面(更不用说一些真正的精挑细选的程序设计,以确保我们测量的内容恰好是CPU在做什么,而没有其他内容)。


杰里-感谢您的评论。作为一名EE,我比某些更高的抽象级别更适应晶体管级别。我真的只是想知道我要成为一名优秀的C ++程序员需要知道什么。
2011年

那张照片听起来很有趣。你为什么不能发布它?
梅森惠勒

@Bev:要真正成为一名优秀的程序员,您实际上不需要了解晶体管方面的任何知识。这些抽象的存在是有原因的,您几乎总是可以将低于机器代码/汇编的抽象级别的任何内容视为完全无关紧要的,只是假设它可以工作。
梅森惠勒

@MasonWheeler:我把它带到了以前工作的地方,但是由于我不再在那里工作了,因此访问它可能会有些困难(可能并非没有可能,尽管我辞职了,但即使如此。 ..)
杰里·科芬

1

不同的语言在不同的硬件抽象层次上工作。C和C ++是非常底层的。另一方面,脚本语言要求您对底层细节了解较少。

但是,我仍然要说,在所有情况下,您了解的越多,您将成为一名更好的程序员。编程的一部分是能够同时兼顾多个抽象级别。

如果您使用C ++进行编程,则至少在编译器的工作抽象水平上,您需要对现代CPU的工作方式有很好的了解。(CPU内部也发生了一些对编译器透明的事情)。


斯科特-“对现代CPU的工作原理有很好的了解。”,您是说数字逻辑如何工作(例如,卡诺图,真值表,与/或/或非/异或门的工作方式)?或者您是说编译器直接使用什么资源(即寄存器)?
2011年

了解更多是件好事。但是,真正的窍门是知道哪种“更多”将为您带来最大的收益。例如,在几乎无法预测编译器将使用哪些指令的情况下,了解指令时序将不会有用。学习如何使用分析器可能会带来更好的成本/收益比。
Steve314

1
@bev-不,我认为您不需要下降到登机口。如果您只知道基本架构(内存,总线,CPU),如何加载指令,执行指令,存储结果等,那么您可能就可以了。您还需要了解编译器如何布置程序的内存空间,包括其如何使用堆栈和堆。
Scott Whitlock

@ScottWhitlock-谢谢-这只是我一直在寻找的特定建议。
2011年

0

我想谈一谈有关C之类的高级语言的总体设计。

总的来说,我认为可以肯定地说这样的语言可以看作是实现一种抽象机器,确实,这就是Dennis Ritchie自己描述C的方式以及C的抽象机的特殊设计如何使其成为更具移植性的语言。这样,对计算机体系结构和机器级别的功能有所了解,对于理解语言的抽象机器也将非常有帮助。

我记得DMR的论文《 C程序和UNIX系统的可移植性》是讨论C语言(抽象)机器模型的第一篇。

我认为DMR关于C的历史和发展的论文在显示真实硬件如何影响语言设计方面也非常有用,并且也许也是早期编程语言设计的典范: C语言的发展


当您是新手时,您似乎认为这是一个论坛,但肯定不是。您对问题的答案不应成为您要添加的要点,而应归于评论,而答案应尝试直接作为对问题的全面答案。就是说,您说的很对,这对主题信息很有用,如果您可以在那几行中直接回答这个问题,并附上解释,那将是很好的。您在这里分享的很酷的信息。欢迎程序员!
Jimmy Hoffa 2012年

注释没有版本化,并且不是永久的,因此对于添加到一组答案中毫无用处。大多数张贴者也倾向于忽略使用评论来更新他们的答案,并且大多数答案未标记为“社区Wiki”答案,因此其他人无法以保持对后续贡献者某些归属的方式对其进行编辑。 。此外,这个特定问题已经开始进行真正的讨论,无论是否喜欢,这都是其中的一些方式。试图将所有贡献强加到一个模型中是stackexchange概念的主要失败。
格雷格·伍兹

顺便说一句,我确实隐含地回答了OP中的一个真实问题:一个人应该对硬件有足够的了解,以便能够将抽象机器建模为语言设计的核心。
格雷格·伍兹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.