段寄存器

一、段寄存器有哪些 ?

段寄存器有ESCSSSDSFSGSLDTRTR8个。

ES:扩展段。在串操作时(比如cmovs)目标操作数的基址是ES,源操作数是DS

CS:代码段,配合EIP使用。

SS: 堆栈段,凡是基址是EBPESP的,段前缀就是SS

DS:数据段,默认的都是DS

FSGS80386 之后定义的。

段寄存器结构:

段寄存器的大小是 96 位

段寄存器结构可以抽象成以下结构

struct Segment

{

  WORD Selector;  //16位段选择子,可见部分.  使用OD 或者X64dbg看段寄存器只会显示16位的段选择子可见部分.当读段寄存器(如mov ax,CS)的时候,只会返回这16位。或者push seg 操作针对的都是这16位。如果目标操作数是32位(如mov eax ,CS),则将16位零扩展成32位赋给目标操作数。但是写的时候,就会涉及到96位

  WORD Attribute; //16位表示的段属性, 表示了当前段寄存器是可读的可写的还是可执行的

  DWORD Base;     //32位表示的基址,表示段从哪里开始

  DWORD limit;    //32位表示,表示的是基址的长度. base + limit 可以确定一个段的大小

}

在x86下.我们可以看如下寄存器表示图.

寄存器名称

段选择子(Select)

段属性(Attributes)

段基址(Base)

段长(Limit)

ES(附加扩展段)

0x0023

可读,可写

0x00000000

0xFFFFFFFF

CS(代码段)

0x001B

可读,可写

0x00000000

0xFFFFFFFF

SS(堆栈段)

0x0023

可读,可写

0x00000000

0xFFFFFFFF

DS(数据段)

0x0023

可读,可写

0x00000000

0xFFFFFFFF

FS(分段机制)

0x003B

可读,可写

0x7FFDF000

0xFFF

GS

未使用

未使用

未使用

未使用

 

二、段寄存器读写

可以使用MOV指令对段寄存器进行读写。

读操作时,可以读到段寄存器的段选择子部分的16位。例如 mov ax,es 指令会把es寄存器的段选择子读到ax。

写操作时,会写入96位,其中源操作数的16位写入到段寄存器的段选择子部分,另外80位会根据段选择子从GDT表(全局描述表)中获取。因此,

1 .mov ax,cs

2. mov ds,ax

实际上是把cs完整的复制给了ds。

三、段属性探测

CS代码段属性探测

int Var = 0;

int main()

{  

    __asm   

    {      

        mov ax,cs      

        mov ds,ax       

        mov dword ptr ds:[Var],eax         ;等价于 mov dword ptr cs:[Var],eax  

    }

}

将CS赋值到AX中. AX赋值给DS. 此时DS就代表CS了. 如果以把eax之给 CS.则会出现错误.

说明权限确实是不可写.

其它代码段段属性探测

int Var = 0; int main()

{   

    __asm   

    {       

        mov ax,ss

        mov ds,ax       

        mov dword ptr ds:[Var],eax   

    }

}

段基地址探测

通常我们用汇编读写某一个地址时,如下:
Mov dword ptr ds:[0x123846],eax
这时我们把eax 的值往地址去写,写的地址是:
ds.base + 0x123456

int main()

{

    __asm

    {

        mov ax,fs

        mov gs,ax

        mov eax,gs:[0]

    }

}

段长探测

在段地址探测中,访问有效地址等价于段.base + 偏移地址

int main()

{

    __asm

    {

        mov ax, fs

        mov gs, ax

        mov eax, gs: [0]  //fs.base + 0 读取

        mov eax,gs:[0x1000]//fs.base + 0x1000

        mov eax, dword ptr ds : [eax + 0xFFF] ;

       // mov eax,gs:[0x1000] //fs.base + 0x1000 读取

    

    }

}

<think>嗯,我现在要介绍一下8086的段寄存器。首先,我得回忆一下8086处理器的基本结构。8086是Intel早期的16位微处理器,它的寻址方式有什么特点呢?对了,它采用了分段内存管理,这样可以用16位的寄存器来访问更大的内存空间。 段寄存器应该是用来存储这些内存段的基地址的。常见的段寄存器有CS、DS、SS、ES这几个对吧?那每个段寄存器的作用可能不同。比如,CS是代码段寄存器,指向当前执行的代码段;DS是数据段寄存器,指向数据段;SS是堆栈段寄存器,用于堆栈操作;ES是附加段寄存器,可能在处理字符串等操作时使用额外的数据段。 不过具体的,每个段寄存器对应的用途需要准确描述。比如,CS:IP组合决定下一条要执行的指令地址,DS和ES用于数据访问,SS:SP或SS:BP用于堆栈操作。此外,段寄存器与偏移地址的组合形成20位的物理地址,计算方式是段寄存器左移4位加上偏移地址。比如,DS=0x1234,偏移地址0x5678,物理地址就是0x12340 + 0x5678 = 0x179B8。 可能还需要说明为什么需要分段管理,因为8086的地址总线是20位,而寄存器只有16位,所以通过分段机制可以访问1MB的内存空间。每个段最大64KB,因为偏移地址是16位的。这样,虽然每个段不超过64KB,但通过改变段寄存器的值,可以覆盖整个1MB内存。 另外,段寄存器的使用示例可能有帮助。比如,MOV指令中如何指定段寄存器覆盖默认的段。例如,MOV AX, [BX]默认使用DS,但可以用段前缀如MOV AX, ES:[BX]来使用ES段。 还需要注意段寄存器的限制,比如某些指令必须使用特定的段寄存器,如堆栈操作PUSH和POP必须使用SS,指令的取指必须使用CS等。 检查一下是否有错误的地方。例如,段寄存器存储的是段基址的高16位,左移4位后加上偏移得到20位地址。每个段寄存器对应的段类型是否正确。另外,是否有其他段寄存器,比如后来的80386有更多的段寄存器,但8086只有四个:CS、DS、SS、ES。 总结来说,段寄存器的作用、各个寄存器的用途、地址计算方式以及分段机制的原因都是需要涵盖的点。要确保语言准确,例子正确,没有技术错误。</think>8086处理器的段寄存器是其内存分段管理机制的核心组成部分,主要用于生成20位的物理地址,从而支持1MB内存空间的访问。以下是关键要点: ### 一、段寄存器的作用 1. **地址扩展** 8086为16位架构,但通过`段基址×16 + 偏移量`的计算方式(例:段寄存器值`0x1234`左移4位得`0x12340`,加上偏移`0x5678`,最终地址`0x179B8`),实现20位物理地址,突破16位寻址限制。 2. **分段管理** 将内存划分为代码、数据、堆栈等逻辑段,各段最大64KB(偏移地址16位)。 ### 二、4个段寄存器及用途 | 段寄存器 | 名称 | 用途 | |----------|---------------|----------------------------------------------------------------------| | **CS** | 代码段寄存器 | 指向当前执行的代码段,与**IP**寄存器组合确定下一条指令地址(CS:IP) | | **DS** | 数据段寄存器 | 指向默认数据段,用于大多数数据操作(如`MOV AX, [BX]`默认使用DS) | | **SS** | 堆栈段寄存器 | 管理堆栈区域,与**SP/BP**寄存器配合处理堆栈操作(如PUSH/POP指令) | | **ES** | 附加段寄存器 | 作为辅助数据段,常用于字符串操作(如`MOVSB`指令使用ES:DI目标地址) | ### 三、关键特性 1. **段覆盖前缀** 可通过显式指定段寄存器覆盖默认段,例如: ```assembly MOV AX, ES:[BX] ; 使用ES而非默认的DS ``` 2. **硬件强制关联** - 指令取指**必须**通过CS段 - 堆栈操作(PUSH/POP)**必须**使用SS段 3. **编程影响** 开发者需手动管理段寄存器,例如: ```assembly MOV AX, @DATA MOV DS, AX ; 初始化数据段 ``` ### 四、设计意义 - **兼容性与扩展性**:在16位寄存器基础上实现1MB内存访问,为后续x86架构奠定基础。 - **多任务支持雏形**:通过分段隔离代码、数据和堆栈,为后期保护模式提供演进路径。 ### 示例:物理地址计算 若`CS=0x0200`,`IP=0x0100`,则: 物理地址 = `0x0200 << 4 + 0x0100 = 0x2000 + 0x0100 = 0x2100` 通过这种机制,8086在硬件资源有限的情况下,高效地扩展了内存寻址能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值