是同一個地址。你的疑惑應該是為什麼不同的段地址能對映到同一個物理地址上?簡單點說,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位暫存器的最大值64K3. 段的數量不宜太少,否則作業系統/編譯器在分配記憶體時無法把一個未用滿段再次分配給別人,比如1MB記憶體如果按64K不重疊的劃分,只能分成16個段,如果段不能重疊,記憶體最多隻能分成16份,最多載入16塊可執行程式碼(某些程式碼入口必須是偏移地址為0),那麼為了作業系統管理記憶體更方便,最好的辦法就是讓段的數量也足夠多,作業系統管理記憶體更靈活。結合以上3條,段要足夠大、段要足夠多、段暫存器是16位的,所以就變成了8086這樣段長64K、段與段之間可重疊的情況了。
是同一個地址。你的疑惑應該是為什麼不同的段地址能對映到同一個物理地址上?簡單點說,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位暫存器的最大值64K3. 段的數量不宜太少,否則作業系統/編譯器在分配記憶體時無法把一個未用滿段再次分配給別人,比如1MB記憶體如果按64K不重疊的劃分,只能分成16個段,如果段不能重疊,記憶體最多隻能分成16份,最多載入16塊可執行程式碼(某些程式碼入口必須是偏移地址為0),那麼為了作業系統管理記憶體更方便,最好的辦法就是讓段的數量也足夠多,作業系統管理記憶體更靈活。結合以上3條,段要足夠大、段要足夠多、段暫存器是16位的,所以就變成了8086這樣段長64K、段與段之間可重疊的情況了。