jmp 16位-32位
[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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
老兄啊,你的代码能读么?
没看清楚你的代码,剪点我从前写的吧
复制代码
$0x8是选择子
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
我把代码贴全吧
请问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 编辑 ]
题外话,个人认为: nasm 的代码有些地方一点都不漂亮,对 nasm 的代码比较反感。
言归正传:GDT 在进入保护模式时候已经被设好了。其中就有 32 位代码的进入点。
>> jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 SelectorCode32:0 处
SelectorCode32 就是一个选择子,在已经建立好的 GDT 中查找代码位置。
我对 nasm 的语法不熟悉,这应该是定义一个立即数。这个数字在 GDT 中的偏移就是正确代码进入点的描述符。
这里只是将 XXXX:Y 形式转化为: XXXXY 这种形式而已