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位代码段 段基址? 老兄啊,你的代码能读么?
没看清楚你的代码,剪点我从前写的吧
#define R(x) (x - KERNBASE)
/*
* We have not enable paging yet
* and $R(MPboot32) is too large for ljmp
*/
ljmpl $0x8, $R(MPboot32)
$0x8是选择子 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 我把代码贴全吧
请问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 编辑 ] 题外话,个人认为: nasm 的代码有些地方一点都不漂亮,对 nasm 的代码比较反感。
言归正传:GDT 在进入保护模式时候已经被设好了。其中就有 32 位代码的进入点。
>> jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 SelectorCode32:0处
SelectorCode32 就是一个选择子,在已经建立好的 GDT 中查找代码位置。
我对 nasm 的语法不熟悉,这应该是定义一个立即数。这个数字在 GDT 中的偏移就是正确代码进入点的描述符。 原帖由 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]