PC_寻址方式
寻址方式
- 寻找指令或者操作数有效地址的方式,即,确定本条指令的数据地址以及下一条指令的地址的方法
- 包含指令寻址和数据寻址两类
- 指令中断地址码字段不代表操作数的真是地址,则称这种地址为形式地址(A)
- 形式地址结合寻址方式可以计算出操作数在存储器中的真实地址(称为有效地址(EA))
- (A)表示地址为A的数值
- A可以是寄存器编号
- 也可以是内存单元地址
- 对应的(A)就是寄存器中的数值(或相应内存单元的数值)
- EA=(A)表示有效地址EA就是A处保存的值
- (EA)就表示操作数本身
指令寻址
-
寻找下一条将要执行的指令地址称为指令寻址
-
顺序寻址
-
跳跃寻址
- 如果发生跳跃,跳跃结果是当前指令修改PC值,所以下一条指令依然是通过PC给出
- 但是PC中的值可能不再是默认+1的结果
-
数据寻址
-
寻找本条指令的(操作数)数据地址称为数据寻址
-
在指令中表示一个操作数的地址
-
并且如何用这种表示,得到操作数或者如何计算出操作数的地址
-
将地址码字段进一步划分为寻址特征和形式地址
-
O P 操 作 码 寻 址 特 征 形 式 地 址 A \begin{array}{|c|c|c|c|} \hline OP操作码&寻址特征&形式地址A\\ \hline \end{array} OP操作码寻址特征形式地址A
-
-
-
对于按字寻址的机器
- 程序计数器PC的位数取决于存储器的容量(字数)
- 指令寄存器的长度取决于指令字长
寻址特征字段
- 如果机器支持多种寻址方式,那么需要有不同的寻址特征来指定指令采用的是那种寻址方式
例
- 计算机采用16位定长指令格式,操作码位数和寻址方式位数固定
- 已知该机器指令系统中有48条指令
- 并且支持4中寻址方式:
- 直接
- 间接
- 立即
- 相对
- 在单地址指令中,直接寻址方式的可能寻址范围是多少?
- 分析
- 由于指令数量 2 5 < 48 < 2 6 2^5<48<2^6 25<48<26
- 因此需要6bit来区分不同指令(不同操作码)
- 如果只用5bit或者更少的二进制位不足以表达48中不同编码(至多32条),所以采用6
- 为了支持不同的寻址方式,区分4种寻址方式需要2位( 2 2 = 4 2^2=4 22=4,2位足够表达4中不同编码)
- 16-6-2=8bit
- 因此,剩余8bit留给直接寻址方式,范围宽度为 2 8 = 256 2^{8}=256 28=256
- 无符号范围 0 ∼ 255 0\sim{255} 0∼255
隐含寻址
- 不明显地给出操作数地址
- 在指令中隐含操作数地址
- 特点:
- 缩短指令长度
- 由于隐地址不需要在指令中显式指出操作数地址,因此可以最大程度简化指令(地址)结构
- 需要增加存储操作次数或者隐含地址的硬件
- 这就是为什么隐含寻址的指令中虽然没有操作数地址码,但是速度并不快
立即数寻址🎈
- 这种类型的指令的地址字段指出的不是操作数地址,而是操作数本身,又称为立即数
- 特点:
- 指令在执行阶段不访问主存,指令执行时间最短
- 甚至不需要通过访问寄存器来获得操作数(地址),因此立即数寻址的速度最快
- 缺点是位数限制了立即数的范围
- 指令在执行阶段不访问主存,指令执行时间最短
直接寻址
- 指令中的形式地址A是操作数的真是地址EA
- 即EA=A
- 特点:
- 简单(在执行阶段仅需要访问一次主存,不需要专门计算操作数的有效地址)
- A的位数决定了指令操作数的寻址范围,操作数的地址不易修改
间接寻址
- 相对于直接寻址而言的
- 设操作数为 x x x
- E A = ( A ) EA=(A) EA=(A)
- x = ( E A ) = ( ( A ) ) x=(EA)=((A)) x=(EA)=((A))
- 如果是2次间接寻址,那么:
- EA=((A))
- x = ( E A ) = ( ( ( A ) ) ) x=(EA)=(((A))) x=(EA)=(((A)))
- 依次类推
- 特点
- 间接寻址可以扩大寻址范围
- 形式地址A的位数往往比有效地址位数更少
- 但是自行阶段需要多次访存
- 每多1次间址,就需要多访存一次(根据存储字的最高位确定访问次数)
- 这是非常坏的,效率很低
寄存器寻址
- 在指令字中直接给出操作数所在寄存器编号
- E A = R i EA=R_i EA=Ri( R i R_i Ri表示编号为i的寄存器,可以将 R i R_i Ri理解为地址,而且是可以高速访问的地址)
- x = ( E A ) = ( R i ) x=(EA)=(R_i) x=(EA)=(Ri), R i R_i Ri寄存器中的内容就是操作数 x x x
- 特点:
- 指令在执行阶段不需要访存只访问寄存器
- 因为寄存器数量少,对应的地址码(寄存器编号)长度较小,使得指令字短,不需要访存
- 支持向量/矩阵运算
- 但是,寄存器价格高,寄存器的数量有限
- 指令在执行阶段不需要访存只访问寄存器
寄存器间接寻址
-
在寄存器 R i R_i Ri给出的表示操作数本身,而是操作数所在主存单元的地址
-
E A = ( R i ) EA=(R_i) EA=(Ri)
-
x = ( E A ) = ( ( R i ) ) x=(EA)=((R_i)) x=(EA)=((Ri))
-
-
特点
- 相比于一般间接寻址的速度快(第一次访问的地址是寄存器,速度快)
- 指令执行阶段需要访问主存
相对寻址
-
将PC中的内容加上指令格式中的形式地址A ,形成操作数的有效地址EA
- E A = ( P C ) + A EA=(PC)+A EA=(PC)+A
- A是相对于当前指令地址的位移量
- 不过,实际问题中,经常会说,取值令时,每取出一个字节,PC自动+1
- 这时候,PC的值需要做修正
- 假 设 被 取 出 的 指 令 有 k 个 字 节 : P C ′ = ( P C ) + k 假设被取出的指令有k个字节:PC'=(PC)+k 假设被取出的指令有k个字节:PC′=(PC)+k
- 然后再计算相对偏移后的有效地址EA=(PC’)+A=(PC)+k+A
- 相应的偏移量 A = E A − ( P C ) − k A=EA-(PC)-k A=EA−(PC)−k
-
从公式上看,容易理解,A的位数决定了操作数的范围
-
相对寻址提供的相对地址实质上是:
- 以下一条指令在内存中的首地址为基准位置的偏移量
- 因为,寻址阶段位于取值阶段之后
- 众所周知,取指阶段结束后,PC已经完成了自增,此时的PC内容是下一条(默认情况下)的指令的首地址
- EA=(PC)+A正是在取指阶段后的寻址阶段执行的,因此,偏移量A是相对于当前正在执行的指令的下一条指令的首地址的偏移量
-
优点是:
- 操作数的地址是不固定的
- 它随着PC的变化而变化,且与指令之间总是相差一个固定值
-
相对寻址相对于多到程序设计最为重要
- 多道程序设计中,各个程序段可能需要在内存中浮动
- 相对寻址特别有利于程序浮动,广泛应用于转移指令🎈
例
- 设相对寻址指令长度为3B
- 第一字节为操作码
- 第二,第三字节为地址码(作为偏移量)
- 采用补码的形式来表示
- 数据字存储器中采用低字节为字地址的方式(即,小端方式方式存放数据)
- 每当cpu从存储器中取出1字节时,自动完成 ( P C ) + 1 → P C (PC)+1\to{PC} (PC)+1→PC
- 如果PC的当前值为240(十进制)
- 要求转移到290(十进制)
- 则,转移指令的第2,3个字节的内容为?
- 分析:
- 完成取值周期操作时,PC的值自增了3(指令的长度为3字节,所以执行了三次PC+1)
- 此时PC的内容为240+3=243
- 为了转移到地址290(即EA=290),根据相对寻址公式EA=(PC)+A
- A=290-243=47
- 将47转为二进制(16进制:
47
=
8
∗
5
+
7
=
10100
0
2
+
11
1
2
=
10111
1
2
47=8*5+7=101000_2+111_2=101111_2
47=8∗5+7=1010002+1112=1011112)
- + 47 的 原 码 T ( + 47 ) = 0 , 101111 ; 补 码 C ( + 47 ) = T ( + 47 ) +47的原码T(+47)=0,101111;补码C(+47)=T(+47) +47的原码T(+47)=0,101111;补码C(+47)=T(+47)
- 由于47是个正数,所以扩充为2字节后,得到0000 0000 0010 111 1 2 1111_2 11112=002FH
- 由因为要求用低字节为字地址的方式存放数据,则低字节2FH应该位于指令的地址码字段的第二字节位置,第三字节为00H
- 又比如,PC的值是240,要求转移到200
- 那么根据公式EA=(PC)+A
- A=EA-(PC)=200-(240+3)=-43
- 即,偏移量为-40(十进制真值)
- 40 = 4 ∗ 10 + 3 = 101 0 2 × 100 2 + 1 1 2 = 10101 1 2 40=4*10+3=1010_2\times{100}_2+11_2=101011_2 40=4∗10+3=10102×1002+112=1010112
- T ( − 40 ) = 1 , 10101 1 2 T(-40)=1,101011_2 T(−40)=1,1010112
- 其补码
C
(
−
40
)
=
1
,
010101
C(-40)=1,010101
C(−40)=1,010101
- 扩充为2字节(16bit)
- 1111 1111 1101 0101=FFD5H
- 同样因为小端方式,随意指令的第二字节是D5H,而第三字节是FFH
- 那么根据公式EA=(PC)+A
基址寻址
-
将cpu中的基址寄存器BR的内容加上指令格式中的形式地址A形成的操作数有效地址EA
- E A = ( B R ) + A EA=(BR)+A EA=(BR)+A
- BR可以采用专用寄存器或者通用寄存器实现
-
特点
- 基址寄存器BR是面向操作系统的
- 内容有操作系统/管理程序确定
- 采用通用寄存器作为BR时,虽然用户可以决定哪个GPR作为BR,但是内容依然有操作系统决定
- 主要是用来解决程序逻辑空间和存储器物理空间的无关性
- 程序执行过程中,BR的内容不变(作为基地址)
- 形式地址可以变(作为偏移量)
- 内容有操作系统/管理程序确定
- 优点:
- 可扩大寻址范围
- BR的位数大于形式地址A的位数
- 用户不必考虑自己的程序存于主存的哪个空间区域,有利于多道程序设计
- 相对寻址也是有利于多道程序设计
- 可以编制浮动程序,但偏移量(形式地址A)位数较短
- 因此主要说相对寻址方式对于多道程序设计/浮动程序的设计最为重要
- 可扩大寻址范围
- 基址寄存器BR是面向操作系统的
例
- 某计算采用大端方式,按字节编址
- 某指令中的操作数的机器数为1234 FF00H
- 该操作数采用基址寻址方式
- 形式地址的补码表示为FF12H
- 基址寄存器BR的内容(BR)=F000 0000H
- 该操作数的LSB(最低有效字节)所在内存地址为?
- 分析:
- 基址寻址方式有效地址的公式EA=(BR)+A
- A的补码为FF12H=1,111 1111 0001
0010
2
{0010}_2
00102,最高位为1是负数,则其真值为:
- 1,000 0000 1110 1101+1=1,000 0000 1110 1110,
- 将符号位改为
-
,得到真值的二进制形式:-000 0000 1110 1110 - 真值的16进制形式
-00EE
H - 带入公式EA=F000 0000H+(-00EEH)=EFFF FFFFH+1H-00EEH=EFFF FF11H+1H=EFFF FF12H
- 也即是说,操作数所在地址为EFFF FF12H
- 更具体的说,是第一个被放置的字节位置是EA=EFFF FF12H+0H
- 由于机器采用大端方式存储数据,而且操作数位数是4*8=32bit=4B
- 那么操作数的最低有效字节00H所在字节地址为EA+3=EFFF FF15H
- 注意不是+4,而是+3
- 因为第1个字节是+0;第2个字节+1,第3字节+2,第4个字节+3
- 类似于数组从0开始计算下标一样
- 这里EA表示的是有效地址的简写
- 那么操作数的最低有效字节00H所在字节地址为EA+3=EFFF FF15H
变址寻址
-
E
A
=
(
I
X
)
+
A
EA=(IX)+A
EA=(IX)+A
- 变址寄存器IX(index Register)
- 特点:
- 变址寄存器面向用户
- 在程序执行过程中,IX的内容可以作为偏移量,由用户改变
- 偏移量的位数足以表示整个存储空间
- 形式地址A不变(和基址寻址特点相反)
- 也可以扩大寻址范围
- 便于编制循环程序
- 变址寻址立足用户,主要用户处理数组用提,在变址寻址中,变址寄存器的内容是由用户设定
- 在程序执行过程中其值可变,指令字中的形式地址A反而不可变
例
- 在按字节编址的计算机中,某double类型(double占8字节(sizeof(double)=8,单位是字节),(64bit))数组A的首地址为2000H
- 现在使用变址寻址方式(循环结构)访问数组A
- 已知保存数组下标的变址寄存器的初始值为0
- 为了便于描述,设变址寄存器的值为 ( I X ) (IX) (IX)
- 每次循环取一个数组元素,其偏移地址(偏移量) O = ( I X ) × s i z e o f ( d o u b l e ) O=(IX)\times{sizeof(double)} O=(IX)×sizeof(double)
- 取完编址寄存器的内容自动加1,即 ( I X ) + + (IX)++ (IX)++
- 现在,问,某次循环所取的元素的地址是2100H的情况下,进入该次循环是的编址寄存器的内容?
- 设所求内容为X
- O = 8 X O=8X O=8X
-
2000
H
+
O
=
2100
H
2000H+O=2100H
2000H+O=2100H
- 8X=100H,为了便于计算,统一化为二进制(或者10进制)计算
- X = 1 6 2 2 3 = 2 8 2 3 = 2 5 X=\frac{16^2}{2^3}=\frac{2^8}{2^3}=2^5 X=23162=2328=25
- 所以X=32(十进制)
- Note:
- 由于计算机按照字节编址,所以地址值每加1,在内存上就对应(代表下一个字节的)
堆栈寻址
- 堆栈是存储器(寄存器组)中一块特定的,按照后进先出(LIFO)的原则管理的存储区
- 该存储区中读写单元的**地址(指针)**是用一个特定的寄存器给出
- 该寄存器称为堆栈指针
- 寄存器堆栈又称为硬堆栈
- 成本高
- 从主存中划分一段区域来做堆栈称为软堆栈(比较常用)
- 在采用堆栈结构的计算机系统中,大部分指令表面上都表现为无操作数指令心事
- 应为操作数地址都隐含使用了SP
- 通常,在读写堆栈中的一个单元的前后,都便有自动完成对SP内容的增量/减量操作
小结
-
寻 址 方 式 有 效 地 址 访 存 次 数 隐含寻址 程序指定 0 立即寻址 A 即是操作数 0 直接寻址 E A = A 1 一次间接寻址 E A = ( A ) 2 寄存器寻址 E A = R i 0 寄存器间接一次寻址 E A = ( R i ) 1 相对寻址 E A = ( P C ) + A 1 基址寻址 E A = ( B R ) + A 1 变址寻址 E A = ( I X ) + A 1 \begin{array}{c|c|c} \hline \text { 寻 址 方 式 } & \text { 有 效 地 址 } & \text { 访 } \text { 存 次 数 } \\ \hline \text { 隐含寻址 } & \text { 程序指定 } & 0 \\ \hline \text { 立即寻址 } & \mathrm{A} \text { 即是操作数 } & 0 \\ \hline \text { 直接寻址 } & \mathrm{EA}=\mathrm{A} & 1 \\ \hline \text { 一次间接寻址 } & \mathrm{EA}=(\mathrm{A}) & 2 \\ \hline \text { 寄存器寻址 } & \mathrm{EA}=\mathrm{R}_{i} & 0 \\ \hline \text { 寄存器间接一次寻址 } & \mathrm{EA}=\left(\mathrm{R}_{i}\right) & 1 \\ \hline \text { 相对寻址 } & \mathrm{EA}=(\mathrm{PC})+\mathrm{A} & 1 \\ \hline \text { 基址寻址 } & \mathrm{EA}=(\mathrm{BR})+\mathrm{A} & 1 \\ \hline \text { 变址寻址 } & \mathrm{EA}=(\mathrm{IX})+\mathrm{A} & 1 \\ \hline \end{array} 寻 址 方 式 隐含寻址 立即寻址 直接寻址 一次间接寻址 寄存器寻址 寄存器间接一次寻址 相对寻址 基址寻址 变址寻址 有 效 地 址 程序指定 A 即是操作数 EA=AEA=(A)EA=RiEA=(Ri)EA=(PC)+AEA=(BR)+AEA=(IX)+A 访 存 次 数 001201111
-
偏移寻址方式包括
- 相对寻址
- 基址寻址
- 偏移量是形式地址A的内容
- BR的内容在执行过程中是不变的
- 变址寻址
- 偏移量是变址寄存器IX的内容
- 形式地址A的内容执行过程中不变
-
依赖于寄存器的寻址方式
- 包括了偏移寻址方式的三种
- 还有寄存器寻址和寄存器间接寻址
- 共有5种设计寄存器的寻址方式
- 其中有4中可以使用通用寄存器实现,一种是程序计数器实现
例
- 设计算机有16个通过寄存器
- 采用32bit定长指令
- 操作码OP占8bit
- 包含了寻址方式位(用于指出计算操作数有效地址的方法)
- Store指令的源操作数和目的操作数分别用寄存器直接寻址和基址寻址
- E A = R i EA=R_i EA=Ri
- E A = ( B R ) + A = R i + A EA=(BR)+A=R_i+A EA=(BR)+A=Ri+A
- (即,有两个显示操作数,指令有2个(操作数)地址码)
- 两种寻址方式都各需要一个寄存器
- 它们都可以使用通用寄存器来实现
- 如果基址寄存器可以选用任意一个通用寄存器,那么由于寻址范围是16,恰为 2 4 2^4 24,所以需要用4bit来区分不同的寄存器(0000$\sim$1111)
- 那么两个操作数寄存器寻址占用了4+4=8位
- 而寄存器寻址不需要偏移量(不属于偏移寻址方式)
- 那么32位指令字长剩余32-8-4-4=16bit可以用来表示偏移量(A的位数16bit)
- Note:基址寻址的偏移量正是有形式地址A提供
- 如果是变址寻址,则由IX提供偏移量
- 如果使用补码来表示偏移量;那么表示范围为?
- 对于给定的16位,划分最高位1位作为符号位
- 还有n=15位作为数值位
- 那么根据补码的知识,可以表示的范围为:
- − 2 15 ∼ 2 15 − 1 -2^{15}\sim{2^{15}-1} −215∼215−1
- − 32768 ∼ 32767 -32768\sim{32767} −32768∼32767
混合/复合寻址
-
例如,先变址寻址后在间址寻址
- 假设指令格式为:
- O P ; M ; I ; D OP;M;I;D OP;M;I;D
- 其中OP操作码,M表示寻址方式
- I表示(变址)寄存器IX的编号
- D为形式地址
- 那么操作数的有效地址为:
- E A = ( ( I ) + D ) EA=((I)+D) EA=((I)+D)
- 其中 ( I ) + D (I)+D (I)+D对于变址寻址而言已经是有效地址
- 但是对于基址寻址和间址寻址的复合寻址方式,
(
I
)
+
D
(I)+D
(I)+D还不是有效地址
- 为了便于描述,借助C语言的取地址概念,那么可以描述为 & E A = ( I ) + D \&EA=(I)+D &EA=(I)+D
- 再次寻址 ( ( I ) + D ) ((I)+D) ((I)+D)才是有效地址
- 操作数 x = ( E A ) = ( ( ( I ) + D ) ) x=(EA)=(((I)+D)) x=(EA)=(((I)+D))
- 假设指令格式为:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)