+ -
当前位置:首页 → 问答吧 → 看OrangeOS时的一些问题

看OrangeOS时的一些问题

时间:2011-08-19

来源:互联网

Assembly code

; ==========================================
; pmtest1.asm
; 编译方法:nasm pmtest1.asm -o pmtest1.bin
; ==========================================

%include    "pm.inc"    ; 常量, 宏, 以及一些说明

org    07c00h
    jmp    LABEL_BEGIN

[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 结束

GdtLen        equ    $ - LABEL_GDT    ; GDT长度
GdtPtr        dw    GdtLen - 1    ; GDT界限
        dd    0        ; GDT基地址

; GDT 选择子
SelectorCode32        equ    LABEL_DESC_CODE32    - LABEL_GDT
SelectorVideo        equ    LABEL_DESC_VIDEO    - LABEL_GDT
; END of [SECTION .gdt]

[SECTION .s16]
[BITS    16]
LABEL_BEGIN:
    mov    ax, cs
    mov    ds, ax
    mov    es, ax
    mov    ss, ax
    mov    sp, 0100h

    ; 初始化 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

    ; 为加载 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]

    ; 关中断
    cli

    ; 打开地址线A20
    in    al, 92h
    or    al, 00000010b
    out    92h, al

    ; 准备切换到保护模式
    mov    eax, cr0
    or    eax, 1
    mov    cr0, eax

    ; 真正进入保护模式
    jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs,
                    ; 并跳转到 Code32Selector:0  处
; END of [SECTION .s16]


[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]



其中的 mov ax, SelectorVideo
  mov gs, as
  ......
  mov [gs:edi], ax
书上说:“gs值为SelectorVideo, 它指示对应现存的描述符DESC_VIDEO,这条指令把ax的值写入显存中偏移为edi的位置

我的问题是:SelectorVideo不是应该是DESC_VIDEO相对于GDT基址的偏移,书上说这个不是偏移,是选择符,不明白啊。
还有jmp dword SelectorCode32:0 为什么跳转的目标是描述符DESC_CODE32对应的段的首地址处,为什么会这样呢,不明白啊。。

作者: littleubuntu   发布时间: 2011-08-19

把选择符看成数组下标,gdt的描述符0不用,SelectorCode32是0x8,SelectorVideo是0x10

作者: ww2000e   发布时间: 2011-08-20