在计算机中抽象(屏幕上的字母)符合实际情况(电流通过内存和处理器中的电路).这种进化是如何发生的?
我想,我说的比汇编者更深入.也许比处理器指令更深?在某些时候,命令实际上是由硬件解释的,但我不明白在哪里/如何发生.
我没有上大学,所以没有参加CS课程或其他任何事情.像许多人一样,我是一个爱好者,变成了"亲".结果,我认为我失踪了很多拼图.我知道一点点C++,并且理解指针等的概念(尽管我并没有在愤怒中使用它们),但是我只是在高级别工作.我不确定知道这种东西会不会对我有所帮助,但它确实很有趣.
处理器操作所谓的提取 - 解码 - 执行周期.机器代码指令相当低级(即它们在单个指令中没有那么多).例如,添加两个数字将具有一系列语义指令,如:
将指向操作数1地址的指针加载到寄存器1中
将存储在寄存器1中的地址中的值加载到寄存器2中
将指向操作数2地址的指针加载到寄存器1中
将存储在寄存器1中的地址的值加载到寄存器3中
添加寄存器2和寄存器3的内容并将其存储在寄存器4中
将指向目标的指针加载到寄存器1中
将寄存器4的内容存储在寄存器1中指定的地址中
处理器内部是一组特殊的快速存储器,称为"寄存器文件",它包含处理器用于存储当时正在处理的数据的存储器.寄存器文件有几个寄存器,它们是唯一标识的.指令通常用于寄存器,尤其是RISC架构; 虽然情况并非总是如此,但目前这是一个足够好的抽象.
通常,处理器必须将数据加载或存储到寄存器中以对其执行任何操作.操作如寄存器运算工作,从两个寄存器取操作数和结果安置到第三(用于花生画廊的利益,我已经使用了6502 -让我们不要混淆问题;-).处理器具有将寄存器中的数据加载或存储到机器主存中的特殊指令.
处理器有一个称为"程序计数器"的特殊寄存器,用于存储要执行的下一个操作的地址.因此,执行指令的顺序大致如下:
获取存储在程序计数器中当前地址的指令.
解码指令,分离实际操作,它使用的寄存器,"寻址模式"(如何获取或存储数据的位置)以及其他一些位和bob.
执行指令.
执行该指令将改变各种寄存器中的值.例如,'load'指令会将值复制到寄存器中.算术或逻辑(And,Or,Xor)将获取两个值并计算第三个值.跳转或分支指令将改变程序计数器的地址,以便处理器开始从不同的位置获取指令.
处理器可以有专门的寄存器.这样的一个例子是上述程序计数器.另一个典型的是条件标志寄存器.这将有几个具有特殊含义的位.例如,如果最后一次算术运算的结果为零,则可能会设置一个标志.这对条件操作很有用.你可以比较两个数字.如果它们相等,则设置"零"标志.处理器可以具有条件指令,仅在设置了该标志时才执行该条件指令.
在这种情况下,您可以递减寄存器中的计数器,如果它为零,则设置条件标志.条件(零上的分支)可用于循环,其中如果递减指令的结果为零,则递减计数器并退出循环.在某些处理器(例如ARM系列)上,所有指令都是有条件的,对非条件指令有一个特殊的"do always"条件.
典型处理器指令的一些示例是:
递增或递减寄存器
将寄存器的内容加载或存储到内存中.您还可以通过另一个寄存器的内容来加载或存储偏移量的地址.这允许您通过递增另一个寄存器来轻松地循环数据数组.
加,减,乘,逻辑运算来计算值.它们从两个寄存器中获取操作数,并将结果放在第三个寄存器中.
跳转到另一个位置 - 这会将位置的内容移动到程序计数器中并开始从新位置获取指令.
将值推送或弹出到堆栈上.
这个stackoverflow帖子有一个编译C代码的小片段和该片段的汇编语言输出的例子.它应该为您提供高级语言与其编译的机器代码输出之间的关系类型的示例.
学习这个的最好方法是获得一个汇编程序并试一试.对于像20世纪80年代的8位微处理器这样的老式,简单的计算机来说,这曾经变得容易得多.目前最接近此类架构的是嵌入式系统.您可以非常便宜地获得像Microchip PIC这样的嵌入式处理器的开发板.由于这种类型的架构比现代操作系统具有更少的行李,因此使用系统调用的i-dotting和t-crossing更少.这样可以更容易地在这种类型的体系结构上引导汇编语言程序; 更简单的架构也更容易理解.
另一个选择是获得一个仿真器,如SPIM.这将模拟CPU并让您在其上组装和运行程序.这种仿真器的优点是它们还具有单步执行程序的功能(很像调试器)并显示寄存器文件的内容.这可能有助于深入了解实际情况.
我非常建议您阅读" 代码 "一书,它详细介绍了计算机如何从不同的系统演变而来.
它非常吸引人,并将向您解释事物如何从摩尔斯电码代码演变为简单的添加机器再到某些组件.它应该为您提供CPU,内存等硬件如何解释和使用机器指令的图片.