文章也同时在简书更新
引言
本篇文章继续第四章关于内存寻址的探讨,主要介绍各类寄存器。
摘要
16位和32位段寄存器
不管CPU正在做什么,只要他对内存中某一个位置进行寻址,那么该位置的段地址就会出现在6个寄存器之一中。
所有的段寄存器大小都是16位!所有的段寄存器大小都是16位!!所有的段寄存器大小都是16位!!!无论CPU是什么型号,甚至是对于32位CPU来说也是如此。
- CS(code segment)代码段:机器指令存放在代码段的某些偏移位置处。CS包含当前执行指令的代码段的段地址。
- DS(data segment)数据段:变量和其他数据存放在数据段的某些偏移位置处。也许会有很多个数据段,但CPU一次只能使用一个,这是通过将该段的段地址放入寄存器DS来实现的。
- SS(stack segment)堆栈段:堆栈式CPU用来暂时存放数据和地址等一个非常重要的部件。堆栈也有一个段地址,它存放在SS中。
- ES(extra segment)附加段:它是一个可用于指定内存中某一位置的备用段。
- FS和GS是ES的克隆:从命名上可以联想到E->F->G。
通用寄存器
- 段寄存器是存放段地址的专家,通用寄存器则用来存放偏移地址,它必须和段地址成对出现,以标识内存中的某个位置。
- 在当前32位世界中,通用寄存器分为三个一般类:16位通用寄存器,32位扩展通用寄存器和8位的半寄存器。16位和8位寄存器实际上是32位寄存器内部的一块区域的名字。
- 32位通用寄存器的高16位根本没有自己的名字,可以通过SI来访问ESI的低16位,但是想要获取高16位,必须要引用ESI,获取整个32位数据。
半寄存器
- 8位半寄存器的好处是可以读取和修改16位数据的其中一半,高H低L。但这一双重特性只涉及16位通用寄存器AX,BX,CX和DX。其他的16位通用寄存器(SP,BP,SI,DI)并不具有类似的特性。例如,不存在名为SIH和SIL的8位寄存器。
指令指针寄存器
- 指令指针寄存器(instruction pointer)通常称为IP,它是16位的大小。在32位保护模式下,则为EIP。
- 它只做一件事情:包含当前代码段中下一条即将执行的机器指令的偏移地址。一个程序可能有很多个代码段或者只有一个。当前代码段(current code segment)是指段地址当前存放在代码寄存器CS中的那段代码。
- 当执行程序时,CPU使用IP来跟踪位于当前代码段中的位置。每执行一条指令后,IP就递增一定数量的字节。这个字节数是刚刚执行的那条指令的大小。最终的结果是IP跳到了内存中更远的地方,指向下一条即将执行的指令的开始位置。
- CS和IP一起,保存下一条即将执行指令的完整地址。在实模式段模型中,CS和IP共同组成一个20位的地址,指向实模式内存中的1048576(2的20次方)个字节之一。
- 值得注意的是,IP是唯一既不能直接读出,也不能直接写入的寄存器。有一些技巧可以用来获取当前IP寄存器的值,但是拥有IP的值并不是像你想象得那么有用。
标志寄存器
- 标志寄存器(flags register)在8086,8088和80286中的大小为16位,正式名称是FLAGS。在386等更高CPU中,它的大小是32位,正式名称为EFLAGS。
- 当程序执行测试时,它所测试的就是标志寄存器中某个单个的标志位。因为每个标志位可以包含的值只有0或1,所以在汇编中,测试就是二选一的过程:标志位被设置为1,或者没有被设置为1。根据是否被设置为1,程序会执行非此即彼的不同决策,走不同的路。关于各标志位的具体作用将在后续再详细介绍。
感想
如果整个PC是一个工厂车间,各类外设是工人们,那么CPU就是车间工长,而寄存器就是工长衣服的口袋,里面装着他常用的各种数据和信息。工人们和工长在名为“数据总线”的流水线上协同工作,保障车间的正常运作。