🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

一、内存分段的核心原因

1. 硬件限制与寻址需求

2. 物理地址计算公式

二、关键概念与规则

1. 段的大小限制

2. 四大逻辑段及其寄存器

3. 段寄存器的作用

三、实模式与保护模式的分段差异

1. 实模式(8086兼容模式)

2. 保护模式(32位及以上)

四、编程实践要点

1. 段定义与初始化

2. 常见错误规避

3. 现代系统中的分段


img

汇编语言中的内存分段是为解决16位寄存器无法直接寻址1MB物理内存(20位地址空间)而设计的核心机制,通过段地址与偏移地址组合计算物理地址(公式:物理地址 = 段地址 × 16 + 偏移地址)。该机制将内存划分为逻辑段(代码段、数据段等),每个段最大64KB,起始地址必须16字节对齐(低4位为0),由段寄存器(CS/DS/SS/ES)存储段基值。实模式下分段是硬件寻址基础,保护模式则通过段描述符表扩展权限控制与4GB寻址能力。


一、内存分段的核心原因

1. 硬件限制与寻址需求

  • 8086 CPU采用20位地址总线(可寻址1MB内存空间),但寄存器仅16位,无法直接表示20位物理地址。
  • 分段机制通过二维寻址突破限制:将内存划分为多个逻辑段,每个段内用16位偏移地址寻址,段基址由16位段寄存器提供(左移4位后形成20位基址)。

2. 物理地址计算公式

  • 物理地址 = 段地址 × 16 + 偏移地址(等价于段地址左移4位后与偏移地址相加)。
    示例:若 CS = 2000hIP = 0300h,则物理地址 = 2000h × 10h + 0300h = 20300h
  • 段地址必须16字节对齐:因段寄存器值左移4位后低4位恒为0,故段起始地址低4位固定为0(如 2000h 对应物理地址 20000h)。

二、关键概念与规则

1. 段的大小限制

  • 最大64KB:由16位偏移地址决定($2^{16} = 65536$ 字节),段内地址范围不超过此值。
  • 最小16B:段寄存器值变化的最小单位为1(对应16字节偏移),当偏移地址仅使用低4位时达到最小段长。

2. 四大逻辑段及其寄存器

  • 代码段(CS):存储指令,配合指令指针 IP 定位下一条指令。
  • 数据段(DS):存储全局变量和常量,默认用于数据访问(如 MOV AX, [BX] 隐含使用 DS)。
  • 堆栈段(SS):管理函数调用和中断现场,配合栈指针 SP 使用。
  • 附加段(ES):常用于字符串操作的目标地址(如 MOVSB 指令)。

3. 段寄存器的作用

  • 存储段基值:16位段寄存器保存段起始地址的高16位(低4位隐含为0),不直接存储物理地址
  • 逻辑段映射:通过 ASSUME 伪指令声明段寄存器与逻辑段的绑定关系(如 ASSUME CS:CODE_SEG),但需手动初始化段寄存器值(如 MOV AX, DATA_SEG; MOV DS, AX)。

三、实模式与保护模式的分段差异

1. 实模式(8086兼容模式)

  • 直接物理寻址:段寄存器值左移4位后与偏移地址相加,结果即为物理地址
  • 无内存保护:所有程序共享同一地址空间,无法防止越界访问(如数据段与代码段重叠可能导致指令被误改写)。

2. 保护模式(32位及以上)

  • 段描述符机制:段寄存器存储段选择子(指向GDT/LDT中的描述符),描述符包含段基址、界限和权限标志。
  • 物理地址 = 段描述符基址 + 偏移地址:偏移地址受描述符中界限值约束,越界访问触发异常
  • 平坦模型(Flat Model):现代系统常将代码段和数据段基址设为0、界限设为4GB,逻辑上取消分段,但硬件仍需段寄存器支持。

四、编程实践要点

1. 段定义与初始化

  • 必须显式声明段:通过 SEGMENT/ENDS 伪指令定义逻辑段(如 DATA SEGMENT)。
  • 段寄存器初始化:DOS加载器仅设置 CS:IPDSSS 等需手动加载(如 MOV AX, DATA_SEG; MOV DS, AX),否则数据访问会指向随机内存。

2. 常见错误规避

  • 段未初始化:若 DS 未正确设置,数据访问将指向无效地址,导致崩溃。
  • 跨段访问未声明:使用 ASSUME 明确段寄存器映射,避免汇编器误判隐含段前缀(如 ES:[BX] 需显式指定 ES)。
  • 段越界:偏移地址超过64KB时需切换段寄存器,否则触发未定义行为。

3. 现代系统中的分段

  • 保护模式为主流:分段主要用于权限隔离(如内核态/用户态),实际内存管理依赖分页机制
  • 平坦模型普及:Windows/Linux等系统通过将所有段基址设为0,逻辑上视为单一4GB线性空间,简化编程模型。

内存分段是理解x86架构演进的关键:实模式下为突破16位寻址限制的硬件设计,保护模式下演变为内存保护与权限控制的基石。尽管现代系统多采用平坦模型,但段寄存器仍参与地址转换,且汇编级开发(如操作系统内核、引导程序)必须掌握分段机制以避免低级错误。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐