317316abcd 发表于 2007-06-18 11:18

jmp 16位-32位


; GDT
;                                       段基址,      段界限   , 属性
LABEL_GDT:                Descriptor               0,                0, 0                     ; 空描述符
LABEL_DESC_CODE32:      Descriptor               0, SegCode32Len - 1, DA_C + DA_32      ; 非一致代码段, 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

...
...
; 真正进入保护模式
      jmp      dword SelectorCode32:0      ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 SelectorCode32:0处
SECTION .s32]; 32 位代码段. 由实模式跳入.


LABEL_SEG_CODE32:

请问jmp跳向的一个地方明明是 LABEL_DESC_CODE32      - LABEL_GDT 的偏移量 怎么能跳到下面的LABEL_SEG_CODE32呢 难道说把选择子装入CS中会自动判断32位代码段 段基址?

bluster 发表于 2007-06-18 11:44

老兄啊,你的代码能读么?
没看清楚你的代码,剪点我从前写的吧

#define R(x)    (x - KERNBASE)
      /*
         * We have not enable paging yet
         * and $R(MPboot32) is too large for ljmp
         */
      ljmpl   $0x8, $R(MPboot32)


$0x8是选择子

317316abcd 发表于 2007-06-18 15:19

org        0100h
        jmp        LABEL_BEGIN


; GDT
;                                       段基址,      段界限   , 属性
LABEL_GDT:                Descriptor             0,                0, 0                   ; 空描述符
LABEL_DESC_CODE32:        Descriptor             0, SegCode32Len - 1, DA_C + DA_32        ; 非一致代码段, 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



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 , ax
        shr        eax, 16
        mov        byte , al
        mov        byte , ah

        ; 为加载 GDTR 作准备
        xor        eax, eax
        mov        ax, ds
        shl        eax, 4
        add        eax, LABEL_GDT                ; eax <- gdt 基地址
        mov        dword , eax        ; <- gdt 基地址

        ; 加载 GDTR
        lgdt       

        ; 关中断
        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


; 32 位代码段. 由实模式跳入.


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

        mov        edi, (80 * 10 + 0) * 2        ; 屏幕第 10 行, 第 0 列。
        mov        ah, 0Ch                        ; 0000: 黑底    1100: 红字
        mov        al, 'P'
        mov        , ax

        ; 到此停止
        jmp        $

SegCode32Len        equ        $ - LABEL_SEG_CODE32
; END of

; 描述符
; 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                                (2 字节)
        dw        %1 & 0FFFFh                                ; 段基址 1                                (2 字节)
        db        (%1 >> 16) & 0FFh                        ; 段基址 2                                (1 字节)
        dw        ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)        ; 属性 1 + 段界限 2 + 属性 2                (2 字节)
        db        (%1 >> 24) & 0FFh                        ; 段基址 3                                (1 字节)
%endmacro ; 共 8 字节

DA_32                EQU        4000h
DA_C                EQU        98h

317316abcd 发表于 2007-06-18 15:24

我把代码贴全吧
请问jmp跳向的一个地方明明是 LABEL_DESC_CODE32      - LABEL_GDT 的偏移量 怎么能跳到下面的LABEL_SEG_CODE32呢(偏移量和LABEL_SEG_CODE32地址应该不同啊) 难道说把选择子装入CS中会自动判断32位代码段 段基址?

还有   mov       ax, cs
      shl      eax, 4
      add      eax, LABEL_SEG_CODE32
      mov      word , ax
这四句什么作用

[ 本帖最后由 317316abcd 于 2007-6-18 15:26 编辑 ]

mik 发表于 2007-06-19 23:08

题外话,个人认为: nasm 的代码有些地方一点都不漂亮,对 nasm 的代码比较反感。


言归正传:GDT 在进入保护模式时候已经被设好了。其中就有 32 位代码的进入点。

>> jmp      dword SelectorCode32:0      ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 SelectorCode32:0处

SelectorCode32 就是一个选择子,在已经建立好的 GDT 中查找代码位置。
我对 nasm 的语法不熟悉,这应该是定义一个立即数。这个数字在 GDT 中的偏移就是正确代码进入点的描述符。

mik 发表于 2007-06-19 23:13

原帖由 317316abcd 于 2007-6-18 15:24 发表于 4楼
还有   mov       ax, cs
      shl      eax, 4
      add      eax, LABEL_SEG_CODE32
      mov      word , ax
这四句什么作用
...

这里只是将 XXXX:Y 形式转化为:XXXXY 这种形式而已
页: [1]
查看完整版本: jmp 16位-32位