(一)对程序员来说是CPU是什么

1. CPU的内部结构解析

CPU和内存是由许多晶体管组成的电子部件,通常称为IC(Integraed Circuit,集成电路)。

从功能方面来看,如图1-2所示,CPU的内部由寄存器、控制器、运算器和时钟四个部分构成,各部分之间由电流信号相互连通。

  • 寄存器
    可用来暂存指令、数据等处理对象,可以将其看作是内存的一种,根据种类的不同,一个CPU内部会有20~100个寄存器。

  • 控制器
    负责把内存上的指令,数据等读入寄存器,井根据指令的执行结果来控制整个计算机。

  • 运算器
    负责运算从内存读入寄存器的数据。

  • 时钟
    负责发出CPU开始计时的时钟信号。

通常所说的内存指的是计算机的主存储器(main memory),简称主存。

主存通过控制芯片等与CPU相连,主要负责存储指令和数据。

主存由可读写的元素构成,每个字节(1字节-8位) 都带有一个地址编号。

CPU可以通过该地址读取主存中的指令和数据,当然也可以写入数据。

但有一点需要注意,主存中存储的指令和数据会随着计算机的关机而自动清除。


程序启动后,根据时钟信号,控制器会从内存中读取指令和数据。

通过对这些指令加以解释和运行,运算器就会对数据进行运算,控制器根据该运算结果来控制计算机。

所谓的控制就是指数据运算以外的处理(主要是数据输入输出的时机控制)。



2. CPU是寄存器的集合体

程序是把寄存器作为对象来描述的。

如代码清单1-1所示,这是用汇编语言(assembly)编写的程序的一部分:

汇编语言采用助记符(memonic)来编写程序,每一个原本是电气信号的机器语言指令都会有一个与其相应的助记符。助记符通常为指令功能的英语单词的简写。例如,mov和add分别是数据的存储(move)和相加(addtion)的简写。

将汇编语言编写的程序转化成机器语言的过程称为汇编;反之,机器语言转化成汇编语言的过程则称为反汇编。


通过阅读汇编语言编写的代码,能够了解转化成机器语言的程序的运行情况。

机器语言级别的程序是通过寄存器来处理的。也就是说,在程序员看来“CPU是寄存器的集合体"。

其中,eax和ebp是CPU内部的寄存器的名称。内存的存储场所通过地址编号来区分,而寄存器的种类则通过名字来区分。

使用高级语言编写的程序会在编译后转化成机器语言,然后再通过CPU内部的寄存器来处理。



3. 决定程序流程的程序计数器

图1-4是程序起动时内存内容的模型:

用户发出启动程序的指示后,Windows等操作系统会把硬盘中保存的程序复制到内存中,示例中的程序实现的是将123和456两个数值相加,并将结果输出到显示器上。


存储指令和数据的内存,是通过地址来划分的。

实际上,一个命令和数据通常被存储在多个地址上,但为了便于说明,图1-4中把指令、数据分配到了一个地址中。

地址0100是程序运行的开始位置。

Windows等操作系统把程序从硬盘复制到内存后,会将程序计数器(CPU寄存器的一种)设定为0100,然后程序便开始运行。

CPU每执行一个指令,程序计数器的值就会自动加1。

然后,CPU的控制器就会参照程序计数器的数值,从内存中读取命令并执行。

也就是说,程序计数器决定着程序的流程。



4. 条件分支和循环机制

程序的流程分为顺序执行、条件分支和循环三种。

  • 顺序执行
    是指按照地址内容的顺序执行指令。

  • 条件分支
    是指根据条件执行任意地址的指令。

  • 循环
    是指重复执行同一地址的指令。

顺序执行的情况比较简单,每执行一个指令程序计数器的值就自动加1。

分支和循环,机器语言的指令就以将程序计数器的值设定为任意地址(不是+1)。这样一来,程序便可以返回到上一个地址来重复执行同一个指令,或者跳转到任意地址。


图1-5表示把内存中存储的数值(示例中是123)的绝对值输出到显示器的程序的内存状态:

程序运行的开始位置是0100地址。

随着程序计数器数值的增加,当到达0102地址时,如果累加寄存器的值是正数,则执行跳转指令(jump指令) 跳转到0104地址。

此时, 由于累加寄存器的值是123,为正数,因此0103地址的指令被跳过,程序的流程直接跳转到了0104地址。也就是说,“跳转到0104地址”这个指令间接执行了“将程序计数器设定成0104地址”这个操作。


条件分支和循环中使用的跳转指令,会参照当前执行的运算结果来判断是否跳转。

CPU在进行运算时,标志寄存器的数值会根据运算结果自动设定。

条件分支在跳转指令前会进行比较运算。

至于是否执行跳转指令,则由CPU在参考标志寄存器的数值后进行判断。

运算结果的正、零、负三种状态由标志寄存器的三个位表示。


图1-6是32位CPU(寄存器的长度是32位)的标志寄存器的示例:

标志寄存器的第一个字节位,第二个字节位和第三个字节位的值为1时,表示运算结果分别为正数零和负数。


CPU执行比较的机制:

例如,假设要比较累加寄存器中存储的XXX值和通用寄存器中存储的YYY值,执行比较的指令后,CPU的运算装置就会在内部(暗中)进行XXX-YYY的减法运算。

而无论减法运算的结果是正数,等还是负数,都会保存到标志寄存器中,结果为正表示XXX比YYY大,零表示XXX和YYY相等,负表示XXX比YYY小。

程序中的比较指令,就是在CPU内部做减法运算。



5. 函数的调用机制

函数调用使用的是call指令, 而不是跳转指令。

在将函数的入口地址设定到程序计数器之前,call指令会把调用函数后要执行的指令地址存储在名为栈的主存内。

函数处理完毕后,再通过函数的出口来执行return命令。


return命令的功能是,把保存在栈中的地址设定到程序计数器中。

如图1-7所示,MyFunc函数被调用之前,0154地址保存在栈中:

MyFunc函数的处理完毕后,栈中的0154地址就会被读取出来,然后再被设定到程序计数器中(图1-8):

在编译高级编程语言的程序后,函数调用的处理会转换成call指令,函数结束的处理则会转换成return指令。



6. 通过地址和索引实现数组

通过基址寄存器和变址寄存器这两个寄存器,可以对主内存上特定的内存区域进行划分,从面实现类似于数组的操作。



7. CPU的处理其实很简单

表1-2按照功能对CPU能执行的机器语言指令进行了大体分类:





参考

《程序是怎样跑起来的》 —— 1. 对程序员来说是CPU是什么

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值