2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)
[ ] 6个段寄存器(ES、CS、SS、DS、FS和GS)
ECS——代码段寄存器(Code Segment Register),其值为代码段的段值;
EDS——数据段寄存器(Data Segment Register),其值为数据段的段值;
EES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
ESS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;
EFS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
EGS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。
80x86寻址,段的寻址技术,把内存空间分为一个或多个称为段的线性区域,从而段地址+段内偏移地址转换线性地址。16位段+32位段内地址。6个段寄存器存放段地址。
由段寄存器SS寻址的段-堆栈段,栈顶由ESP寄存器内容指定。堆栈顶处地址SS:[ESP]。
具体转换:
1.实模式下:段地址在段寄存器中如DS+段偏移地址在存放在任意一个可用于寻址的寄存器中(例如SI)——>实际内存地址
具体:
1.实模式
80X86系列CPU中,最早的是8086,它有20根地址线,可以寻址1MB(2^20)内存空间。很自然地,如果CPU要跟主存交换信息,它也必须有20位的物理地址,但是,8086CPU内部是16位的结构,它里面跟地址有关的寄存器都是16位的(8086中跟地址有关的寄存器有五个:SI,DI,BP,SP,IP,前四个是变址寄存器,最后一个是指令指示器,它保存的是CPU将要执行的下一条指令的偏移地址),因此只能进行16位地址运算,寻找操作数的范围也只能是64KB以内,怎么办?以下是8086的设计人员想出的办法:
a.主存分段:将1M的主存分段,每段为16位寻址的最大值(64KB)。这样,对于每一个段,我们只需要一个寄存器就可以寻址整个段。(我们把这个叫偏移地址,8086中有专门的寄存器来寄存这些地址:IP,SP,BP,SI)
b.左移获得段基址
但是不管怎样,主存还是20位的,我们能根据寄存器知道每一个段内地址的索引,怎样知道整个主存中的位置呢,也就是怎么得到基址呢?设计人员是这样想的,不就是高四位吗,好,我将寄存器的值左移四位,从逻辑上来讲,不就是20位了吗?把这个当做段的基址。(这个段首址也用专用的寄存器存放:CS,DS,SS,ES(386加了FS,GS附加数据段)四个段寄存器)这样,我们就既能寻址到主存中任意位置的物理地址了,具体如下:
对于CS(代码段):物理地址PA = (CS)左移四位+(IP)
对于SS(堆栈段):物理地址PA = (SS)左移四位+(SP)
对于DS(代码段):物理地址PA = (DS或ES、FS、GS)左移四位+(偏移地址)
——偏移地址寄存器根据寻址方式而定
2.保护模式下:段寄存器存放的是一个段描述符表中某一描述符项在表中的索引值,或者也叫选择符。
保存描述符项的描述符表有3种类型:GDT是主要的基本描述符表,可用于引用访问一个内存段。中断描述符表IDT保存有定义中断或异常处理过程的段描述符。LDT作为GDT的补充。定位该三个表-GDTR,LDTR,IDTR三个特殊寄存器。