4 寻址机制

前面,bochs加载代码清单1进入实模式,在显示屏上打印字符串,然后进入死循环。那么如何让实模式跳转到保护模式呢?那么就不得不说实模式和保护模式的寻址机制了。


1实模式寻址机制


由于实模式下只有20根地址线可用,它的寻址能力为:

1M =220* 8bit

由于每位地址指向一个字节8bit,所以后面我们乘于8bit。一个地址由段和偏移地址决定,计算公式如下:

物理地址(PhysicalAddress=段值(Segment* 16 +偏移(Offset

段乘于16表示将段左移4位,然后和偏移构成20位的地址。注意的是,在实模式中段值和偏移都为16位。


2保护模式寻址机制


保护模式有32根地址线可用,它的寻址能力为:

4G =232* 8bit

保护模式下一个地址也是由段和偏移地址构成,但是段中存储的不是地址,而是GDT(会LDT)的索引值。通过索引值找到GDT中的数据项(段描述符),段描述符中才实际存储段地址值。保护模式寻址机制如图1所示。


1保护模式寻址机制


3什么是GDT


既然从实模式进入保护模式涉及到GDT,那么就要了解GDT的结构。GDT实际就是容器,它存储的段描述符由8个字节构成。如图2所示


2GDT中段描述符结构


4编写GDT段描述符


;------------------------------------------------------------------------------------------------------

;

;描述符

;usage: Descriptor Base, Limit, Attr

; Base: dd

; Limit: dd (low 20 bits available)

; Attr: dw (lower 4 bits of higher byte are always 0)

%macroDescriptor3

dw %2& 0FFFFh ;段界限1

dw %1& 0FFFFh ;段基址1

db (%1>> 16) & 0FFh ;段基址2

dw ((%2>> 8) & 0F00h) | (%3 & 0F0FFh) ;属性1+段界限2+属性2

db (%1>> 24) & 0FFh ;段基址3

%endmacro;


宏有3个参数,在宏体中用%12%3%表示,1%32位基址,2%为少于20位的段界限,3%为少于4位的属性。


宏中对三个参数进行了拆分组合生成8字节的段描述符。


5将段描述符放入GDT


[SECTION.gdt]

;GDT

;段基址,段界限 ,属性

LABEL_GDT: Descriptor 0, 0, 0 ;空描述符

LABEL_DESC_CODE32:Descriptor 0,SegCode32Len- 1, DA_C + DA_32 ;非一致代码段

LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ;显存首地址

;GDT结束


gdt段中,存储了3个段描述符。分别时空描述符LABEL_GDT32位代码段描述符、视频段描述符。


[SECTION.s32]; 32位代码段.由实模式跳入.

[BITS 32]

LABEL_SEG_CODE32:

mov ax,SelectorVideo

mov gs,ax ;视频段选择子(目的)

mov edi,(80 * 11 + 79) * 2 ;屏幕第11,79列。

mov ah,0Ch ; 0000:黑底 1100:红字

mov al,'P'

mov [gs:edi],ax

;到此停止

jmp $

SegCode32Len equ $- LABEL_SEG_CODE32

;END of [SECTION .s32]


其中在32位代码段描述符中,SegCode32Len– 1表示32位代码段的长度(即段界限),减去1是应为从0开始计算。


;GDT选择子

SelectorCode32 equ LABEL_DESC_CODE32 -LABEL_GDT

SelectorVideo equ LABEL_DESC_VIDEO -LABEL_GDT

;END of [SECTION .gdt]


这里可以看出SelectorCode32SelectorVideo为索引值,表示在GDT中的位置。从这里也可以猜测空描述符的作用。


6设置段描述符


段寄存器存放的是GDT的索引值,但是段描述符中的32位代码段基址为0,视频段为0B8000h。很明显32为代码段的地址并不是0,显存的代码段为0B8000h。在实模式下设置32位代码段基址。


[SECTION.s16]

[BITS 16]

LABEL_BEGIN:

mov ax,cs

……

;初始化32位代码段描述符

xor eax,eax

mov ax,cs

shl eax,4

add eax,LABEL_SEG_CODE32

mov word[LABEL_DESC_CODE32 + 2], ax

shr eax,16

mov byte[LABEL_DESC_CODE32 + 4], al

mov byte[LABEL_DESC_CODE32 + 7], ah

……


这里将代码寄存器cs(存放执行代码段地址)左移4位(段*16),然后和32位代码段LABEL_SEG_CODE32在执行代码段中的地址(偏移地址)相加。得到物理地址存放到eax中。然后将eax拆分组合放到LABEL_DESC_CODE32描述符中段基址地方。


现在段描述符都初始化好了,可以加载gdtr了。


7加载gdtr


GDTR是一个长度为48bit的寄存器,内容为一个32位的基地址和一个16位的段限。其中32位的基址是指GDT在内存中的地址。


[SECTION.gdt]

……

LABEL_GDT: Descriptor 0, 0, 0 ;空描述符

……

;GDT结束


GdtLen equ $- LABEL_GDT ; GDT长度

GdtPtr dw GdtLen- 1 ; GDT界限

dd 0 ;GDT基地址;为加载GDTR作准备

……

xor eax,eax

mov ax,ds

shl eax,4

add eax,LABEL_GDT ; eax <- gdt基地址

mov dword[GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt基地址

;加载GDTR

lgdt [GdtPtr];将GDT地址赋值给gdtr


代码将数据段赋值给ax,然后左移4位,加上GDT在程序中的偏移地址。这个值为GDT的物理地址。最后将这个地址赋值给dword[GdtPtr + 2]


完成这些之后,再进行:

  • 关闭实模式下中断

  • 打开A20

  • 设置cr0PE

  • 跳转进入保护模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HBase是一个分布式的列存储数据库,它的数据存储在HDFS中,采用了一种称为“HRegion”的存储单元进行管理。HRegion是一个逻辑上的数据存储单元,它由一系列的HStore组成,每个HStore包含了一系列的HFile。HFile是HBase中数据存储的最小单元,它是一个按照一定格式进行组织的文件。每个HFile中存储了一些行键范围内的数据,这些数据按照列族和列限定符进行组织。HBase利用HFile的这种存储方式,使得数据可以被高效地查询和访问。 当客户端需要访问HBase中的数据时,它需要先通过HBase客户端API向ZooKeeper请求获取当前正在服务的RegionServer列表。然后,客户端根据要访问的数据的行键,计算出该数据所在的Region的信息,包括Region的名称和Region所在的RegionServer的地址。在获取到RegionServer地址之后,客户端将数据查询请求发送给该RegionServer,RegionServer会根据数据的行键在本地的HRegion中查找相应的数据,并将结果返回给客户端。 HBase的寻址机制主要是通过行键分片实现的。HBase将所有的数据按照行键进行排序,并将数据划分成若干个连续的区间,每个区间对应一个HRegion。当客户端需要访问某个数据时,它会首先计算出该数据所属的区间,然后根据该区间对应的HRegion的信息进行访问。在HRegion内部,HBase采用了一种称为“MemStore”的内存缓存机制,用于缓存最近写入的数据。当MemStore中的数据积累到一定程度时,HBase会将其中的数据写入磁盘中的HFile中。这样可以有效地提高HBase的写入性能和数据的可用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值