第3章 分段机制和逻辑地址

第3章 分段机制和逻辑地址

该章节主要介绍了寄存器的字长、如何访问内存、内存中的字节序以及8086的分段机制。

寄存器和字长

早期寄存器可以保存4比特、8比特、16个比特。现在的一般都是32位和64位。为了方便区分有一些常用叫法。

image

汇编里看到这样的指令:db、dw、dd、dq其实就是对应上面英文首字母的。

image

db、dw、dd、dq指令对应的含义(图片来源:tutorialspoint)
  • db:分配1个字节的空间;
  • dw:分配1个字(2个字节)的空间;
  • dd:分配2个字(4个字节)的空间;
  • dq:分配4个字(8个字节)的空间;

内存访问和字节序

如果要保存更多的数据,寄存器就不太够了,所以有了内存这玩意,可以保存大量的数据,现在家用电脑一般内存都8G、16G了,还有的更多。服务器级别上百GB也见过,非常牛B。

搜下现在的CPU,下面是酷睿i7 14代系列,二级和三级缓存都还是MB单位。

image

i7 14700K参数(图片来源于英特尔官网)

内存中的内每个字节都对应一个地址。

image

内存模型(来源书籍)

内存每个地址只对应1个字节,那么如果需要取出1个字(2个字节),那么是怎么取的呢?这个就涉及到字节序的问题了。

  • 如果访问内存中的一个字,那么,它规定高字节位于高地址部分,低字节位于低地址部分,这称为低端字节序(Little Endian)
  • 高字节位于低地址部分,低字节位于高地址部分,这称为高端字节序(Big Endian)

例子:往内存0x8000的位置写入一个双字(4字节)。

  mov dword [0x8000],0x87654321 ;写一个双字

低端字节序就是存数的低位存储在低位、存数的高位存储内存的高位。(以字节为单位)
image

高端字节序就是存数的低位存储在高位、存数的高位存储内存的低位。(以字节为单位)
image

低端字节序更符合计算机的计算逻辑,但是人眼看起来不太习惯,比如用Bochs查看内存分布(低端字节序),要从右向左读:

Bochs查看内存分布
image

古老的INTEL 8086处理器

8086是历史上很经典的一款产品,卖的多,往后的产品基于商业考虑,都要兼容之前的模式,所以要学习处理器,就要从8086开始。

8086的通用寄存器

8086的通用寄存器:

image

8086的8个通用寄存器(来源书籍)

8086是16位的处理器,寄存器都是16位的,可以拆成两个8位的寄存器,就可以向下兼容。同样往后的80386 32位处理器也是这样处理兼容性的。

程序的重定位难题

书中一开始提及到段(Segment)的概念,因为不管是指令还是数据都是存放在内存中,而处理器又是按顺兴执行指令的,如果指令和数据混杂在一起那么就会导致处理器无法正常工作。如果分成数据段和代码段问题就可以解决了。

image

(图片来源于书籍)

后面又阐述了程序重定位的难题主要是在于:

  • 每个电脑上都可以执行若干程序,每个程序的内存地址是随机分配的;
  • 如果程序开发者使用绝对内存地址那么就无法实现重定位;

image

(图片来源于书籍)

所以就需要一种机制可以方便实现程序的重定位。在8086上访问内存使用段地址和偏移地址,也就是逻辑地址,而不是实际物理地址。

这里其实也可以理解为多加了一层,想起《计算机组原理》成课程里面的系统复杂性管理的其中一个方法:层次化(Hierachy)

逻辑地址

书中介绍了段地址和偏移地址的概念,为后面一个小结引出8086的分段机制提供前置知识。

  • 段地址可以理解为起始地址;
  • 偏移地址就是相对于起始地址的偏移量;

一个指令在当前程序内的偏移地址不管哪台计算上都是固定的,也就是说如果使用这种机制,只要在不同的电脑上可以定位到段地址(程序起始地址)就可以了。

image

(图片来源于书籍)

image
如此,当这个程序被安装到不同的计算机上运行时,只需要修改段地址 A532 即可,管理上就方便了很多。

8086的内存分段机制

该章节一开始介绍了8086的内部结构。
image

(图片来源于书籍)

8086内部有4个段寄存器:

  • CS:Code Segment 代码段寄存器,16位。
  • DS:Data Segment 数据段寄存器,16位。
  • ES:Extra Segment 附加段寄存器,16位。
  • SS:Stack Segment 栈段寄存器,16位。

IP是指令指针(Instruction Pointer)寄存器,它只和CS一起使用,也是16位的。

::: tip
值的一提的是8086有一个6字节的指令预取队列,这个在几十年就有这种设计,真的是非常牛B。
:::

8086的寻址方式是:(CS) * 0x10 + (IP) = 物理地址。(CS)表示CS中存储的值,(IP)表示IP中存储的值。
例如 0xA532:0x0002 寻址示例图:

image

image

为什么这么寻址呢?书中说明了理由:

  • 8086有20根地址线,意味着可以寻址的空间:2^20=1024*1024=1MB。
  • 8086通过CS和IP共同寻址,两个寄存器都是16位的,相加最多17位,无法达到20位。
  • 如果只有16位的寻址空间,那么最大只有:2^16=64KB,不够用。

所以通过 (CS)*0x10,就可以把寻址空间提高到20位。

另外书中有一句话提到:

16位的段地址和16位的偏移地址相加,只能形成16位的物理地址,怎么得到这20位的物理地址呢?

这句话存在一点瑕疵:16位的段地址和16位的偏移地址相加,理论上最大可以有17位。例如:0xFFFF + 0xFFFF = 0x1FFFE,但确实无法得到20位的物理地址。

其他段寄存器:DS、ES和SS也是类似。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴空闲雲

感谢家人们的投喂

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值