问题描述
当一个16位字要从一个奇数内存地址(比如125)的内存中读取时, 8086 C P U 8086CPU 8086CPU首先把 124 124 124放在地址总线上,并在数据高8位中获得125位置的内容。在下一个时钟周期中, 8086 C P U 8086CPU 8086CPU将 126 126 126放在地址总线上,并在数据低8位中获取 126 126 126地址的内容。这两个字节然后由处理器交换,因为这些值在数据总线的错误位置(高8位低8位相反位置)进入CPU。
上述操作需要2个时钟周期。为什么CPU不能简单地将地址125放在地址总线上,然后计算下一个地址,并将该地址的内容(在本例中为126)放在数据总线的低阶字节上?低阶字节和高阶字节可以稍后交换,允许处理器仅在1个时钟周期内从内存中获取16位值。
原因分析
先给出8086引脚图。
8086CPU
有20根地址线:
A
0
:
A
19
A0:A19
A0:A19,有16根数据线:
D
0
:
D
15
D0:D15
D0:D15。实际上16个数据线和20根地址线的低16位是相同的引脚,也称为
A
D
15
:
A
D
0
AD15:AD0
AD15:AD0。它们的功能是在同一个时钟周期的第一部分充当地址线,在后一部分充当数据线。寻址同样重要的是一个引脚称为
B
H
E
‾
\overline{BHE}
BHE,用于“总线高位使能”。同时地址线最低bit
位
A
0
A0
A0 也作为“使能”引脚,用于“总线低位使能”,稍后我们将看到。
B H E ‾ \overline{BHE} BHE信号和 A 0 A0 A0一样,低电平有效。
两次时钟周期读取原因分析
如果
8086
8086
8086 想要读取地址
124
−
125
124-125
124−125 处的
16
b
i
t
16bit
16bit字,则先将地址124
放在地址线
A
19
:
A
0
A19:A0
A19:A0 上,并将
B
H
E
‾
\overline{BHE}
BHE设置为低电平。此时由于
A
0
A0
A0和
B
H
E
‾
\overline{BHE}
BHE都是低电平有效,所以高位低位两个8bit
数据同时有效。高8位数据放在
D
15
:
D
8
D15:D8
D15:D8上,低8位数据放在
D
7
:
D
0
D7:D0
D7:D0上,
C
P
U
CPU
CPU得到一个完整的字。
如果 8086 8086 8086 想要读取地址 124 124 124的单个字节数据,则将地址 124 124 124放在 A 19 : A 0 A19:A0 A19:A0上,并将 B H E ‾ \overline{BHE} BHE设置为高电平。由于 A 0 A0 A0低电平(有效),低8位数据放在 D 7 : D 0 D7:D0 D7:D0 上,但由于 B H E ‾ \overline{BHE} BHE为高电平,高8位数据什么也不做。
如果 8086 8086 8086 想要读取地址 125 125 125的单个字节,则将地址 125 125 125放在 A 19 : A 0 A19:A0 A19:A0上,并将 B H E ‾ \overline{BHE} BHE设置为低电平。因为 A 0 A0 A0为高电平,低8位数据什么也不做,因为 B H E ‾ \overline{BHE} BHE低电平有效,高8位数据放在 D 15 : D 8 D15:D8 D15:D8 上。
这是三种可能的情况( A 0 A0 A0高和 B H E ‾ \overline{BHE} BHE高电平则高低位数据同时无效,所以它没有做任何事情)。注意,地址线高19位 A 19 : A 1 A19:A1 A19:A1在所有三种情况下都是相同的,并且它们在整个时钟周期中不会改变。如果 8086 8086 8086想要在地址 125 − 126 125-126 125−126处读取一个 16 b i t 16bit 16bit字,而这两个地址在 A 19 : A 1 A19:A1 A19:A1上有不同的位,所以它需要两次内存读操作。
读取之后处理器交换高低数据原因分析
按照小端序的存储方式,一个 16 b i t 16bit 16bit 数据 0 x 1234 0x1234 0x1234 在地址 a d d r addr addr处的存储方式应该为: a d d r addr addr地址存储内容为 0 x 34 0x34 0x34, a d d r + 1 addr+1 addr+1地址存储内容为 0 x 12 0x12 0x12。那么当 C P U CPU CPU同时高低位使能时,取出一整个字,此时高位数据 0 x 12 0x12 0x12放数据线 D 15 : D 8 D15:D8 D15:D8,低位数据 0 x 34 0x34 0x34放数据线 D 7 : D 0 D7:D0 D7:D0 上,共同组成正确数据 0 x 1234 0x1234 0x1234。
当数据位于地址 125 125 125位置时, C P U CPU CPU第一个时钟周期取数据时将地址 125 125 125放地址线,将 B H E ‾ \overline{BHE} BHE设置为低电平,此时低位数据 0 x 34 0x34 0x34位于数据线的高8位。 C P U CPU CPU第二个时钟周期取数据时将地址 126 126 126放地址线,将 B H E ‾ \overline{BHE} BHE设置为高电平,此时高位数据 0 x 12 0x12 0x12位于数据线的低8位,数据线数据为 0 x 3412 0x3412 0x3412。刚好和真实数据相反。所以需要处理器交换两字节位置。
知识扩展
根据上述描述把相关原理扩展到32bit处理器中在对不对齐地址数据的读写操作中,可以有如下图所示内容:
第一个时钟周期先在上一个对齐字中读取一部分数据,第二个时钟周期再从下一个对齐字中读取剩余数据,将两次数据做适当移位合并为最终数据。