程序中的“段”是咋回事~

b2f26c321b00e8584c9b631377107600.gif

正文


大家好,我是bug菌~

国庆节还在发文章太不厚道了,最近在回顾一些技术知识,顺便记录下,大家玩累了看看技术文章挺好的。

1

段的概念

在计算机架构中,段的概念是用于组织和管理内存的一种方式,特别是在早期的 x86 架构中,什么8086处理器啥的,不过现在很多概念一直沿用。

每个段代表了内存中的一个逻辑区域,用于不同类型的数据或代码。这种分段机制可以提高程序的灵活性和安全性。

下面是一些常见的段类型:

1. 代码段 (Code Segment, CS)

代码段主要是存储程序的可执行指令。

该段只读,防止程序在运行时意外修改其自身的指令。包含所有执行的逻辑,通常以机器指令的形式存在。

2. 数据段 (Data Segment, DS)

数据段存储程序运行所需的全局变量和静态变量。

该段可读可写,允许程序在运行过程中修改数据。

初始化部分存储初始值,未初始化部分(BSS 段)通常会被默认设置为零。

3. 堆栈段 (Stack Segment, SS)

定义:堆栈段用于存储函数调用时的局部变量、返回地址以及其他临时数据。

该段采用后进先出(LIFO)的结构。

支持函数调用和返回,存储参数和局部变量。

当然我们分析elf文件的时候会发现还有很多类型的段:

  • .text:包含可执行代码。
  • .data:包含已初始化的全局变量和静态变量。
  • .bss:包含未初始化的全局变量和静态变量,其大小在程序加载时会被设置为 0。
  • .rodata:包含只读数据,例如字符串常量。
  • .symtab:符号表,存储程序中的符号信息。
  • .strtab:字符串表,存储符号名称和其他字符串。
  • .rel 或 .rela:重定位信息,用于链接器处理地址修正。

2

段带来的好处

内存保护:通过不同的段,可以对内存区域进行访问控制,防止程序错误地修改其他段的内容。

模块化:代码段和数据段的分离使得程序的结构更加清晰,有助于模块化设计和维护。

动态内存管理:分段允许程序在运行时动态地请求和释放内存,提高了内存利用率。

虽然在现代计算机架构中,分段机制可能不再广泛使用,但其基本思想仍然影响着内存管理的设计和实现。

3

段的特点

段内的地址通常被视为连续的。这意味着在一个特定的段(如代码段、数据段或堆栈段)内,地址是顺序排列的,从段的起始地址到段的结束地址。

连续性:

段内的地址是连续的,这使得访问和管理内存更为简单。例如,在数据段中,变量的地址会依次排列,便于程序在运行时进行访问。

逻辑划分:

虽然物理内存可能是不连续的,但逻辑上每个段的地址范围是连续的。操作系统通过内存管理单元(MMU)来处理虚拟地址与物理地址之间的映射。

段的大小:

每个段的大小可以不同,代码段可能比数据段大,或者相反。但在每个段内部,地址是线性且连续的。

分隔符:

段之间的地址通常不连续,段的开始和结束由段寄存器管理。例如,如果一个段的起始地址是 0x1000,而下一个段的起始地址是 0x2000,那么这两个段之间的地址并不连续。

4

段寻址示例

8086的分段寻址算是最早期、最简单的分段机制了,该分段寻址过程涉及段寄存器和偏移量的组合,即段寄存器内存左移+偏移量便得到了索要访问的地址。

那为什么需要将段寄存器的内容左移 4 位并与偏移量相加,很多朋友并不是很理解,我们可以从以下几个方面进行解析:

在 x86 架构中,段寄存器包含的是段的基地址,而这个基地址是以 16 字节为单位的。

偏移量的概念:偏移量是指在指定段内的具体位置,它是以字节为单位的。

物理地址的计算:

段寄存器的值左移 4 位(即乘以 16)是因为其内容实际上表示的是段的起始地址,以 16 为单位。例如,如果段寄存器中的值是 0x000A(十六进制),那么左移后得到的物理地址为 0x000A0。

将左移后的段基地址与偏移量相加,就可以得到实际的物理地址。

1MB 的内存限制:在 x86 体系结构中,20 位的物理地址可以表示最大 2^20 = 1MB 的内存空间。这是因为 20 位二进制数的范围是从 0 到 1,048,575(0x000000 到 0xFFFFF)。

所以将段寄存器的内容左移 4 位后加上偏移量,我们能够综合得到一个 20 位的物理地址,从而能够有效访问最多 1MB 的内存空间。虽然现代计算机系统中没有在选用这种方式,但核心思想并没有发生很大的变化。

最后

      好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个~

永久、免费分享嵌入式技术知识平台~

推荐专辑  点击蓝色字体即可跳转

☞  MCU进阶专辑 d9e7981e8824d3ac4c1c77305299982b.gif

☞  嵌入式C语言进阶专辑 f4ed3c7d0a374459aac85c2d2e6daa2d.gif

☞  “bug说”专辑 8a16f577e2c1d23923b3224ee4e8f2c2.gif

☞ 专辑|Linux应用程序编程大全

☞ 专辑|学点网络知识

☞ 专辑|手撕C语言

☞ 专辑|手撕C++语言

☞ 专辑|经验分享

☞ 专辑|电能控制技术

☞ 专辑 | 从单片机到Linux

ce2ee5b33a2521beea59ff1963de2843.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值