use*_*896 43 embedded assembly cpu-architecture
在过去的3到5年里,我一直在C和CPython工作.考虑一下我的知识基础.
如果我要使用汇编指令(如MOV AL, 61h支持它的处理器),处理器内部究竟是什么解释此代码并将其作为电压信号发送?如何进行如此简单的指导?
当我试着想到包含MOV AL, 61h甚至包含的众多步骤时,大会甚至感觉像是一种高级语言XOR EAX, EBX.
编辑:我读了一些评论,询问为什么我把它作为嵌入式,当x86系列在嵌入式系统中不常见时.欢迎来到我自己的无知.现在我想,如果我对此一无所知,也有可能其他人也对此一无所知.
考虑到你们在答案中付出的努力,我很难选择一个最喜欢的答案,但我觉得有必要做出决定.没有伤害感情,伙计们.
我经常发现,我对计算机的了解越多,我就越不会意识到我真正知道的.感谢您对微码和晶体管逻辑的开放态度!
编辑#2:感谢这个帖子,我刚刚理解了为什么XOR EAX, EAX比这更快MOV EAX, 0h.:)
old*_*mer 35
我最近开始阅读Charles Petzold的一本名为Code的书,这本书到目前为止涵盖了我认为你很好奇的事情.但在购买/借款之前,我还没有完全通过这本书.
这是我相对较短的答案,而不是Petzolds ......并且希望与你的好奇心一致.
你听说过我假设的晶体管.使用晶体管的最初方式是晶体管收音机.它基本上是一个放大器,将微小的无线电信号漂浮在空气中并将其馈入晶体管的输入端,从而打开或关闭其旁边电路上的电流.并且你用更高的功率连接该电路,这样你就可以接收一个非常小的信号,将其放大并将其馈入扬声器,然后收听广播电台(还有更多信息隔离频率并保持晶体管平衡,但是你得到了我希望的想法.
现在晶体管存在导致使用晶体管作为开关,如灯开关.收音机就像一个调光灯开关,你可以把它从一路转到任何地方.一个非调光灯开关全部开启或全部关闭,开关中间有一些神奇的地方可以转换.我们在数字电子产品中使用相同的晶体管.取一个晶体管的输出并将其馈入另一个晶体管输入.第一个输出肯定不是像无线电波那样的小信号,它会强制第二个晶体管一直开启或完全关闭.这导致了TTL或晶体管 - 晶体管逻辑的概念.基本上你有一个驱动高电压的晶体管或者叫它为1,然后在它上面吸一个零电压,让我们称之为0.并且您使用其他电子设备安排输入,以便您可以创建AND门(如果两个输入均为1,则输出为1),或门(如果一个或另一个输入为1,则输出为1) .逆变器,NAND,门,NOR门(一个或带有一个逆变器)等.曾经有一个TTL手册,您可以购买8个左右的引脚芯片,其中有一个或两个或四个某种门(NAND,NOR, AND,等)内部功能,两个输入和每个输出.现在我们不需要那些用数百万个晶体管创建可编程逻辑或专用芯片更便宜的产品.但我们仍然考虑用于硬件设计的AND,OR和NOT门.(通常更像nand和nor).或门(如果一个或另一个输入为1则输出为1).逆变器,NAND,门,NOR门(一个或带有一个逆变器)等.曾经有一个TTL手册,您可以购买8个左右的引脚芯片,其中有一个或两个或四个某种门(NAND,NOR, AND,等)内部功能,两个输入和每个输出.现在我们不需要那些用数百万个晶体管创建可编程逻辑或专用芯片更便宜的产品.但我们仍然考虑用于硬件设计的AND,OR和NOT门.(通常更像nand和nor).或门(如果一个或另一个输入为1则输出为1).逆变器,NAND,门,NOR门(一个或带有一个逆变器)等.曾经有一个TTL手册,您可以购买8个左右的引脚芯片,其中有一个或两个或四个某种门(NAND,NOR, AND,等)内部功能,两个输入和每个输出.现在我们不需要那些用数百万个晶体管创建可编程逻辑或专用芯片更便宜的产品.但我们仍然考虑用于硬件设计的AND,OR和NOT门.(通常更像nand和nor).现在我们不需要那些用数百万个晶体管创建可编程逻辑或专用芯片更便宜的产品.但我们仍然考虑用于硬件设计的AND,OR和NOT门.(通常更像nand和nor).现在我们不需要那些用数百万个晶体管创建可编程逻辑或专用芯片更便宜的产品.但我们仍然考虑用于硬件设计的AND,OR和NOT门.(通常更像nand和nor).
我不知道他们现在教的是什么,但概念是相同的,对于内存,触发器可以被认为是这些TTL对中的两个(NANDS)连接在一起,一个输出到另一个的输入.让我们离开吧.这基本上是我们称之为SRAM或静态RAM的单个位.sram基本上需要4个晶体管.Dram或动态ram您放入计算机的记忆棒自己每位拿一个晶体管,所以对于初学者你可以看到为什么dram是你买千兆字节的东西.只要力量没有消失,Sram位就会记住你设置它们的内容.Dram开始忘记你告诉它时你告诉它的东西,基本上dram以第三种不同的方式使用晶体管,有一些电容(如电容器,这里不会进入),就像一个微型可充电电池,一旦充电并拔下充电器,它就会开始耗尽.想想一个架子上的一排眼镜,每个玻璃上都有小洞,这些是你的戏剧位,你想要它们中的一些,所以你有一个助手填满你想成为一个的眼镜.那个助手必须不断地填满投手并沿着这条排下去并保持"一"位眼镜足够用水,并让"零"位眼镜保持空白.因此,在任何时候你想看看你的数据是什么,你可以查看并通过寻找肯定高于中间水位的水位来读取零和零水平肯定低于中间的水位为零.所以甚至打开电源,如果助手不能保持足够的眼镜足以告诉一个人从零开始,那么他们最终都会看起来像零并且排出.它是每芯片更多位的权衡.这里的简短故事就是在处理器之外我们使用dram作为我们的大容量内存,并且有一个辅助逻辑,负责保持一个零和零.但是在芯片内部,AX寄存器和DS寄存器例如使用触发器或sram来保存数据.对于您知道的每个位,例如AX寄存器中的位,可能有数百或数千或更多用于将位进出该AX寄存器的位.并且有辅助逻辑,负责保持一个零和零.但是在芯片内部,AX寄存器和DS寄存器例如使用触发器或sram来保存数据.对于您知道的每个位,例如AX寄存器中的位,可能有数百或数千或更多用于将位进出该AX寄存器的位.并且有辅助逻辑,负责保持一个零和零.但是在芯片内部,AX寄存器和DS寄存器例如使用触发器或sram来保存数据.对于您知道的每个位,例如AX寄存器中的位,可能有数百或数千或更多用于将位进出该AX寄存器的位.
你知道处理器以某种时钟速度运行,现在大约2千兆赫兹或每秒20亿个时钟.想想时钟,这是由晶体产生的,另一个主题,但逻辑看到时钟作为一个电压,在这个时钟速率2ghz或其他任何时候变为高和零高和零(游戏进程为17mhz,旧的ipods约为75mhz,原装ibm pc 4.77mhz).
因此,用作开关的晶体管使我们能够将电压转换为硬件工程师和软件工程师熟悉的1和0,并且甚至可以为我们提供AND,OR和NOT逻辑功能.我们拥有这些神奇的晶体,可以让我们获得准确的电压振荡.
所以我们现在可以做一些事情,比如说,如果时钟是一个,我的状态变量说我处于提取指令状态,那么我需要切换一些门,以便我想要的指令的地址,这是在程序计数器,在内存总线上输出,这样内存逻辑可以给我指示MOV AL,61h.您可以在x86手册中查看,并发现其中一些操作码位表示这是一个mov操作,目标是EAX寄存器的低8位,mov的源是一个立即值,这意味着它在此指令后位于内存位置.所以我们需要在某处保存该指令/操作码,并在下一个时钟周期获取下一个存储单元.所以现在我们已经保存了电影,
你问这一切怎么样?想想一个python函数执行一些数学公式.你开始用一些输入的公式,来作为变量的程序的顶部,你必须通过该程序可能从库等,并在底部添加一个常数这里,或致电平方根函数的各个步骤回答答案.硬件逻辑做了同样的方式,今天的编程语言使用其中一个看起来很像C.主要的区别是你的硬件功能可能会投入数百或数千,输出是一个位.在每个时钟周期,AL寄存器的位0使用巨大的算法计算,具体取决于您想要查看的距离.想想你为数学运算调用的平方根函数,该函数本身就是其中一些输入产生一个输出,它可能会调用其他函数可能是乘法或除法.所以你可能有一点你可以想到的是AL寄存器的第0位之前的最后一步,它的功能是:如果时钟是1则AL [0] = AL_next [0]; 否则AL [0] = AL [0]; 但是有一个更高的函数,包含从其他输入计算的下一个位,更高的函数和更高的函数,其中大部分是由编译器创建的,就像你的三行python可以变成数百或数千汇编行.几行HDL可以成为数百或数千或更多的晶体管.硬件人员通常不会查看特定位的最低级别公式,以找出所有可能的输入和所有可能的AND,OR和NOT,它们可能比您可能检查程序生成的汇编程序更多地计算.但如果你愿意,你可以.
关于微码的说明,大多数处理器不使用微码.例如,你使用x86进入它,因为它是当时的一个很好的指令集,但表面上很难跟上现代的步伐.其他指令集不需要微编码并直接以我上面描述的方式使用逻辑.您可以将微编码视为使用不同的指令集/汇编语言的不同处理器,该语言模拟您在表面上看到的指令集.没有像你试图在Windows上的mac或linux上模拟窗口那么复杂.微编码层是专门为工作而设计的,你可能会想到只有四个寄存器AX,BX,CX,DX,但那里内心更多.当然,一个汇编程序可以在一个核心或多个核心中的多个执行路径上执行.就像闹钟或洗衣机中的处理器一样,微码程序既简单又小巧,可以调试并烧录到硬件中,希望永远不需要更新固件.至少理想情况下.但是就像你的ipod或手机一样,你有时会想要一个bug修复或其他什么,并且有一种方法可以升级你的处理器(BIOS或其他软件在启动时加载一个补丁).假设您将电池盒打开到电视遥控器或计算器,您可能会看到一个洞,在那里您可以看到一排裸露的金属触点,可能是三个或五个或多个.对于某些遥控器和计算器,如果您真的想要重新编程,请更新固件.通常不是,理想情况下,遥控器是完美的或完美的,足以超过电视机.微码提供了在市场上获得非常复杂的产品(数百万,数亿个晶体管)的能力,并在未来的道路上修复大的和可修复的错误.想象一下,你的团队在18个月内编写了一个2亿线的python程序并且必须交付它,否则公司将无法参加比赛产品.同样的事情,除了你可以在现场更新的代码的一小部分,其余的必须保持刻在石头上.对于闹钟或烤面包机,如果有一个错误或该东西需要帮助你只需把它扔出去另一个.市场上有数亿个晶体管,并在未来的路上修复了大量可修复的漏洞.想象一下,你的团队在18个月内编写了一个2亿线的python程序并且必须交付它,否则公司将无法参加比赛产品.同样的事情,除了你可以在现场更新的代码的一小部分,其余的必须保持刻在石头上.对于闹钟或烤面包机,如果有一个错误或该东西需要帮助你只需把它扔出去另一个.市场上有数亿个晶体管,并在未来的路上修复了大量可修复的漏洞.想象一下,你的团队在18个月内编写了一个2亿线的python程序并且必须交付它,否则公司将无法参加比赛产品.同样的事情,除了你可以在现场更新的代码的一小部分,其余的必须保持刻在石头上.对于闹钟或烤面包机,如果有一个错误或该东西需要帮助你只需把它扔出去另一个.
如果你深入了解维基百科或只是google的东西,你可以查看指令集和机器语言,如6502,z80,8080和其他处理器.可能有8个寄存器和250个指令,您可以从250个汇编指令仍然是非常高级语言的晶体管数量中感受到与每个时钟触发器中计算每个位所需的逻辑门序列相比周期.你在这个假设中是正确的.除了微编码处理器之外,这种低级逻辑不能以任何方式重新编程,您必须使用软件修复硬件错误(对于将要或将要交付但未报废的硬件).
查阅那本Petzold的书,他在解释东西方面表现出色,远远优于我能写的任何东西.
Pre*_*gha 19
编辑:这是一个CPU(6502)的例子,它已经使用python/javascript进行了模拟在TRANSISTOR LEVEL http://visual6502.org您可以将代码放入其中,看看它是如何做的.
编辑:优秀的10 000米级别视图: 新机器的灵魂 - Tracy Kidder
在我进行微码处理之前,我很难想象这一点.然后一切都有意义(抽象地).这是一个复杂的主题,但是在非常高级的视图中.
基本上就是这样想的.
cpu指令本质上是存储在构成存储器的电路中的一组电荷.存在导致这些电荷从存储器传输到CPU内部的电路.一旦进入CPU,电荷就被设置为CPU电路接线的输入.这本质上是一种数学函数,它将导致更多的电输出,并且循环继续.
现代cpu远远复杂,但包括许多层微码,但原理仍然相同.记忆是一组收费.存在移动电荷的电路和执行功能的其他电路将导致其他电荷(输出)被馈送到存储器或其他电路以执行其他功能.
要了解存储器的工作原理,您需要了解逻辑门以及如何从多个晶体管创建逻辑门.这导致发现硬件和软件在数学意义上基本上执行功能的意义上是等同的.
Bri*_*ell 14
这个问题需要解决的问题不仅仅是StackOverflow的答案.
要了解从最基本的电子元件到基本机器代码的所有方法,请阅读Horowitz和Hill的The Art of Electronics.要了解有关计算机体系结构的更多信息,请阅读Patterson和Hennessey的计算机组织和设计.如果您想进入更高级的主题,请阅读Hennessey和Patterson撰写的计算机体系结构:定量方法.
顺便说一句,电子艺术也有一本伴侣实验手册.如果您有时间和资源,我强烈建议您做实验室; 我实际上参加了Tom Hayes教授的课程,其中我们构建了各种模拟和数字电路,最终用68k芯片,一些RAM,一些PLD和一些分立元件构建计算机.您可以使用十六进制键盘将机器代码直接输入RAM; 这是一次爆炸,是在计算机最低级别获得经验的好方法.
Cra*_*ney 13
如果没有整本书籍,就无法详细解释整个系统,但这里是对简单计算机的高级概述:
要了解汇编指令如何导致电压变化,您只需要了解每个级别如何由下面的级别表示.例如,ADD指令将使两个寄存器的值传播到ALU,ALU具有计算所有逻辑运算的电路.然后,另一侧的多路复用器从指令馈送ADD信号,选择所需的结果,该结果传播回寄存器之一.
这是一个很大的问题,在大多数大学里都有一整个学期的课程来回答这个问题.所以,不要在这个小盒子里给你一些非常苛刻的总结,而是引导你到具有全部真相的教科书:计算机组织和设计:Patterson和Hennessey的硬件/软件接口.
非常简短,
机器代码指令作为一系列位存储在处理器中。如果您查看MOV处理器数据表,您会看到它有一个十六进制值,例如(例如)0xA5,这是特定于MOV指令的..(有不同类型的MOV指令具有不同的值,但让我们忽略暂时这样)。
0xA5 hex == 10100101 binary.
*(这不是MOVX86 上的真正操作码值- 我只是为了说明目的而选择一个值)。
在处理器内部,它存储在一个“寄存器”中,它实际上是一个触发器或锁存器阵列,用于存储电压:
+5 0 +5 0 0 +5 0 +5
这些电压中的每一个都馈入一个门或门集合的输入。
在下一个时钟沿,这些门会根据寄存器的输入电压更新其输出。
这些门的输出馈入另一个级别的门,或返回给他们自己。该级别进入下一个级别,然后进入下一个级别,依此类推。
最后,栅极输出方式下的线将被连接回另一闩锁/触发器(内部存储器),或在所述处理器上的输出引脚中的一个。
Register->(clock)->Gate A->(clock)->Gate B->pin
->latch
Run Code Online (Sandbox Code Playgroud)
(忽略不同门类型和更高级别结构的反馈)
这些操作在一定程度上并行发生,由核心架构定义。“更快”处理器(例如 2.0GHz 与 1.0GHz)性能更好的原因之一是更快的时钟速度(GHz 值)导致从一组门到下一组的传播速度更快。
重要的是要了解,在非常高的水平上,处理器所做的只是改变引脚电压。我们在使用诸如 PC 之类的设备时所看到的所有辉煌的复杂性都源自于门的内部模式以及连接到处理器的外部设备/外设(如其他 CPU、RAM 等)中的模式。处理器是指其引脚改变电压的模式和序列,以及允许 CPU 某一时刻的状态影响其下一时刻的状态的内部反馈。(在汇编中,此状态由标志、指令指针/计数器、寄存器值等表示)
以一种非常真实的方式,每个操作码(机器代码指令)的位在物理上与处理器的内部结构相关联(尽管在必要时可以通过内部查找表/指令映射在一定程度上对其进行抽象)。
希望有帮助。我还接受过良好的 EE 教育和大量嵌入式开发经验,所以这些抽象对我来说很有意义,但对新手来说可能不是很有用。