x86汇编寻址理解

来源:互联网 发布:人工智能美国专业排名 编辑:程序博客网 时间:2024/05/18 04:00

        在cpu地址编码中,我以前接触过arm,avr的寻址方式,一般都是直接编码,地址映射就是地址总线的物理地址编码。而最近接触到IA32的汇编语言,感觉比arm复杂得多。所以做个学习笔记标记。

       在arm中,一般寻址都是在总线编码范围内寻址。而在x86中,分为实模式和保护模式,实模式是指在16为段地址编码下的寻址模式。因为intel cpu在最初的时候使用20位的地址总线,而寄存器只有16位,所以为了能够使16位的寄存器寻址到2#20次方,即1m的地址范围。不得不使用了一个叫做段的概念。即加了一个16位的段寄存器来和16位的通用寄存器进行对20位地址总线的寻址。寻址方式为:物理地址=16位 段寄存器左移4位+16位的段内偏移地址(一般使用16位寄存器来保存)。由这个公式可以看出,一共1m的地址,我们可以使用一个16位段寄存器加上一个16位的其他寄存器寻址到1m地址空间中的任意地址,这里还有一个注意的地方,在寻址时,可能存在两个寄存器的地址值不同,而计算出的地址相同的情况。如0012:0004 = 0010:0024 = 00124。intel的cpu由于为了向上兼容,所以以后的cpu都支持实模式。而且在cpu启动的时候,是以实模式方式启动的。

      保护模式,在IA32以后,由于地址总线和数据总线都是扩充到了32位,直接能寻址到4g的地址,所以不用担心寻址问题,但是,为能够保持cpu的向上兼容,依然使用了段的概念但是呢,和实模式下的寻址已经有了很大的不同。

      保护模式下:依然使用 实际地址(物理地址) = 段地址:段偏移地址这个方式进行寻址。但是寻址方式在实模式的基础上,使用了 地址表的概念。即,在保护模式下,我们不会直接使用段寄存器来存储地址,而只是存储一个地址索引值(即偏移地址值,即相对于GDT表其实地址的值,还有叫选择子),我们使用一个GDT和LDT的段结构表,在GDT结构中,包括,段基地址,段地址界限(即段结束的地址),还有段的属性配置。所以我们要使用一个段,我们就是用这个GDT结构(64B,8字节的结构)来配置我们的段,然后将所有的GDT结构放在一个地方,组成一个GDT表。以后我们需要对那个段进行寻址时,就使用哪个段寄存器来找GDT表,找到我们事先提供的每个段的GDT配置,这样就能够使用段寄存器找到我们事先定义的每个段的基地址值了。而段里面的每个地址,我们都可以使用相对于段基地址的偏移地址来寻址。这样做有很多好处,比如可以根据需要配置每个段的属性,安全,特权级别等等。整体寻址思路为:1,配置每个段的GDT结构的基地址和界限还有属性,2.将所有的GDT表存入gdtr寄存器,3.将GDT表中每个段的基地址,进行初始化,4.将需要寻址的段偏移地址存入段寄存器,这样操作得到了每个段的基地址,5最终的实际地址 = 段寄存器:段内的偏移地址。这样,GDT表中的32位段基地址加上每个段的段内地址上限20位,寻址空间达到了巨大的容量(当然这里没有考虑到页的模式)。

     

0 0