x86 段式管理(地址转换后还只是线性地址)

image

启动代码,如下:

在pm.inc中有

; 宏 ------------------------------------------------------------------------------------------------------
;
; 描述符
; 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
dw  %1 & 0FFFFh  ; 段基址1
db  (%1 >> 16) & 0FFh  ; 段基址2
dw  ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)  ; 属性1 + 段界限2 + 属性2
db  (%1 >> 24) & 0FFh  ; 段基址3
%endmacro ; 共 8 字节
;
; 门
; usage: Gate Selector, Offset, DCount, Attr
;  Selector:  dw
;  Offset:  dd
;  DCount:  db
;  Attr:  db
%macro Gate 4
dw  (%2 & 0FFFFh)  ; 偏移1
dw  %1  ; 选择子
dw  (%3 & 1Fh) | ((%4 << 8) & 0FF00h)  ; 属性
dw  ((%2 >> 16) & 0FFFFh)  ; 偏移2
%endmacro ; 共 8 字节
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

正式代码开始

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

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

org  07c00h
jmp  LABEL_BEGIN
//一开始就是全局描述表

//Descriptor  是个宏(相当于结构体定义),8个字节,表示一个GDT项

// 1.LABEL_GDT  8字节

//2. LABEL_DESC_CODE32   8字节
//3.LABEL_DESC_VIDEO 8字节(显卡用的内存,放到这里的数据会自动显示到屏幕)

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值