首先了解跳入保护模式的基本步骤
1、将代码段基址存入GDT
2、利用lgdt将GDT基址以及长度加载到gdtr寄存器
3、关中断
4、打开20号地址线
5、置位CR0的PE,准备切换
6、跳入保护模式下的代码段
下面就是这个简单跳跃得代码:
pm.inc包含一些宏定义以及段的属性定义值
%macro Descriptor 3 dw %2 & 0ffffh dw %1 & 0ffffh db (%1>>16) & 0ffh dw ((%2>>8)&0f00h)|(%3 & 0f0ffh) db (%2>>24)&0ffh %endmacro DA_32 equ 4000h ;32位段 DA_DPL0 equ 00h ;DPL=0 DA_DPL1 equ 220h ;DPL=1 DA_DPL2 equ 40h ;DPL=2 DA_DPL3 equ 60h ;DPL=3 DA_DR equ 90h ;只读数据段 DA_DRW equ 92h ;可读可写数据段 DA_DRWA equ 93h ;可读可写已访问数据段 DA_C equ 98h ;只执行代码段 DA_CR equ 9ah ;可读可执行代码段 DA_CCO equ 9ch ;非一致可执行代码段 DA_CCRO equ 9eh ;可读非一致可执行代码段
protec.asm这是主要逻辑部分。功能实现得主体
%include "pm.inc" org 07c00h jmp START [SECTION .gdt] GDT_DEC: Descriptor 0, 0, 0 CODE32_DEC: Descriptor 0,Code32Len-1,DA_32 + DA_CR VIDEO_DEC: Descriptor 0b8000h,0ffffh ,DA_DRW GdtLen equ $ - GDT_DEC Gdtptr dw GdtLen - 1 dd 0 SelectorCode32 equ CODE32_DEC - GDT_DEC SelectorVideo equ VIDEO_DEC - GDT_DEC [SECTION .s16] [BITS 16] START: mov ax,cs mov ds,ax mov es,ax mov ss,ax mov sp,0100h ;加载代码段基址到GDT描述符 xor eax,eax mov ax,cs shl eax,4 add eax,CODE32_SEG mov word [CODE32_DEC+2],ax shr eax,16 mov byte [CODE32_DEC+4],al mov byte [CODE32_DEC+7],ah ;加载GDT基址及长度到gdtr xor eax,eax mov ax,ds shl eax,4 add eax,GDT_DEC mov dword [Gdtptr+2],eax lgdt [Gdtptr] ;关中断 cli ;打开A20 in al,92h or al,02h out 92h,al ;置位PE mov eax,cr0 or eax,01h mov cr0,eax ;跳转保护模式 jmp dword SelectorCode32:0 [SECTION .s32] [BITS 32] CODE32_SEG: mov ax,SelectorVideo mov gs,ax mov esi,offMessage mov edi,(80*12+30)*2 mov ah,0ch cld call DesplayMessage Message: db "Welcome protected place",0 offMessage equ Message - $$ DesplayMessage: .2: mov al,[cs:esi] test al,al .1: jz .1 mov [gs:edi],ax add edi,2 inc esi jmp .2 Code32Len equ $ - CODE32_SEG
不要值抄写代码运行,一旦代码不能带到目的就重抄一遍。这是不可取得。一定要自己慢慢调试,从内存角度理解每一条指令所起得作用,从内存去查看代码不能达到目的的原由。当然代码不可能一次成功,所以Bochs自带调试命令。
1、在某个物理地址设置断点
b addr b 0x7c00
2、显示当前所有断点的信息
info break
3、继续执行直到遇到断点
c
4、单步执行
s
5、单步执行,遇到函数则跳过
n
6、查看寄存器信息
info cpu
r
fp
sreg
creg
7、查看堆栈
print-stack
8、查看内存物理地址内容
xp /nuf addr xp /40bx 0x9013e
其中nuf表示大小,addr表示首地址
9、查看线性地址内容
x /nuf addr x /40bx 0x13e
10、反汇编一段内存
u start end u 0x30400 0x3040d
11、反汇编执行的每条指令
trace-on
12、每执行一条指令就打印cpu信息
trace-reg on
关闭trace-reg off
下面就是上述代码得结果。在屏幕中打印了一行红色的字