是同一个地址。
你的疑惑应该是为什么不同的段地址能映射到同一个物理地址上?
简单点说,8086的环境里就是这么规定的,物理地址=段地址*16+段内偏移。
当然,如果是你自己设计的CPU,也完全可以让16位段地址只有高4位可用,或者把计算规则改成段地址*4096+段内偏移,等等,这样也都可以,前提是CPU是你自己做的,规矩是你自己定的。
8086环境下,CPU计算物理地址的时候,就是把段地址左移4位(乘16),再加上偏移地址,就得到物理地址了,CPU里有专门一个ALU用于完成这种计算,所以会有大量的地址是重复的,没关系,反正你记住这是规定就是了。
在32位环境里,段地址已经变成段描述符了,计算方法完全不同,同样的也是因为CPU里内置了地址转换的计算单元,32位环境里,地址一样也会重叠,重叠的花样更多。
内存控制器只管物理地址,CPU负责把段+偏移的地址转换成物理地址(如果有需要,可能还涉及分页),内存控制器看不到段地址,只能看到物理地址,转换由CPU完成,所以你不必担心内存怎么识别,这不是内存控制器该管的事情,如果你自己设计CPU,把段寄存器去掉都没问题。
再说为什么当年8086要这么设计,猜测的原因可能有以下几点:
1. 寄存器都是16位的,引入一个新寄存器,最好是跟通用寄存器一样的宽度,否则不好设计;
2. 为了让代码快速访问(如跳转指令),最好的方法是让段的长度足够大,否则长跳转用的太多会造成内存浪费(FAR比NEAR多2字节,包括JMP和CALL之类的),所以一个段的长度应该等于16位寄存器的最大值64K
3. 段的数量不宜太少,否则操作系统/编译器在分配内存时无法把一个未用满段再次分配给别人,比如1MB内存如果按64K不重叠的划分,只能分成16个段,如果段不能重叠,内存最多只能分成16份,最多加载16块可执行代码(某些代码入口必须是偏移地址为0),那么为了操作系统管理内存更方便,最好的办法就是让段的数量也足够多,操作系统管理内存更灵活。
结合以上3条,段要足够大、段要足够多、段寄存器是16位的,所以就变成了8086这样段长64K、段与段之间可重叠的情况了。