汇编语言——寄存器(CPU的工作原理 ax,bx,cx,dx通用寄存器 cs代码段寄存器)
寄存器
一个典型的CPU由运算器、控制器、寄存器等器件组成,这些器件靠内部总线相连。(外部总线是上一篇博客说的内存总线,数据总线,控制总线)
- 内部总线实现CPU内部各个器件之间的联系。
- 外部总线实现CPU和主板上其它器件的联系。
CPU中主要的部件是寄存器,寄存器是CPU中我们可以使用指令读写的部件(通过改变各种寄存器的内容来实现对CPU的控制)
不同的CPU寄存器的个数也不同,8086CPU有14个寄存器 它们的名称为:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。
1、通用寄存器
a.简介
8086CPU所有的寄存器都是16位的,可以存放两个字节。(1Byte=8bit)
AX、BX、CX、DX 通常用来存放一般性数据被称为通用寄存器。
一个16位寄存器所能存储的数据的最大值为:216-1。
示例:
数据:20000
二进制表示:0100111000100000
在寄存器AX中的存储:
四个寄存器都可以分为两个独立的8位寄存器使用。
AX可以分为AH和AL;
BX可以分为BH和BL;CX可以分为CH和CL;
DX可以分为DH和DL。
AX的低8位(0位~7位)构成了AL寄存器,高8位(8位~15位)构成了AH寄存器,它们都是可以独立使用的8位寄存器。一个8位寄存器所能存储的数据的最大值是28-1。
b.汇编指令
汇编指令不区分大小写(和mysql一样大小写不敏感)
丢失(不进位):丢失指的是进位制不能在 8 位寄存器中保存,但是 CPU 不是并真的不丢弃 这个进位值,这个问题以后再说。
2、物理地址
CPU访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间。
每一个内存单元在这个线性空间中都有唯一的地址,这个唯一的地址称为物理地址。
16位CPU的特征:
- 运算器一次最多可以处理16位的数据。
- 寄存器的最大宽度为16位。
- 寄存器和运算器之间的通路是16位的
因为8086CPU是16位的,所以它采用了一个机智的方法(地址加法器):在内部用两个16位地址合成的方法来形成一个20位的物理地址。
小Tips:更多猛击这里
CPU最大能查找多大范围的地址叫做寻址能力 ,CPU的寻址能力以字节为单位 ,如32位寻址 的CPU可以寻址2的32次方大小的地址也就是4G,这也是为什么32位的CPU最大能搭配4G内 存的原因 ,再多的话CPU就找不到了。 16位寄存器,用二进制表示最小的数是0000000000000000,最大的数是1111111111111111。 换算成十进制数就是0-65535,加上零就是65536(2^16)。 也就是说一共可以存放65536个不同的地址。 每一个地址在内存中占一个字节(Byte)。 64KB = 65536byte,so 16位结构,表现出的寻址能力是64K。 20位的寻址能力:2^20/1024/1024 = 1MB 地址总线:属于一种电脑总线 (一部份),是CPU用来沟通某些单元想要存取(读取/写入)电脑内存元件/地方的实体位址。更多去看上一篇博客
地址加法器合成物理地址的方法:物理地址=段地址×16+偏移地址
一个16进制的数*16(向左移1位) ==> 一个二进制(向左移4位)
举例说明物理地址=段地址×16+偏移地址
8086CPU就是这样一个只能提供两张3位数据纸条的CPU。
比如我们只能通过纸条来通信,读者问我图书馆的地址,我只能将它写在纸上告诉读者。
显然我必须有一张可以容纳 4 位数据的纸条才能写下2826这个数据:
不巧的是,没有能容纳4位数据的纸条,仅有两张可以容纳3位数据的纸条。
这样我只能以这种方式告诉读者2826这个数据:
给它两张纸条,让他把第一张纸条乘以10再加上第二张纸条的值就是我们要给它的物理地址(当然我们的是16进制的)
-
段地址
在编程时我们可以根据需要,将若干地址连续的内存单元看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位相应段中的内存单元。
小结:
1、CPU访问内存单元时,必须向内存提供内存单元的物理地址。
8086CPU在内部用段地址和偏移地址移位相加的方法形成最终的物理地址
(1)段地址×16 必然是 16的倍数,所以一个段的起始地址也一定是16的倍数;
(2)偏移地址为16位,16 位地址的寻址能力为 64K,所以一个段的长度最大为64K。也就是说如果偏移地址都是最大64K,那么有16个段(因为20位的寻址能力为1MB)
2、CPU可以用不同的段地址和偏移地址形成同一个物理地址。
3、给定一个段地址,仅通过变化偏移地址来进行寻址,最多可以定位多少内存单元?
结论:偏移地址16位,变化范围为0~FFFFH,仅用偏移地址来寻址最多可寻64K个内存单元。
比如:给定段地址1000H,用偏移地址寻址,CPU的寻址范围为:10000H~1FFFFH。
4、在8086PC机中,存储单元的地址用两个元素来描述。即段地址和偏移地址。
“数据在21F60H内存单元中。”对于8086PC机的两种描述:
(a)数据存在内存2000:1F60单元中;
(b)数据存在内存的2000段中的1F60H单元中。
可根据需要,将地址连续、起始地址为16的倍数的一组内存单元定义为一个段。
答案
1、給定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围是0010H到1000FH 2、有一个数据存放在内存20000H单元中,现给定段地址为SA,若想用偏位地址寻到此单元,则SA应满足,最小为1001H,最大为2000H 解:物理地址=段地址*16+偏移地址 20000H=SA*16+偏移地址 由于16为十进制,转换为十六进制=10H 最小偏移地址=0H 最大偏移地址=FFFFH 最小SA=(20000H-FFFFH)/10H=20000H/10H-FFFFH/10H=2000H-FFFH=1001H 最大SA=(20000H-0H)/10H=20000H/10H-0H/10H=2000H-0H=2000H 3、当sa<1001H 或者sa>2000H 将无法寻到20000H单元
3、段寄存器
段寄存器就是提供段地址的
8086CPU有4个段寄存器:
- CS(代码段)
- DS(数据段)
- SS(堆栈段)
- ES(附加段)
当8086CPU要访问内存时,由这4个段寄存器提供内存单元的段地址。
CS和IP是8086CPU中最关键的寄存器,它们指示了CPU当前要读取指令的地址(其他的段+指针寄存器以后再说,)。
- CS为代码段寄存器;
- IP为指令指针寄存器
8086PC的工作过程
(1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;
(2)IP = IP + 所读取指令的长度,从而指向下一条指令;
(3)执行指令。 转到步骤 (1),重复这个过程。
在 8086CPU 加电启动或复位后( 即 CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086PC机刚启动时,
CPU从内存FFFF0H单元中读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。
CS和IP:
CPU将CS、IP中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。
如果说,内存中的一段信息曾被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指向过。
修改CP和IP的指令:
在CPU中,我们能够用指令读写的部件只有寄存器,我们可以通过改变寄存器中的内容实现对CPU的控制。
CPU从何处执行指令是由CS、IP中的内容决定的,程序员可以通过改变CS、IP中的内容来控制CPU执行目标指令。
那么问题来了,我们要怎样修改CS和IP的值呢?
首先我们来思考一下,如何修改AX中的值?
mov 指令
如:mov ax,123
mov指令可以改变8086CPU大部分寄存器的值,被称为传送指令。
但mov指令不能改变CS、IP的值,CPU为我们提供了另外一个指令:jmp(转移指令)
使用方法:
# 同时修改CS和IP的值 # 使用方法:jmp 段地址:偏移地址 # 功能:用指令中给出的段地址修改CS,偏移地址修改IP。 jmp 2AE3:3 # CS的地址-->3ae3 , 偏移地址 --> 0003 jmp 3:0B16 # CS的地址-->0003 , 偏移地址 --> 0b16 # 仅修改IP的内容: # jmp 某一合法寄存器 # 功能:用寄存器中的值修改IP。 jmp ax (类似于 mov IP,ax) # 修改IP的值为寄存器中的值 jmp bx
内存中存放的机器码和对应汇编指令情况: (初始:CS=2000H,IP=0000H),写出执行顺序。
答案:
(1)mov ax,6622 (2)jmp 1000:3 (3)mov ax,0000 (4)mov bx,ax (5)jmp bx (6)mov ax,0123H (7)转到第(3)步执行
小结:
1、段地址在8086CPU的寄存器中存放。当8086CPU要访问内存时,由段寄存器提供内存单元的段地址。8086CPU有4个段寄存器,其中CS用来存放指令的段地址。
2、CS存放指令的段地址,IP存放指令的偏移地址。
8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。
3、8086CPU的工作过程:
- 从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;
- IP指向下一条指令;
- 执行指令。(转到步骤(1),重复这个过程。)
4、8086CPU提供转移指令(jmp)修改CS、IP的内容。
答案:
下面3条指令执行后,CPU几次修改IP?都是在什么时候?最后IP中的值是多少?
mov ax,bx sub ax,ax jmp ax 首先根据 代码 我们可以看到 mov ax,bx 我们将bx的值存入ax中,暂且不管bx的值为多少我们就认为bx中有一个数据 sub ax,ax 然后我们重新给ax赋值 ax = ax - ax ,所有ax的值应该为 0 jmp ax 当jmp指令,指向的是一个通用寄存器ax,代表的意思为修改 IP 的值 IP的值为ax 即 IP 的值应为0 所以CPU只修改了1次IP 执行到 jmp ax 时 修改了 IP中的值 为 0