jmp 16位-32位

发布于 2022-09-29 15:29:03 字数 2608 浏览 19 评论 0

[SECTION .gdt]
; 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 [SECTION .gdt]

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

LABEL_SEG_CODE32:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

深海里的那抹蓝 2022-10-06 15:29:03

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

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

复制代码
$0x8是选择子

时光病人 2022-10-06 15:29:03

org        0100h
        jmp        LABEL_BEGIN

[SECTION .gdt]
; 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 [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 * 10 + 0) * 2        ; 屏幕第 10 行, 第 0 列。
        mov        ah, 0Ch                        ; 0000: 黑底    1100: 红字
        mov        al, 'P'
        mov        [gs:edi], ax

        ; 到此停止
        jmp        $

SegCode32Len        equ        $ - LABEL_SEG_CODE32
; END of [SECTION .s32]

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

DA_32                EQU        4000h
DA_C                EQU        98h

傾旎 2022-10-06 15:29:03

我把代码贴全吧
请问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 [LABEL_DESC_CODE32 + 2], ax
这四句什么作用

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

初与友歌 2022-10-06 15:29:03

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

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

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

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

画骨成沙 2022-10-06 15:29:03

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

这里只是将 XXXX:Y 形式转化为:  XXXXY 这种形式而已

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文