Orange's:一个操作系统的实现 Descriptor 3宏详解

补充:关于GDT/LDT、段选择子和段描述符的解释
      GDT/LDT:GDT/LDT是段描述符表,里面定义了每个段的段描述符的界限和属性,而段描述符的基址是在代码段中初始化的。
      其中,LDT是局部描述符表,LDT在GDT中也有段描述符,LDT还有其对应的选择子,除此以外,LDT的功能和GDT一样。

      段选择子:段选择子是用来寻址段描述符的,即段描述符定义在GDT中,由段选择子将其赋值给段寄存器。如果TI被置位为1,那么系统将从当前LDT中寻找相应描述符,TI为0就从GDT中寻找相应描述符。

这是段选择子的结构:
Orange's:一个操作系统的实现 Descriptor 3宏详解_第1张图片
      段描述符:定义了段的基址,界限和属性,定义在GDT中,由段选择子寻址。段描述符先在实模式中初始化完基址,再在保护模式中由段选择子寻址将其赋值给段寄存器。

      最近在学于渊的《Orange’s:一个操作系统的实现》,学到GDT(Global Descriptor Table),即段描述符表。段描述符表中存储的是段描述符的索引。网上也有很多关于段描述符的详解,但是我看着很费劲,所以想自己写下自认为容易理解的对段描述符的描述。

      段描述符记录的是地址空间上的一些属性,如一个地址空间是否可以被写入,可以被多少优先级的代码写入,是不是允许执行等的一些属性。段描述符是64位的所以需要8个字节的空间来存储,下面是用NASM语法写的描述符的数据结构:

; 描述符
; usage: Descriptor Base, Limit, Attr
;        Base:  dd
;        Limit: dd (low 20 bits available)
;        Attr:  dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3
	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 ; 共 8 字节

      这里注意这两句话:
      ; Limit: dd (low 20 bits available)
      ; Attr: dw (lower 4 bits of higher byte are always 0)
      段界限定义了32位,但是只有低20位有效,属性定义了16位,但是高8位的低4位总是0。

      我对NASM语法也不是很熟悉,所以要在这里多说明一些。
      在nasm中:%macro是定义多行宏,%macro Descriptor 3 是定义名为Descriptor的宏,接受3个参数,三个参数依次为基址,界限和属性。%1表示的是参数1(段基址),%2表示参数2(段界限),%3表示参数3(段属性)。将来传进来的参数就替换了%1,%2,%3。
代码还是需要结合段描述符的具体结构来看:
Orange's:一个操作系统的实现 Descriptor 3宏详解_第2张图片
      这里用的是代码段和数据段描述符的结构,此外,描述符的种类还有系统段描述符和门描述符,这里先不多余介绍。从上图来看,段基址是32

      现在来看代码吧!

      第一行: dw %2 & 0FFFFh ; 段界限1
      这行很好理解,段界限1双字型参数2的低16位。
      第二行: dw %1 & 0FFFFh ; 段基址1
      段基址1取双字型参数1的低16位。
      第三行: db (%1 >> 16) & 0FFh ; 段基址2
      段基址2取双字型参数1的高16位的低8位。
      第四行: dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性1 + 段界限2 + 属性2
      就是这第四行把我搞得晕头转向。。。
      ((%2 >> 8) & 0F00h)这一部分是段界限2,也就是参数2的高16位的高8位的低4位。
      (%3 & 0F0FFh)这一部分是属性1和属性2,属性1就是字型参数3的高8位的高四位,属性2就是参数3的低8位。

      第五行: db (%1 >> 24) & 0FFh ; 段基址3
      段基址3取双字型参数1的高16位的高8位。
      总的来说,Descriptor 3这个宏就是将描述符的64位用nasm语法分块描述出来。
      如果想了解段描述符的各个位的属性,可以参照:段描述符属性参照表

你可能感兴趣的:(一个操作系统的实现)