0xAA55 发表于 2017-6-15 08:51:49

【汇编】最简单的切保护模式的源码

bits 16
org 0x7c00

Start:
xor ax,ax
mov ds,ax

cli

lgdt

mov eax,cr0
or al,1
mov cr0,eax
jmp dword 0x08:PEStart

GDTR:
.limit:
dw GDT.End-GDT-1
.base:
dd GDT

GDT:
dw 0,0,0,0

dw 0xffff
dw 0
dw 0x9a00
dw 0x00cf

dw 0xffff
dw 0
dw 0x9200
dw 0x00cf
.End:

PEStart:
bits 32

mov ax,0x10
mov es,ax
mov ss,ax
mov ds,ax
mov fs,ax
mov gs,ax
mov esp, 0xffff

.text:
mov dword,'P'|('r'<<16)|0x07000700
mov dword,'o'|('t'<<16)|0x07000700
mov dword,'e'|('c'<<16)|0x07000700
mov dword,'t'|('e'<<16)|0x07000700
mov dword,'d'|(' '<<16)|0x07000700
mov dword,'m'|('o'<<16)|0x07000700
mov dword,'d'|('e'<<16)|0x07000700
jmp .text

times 510-($-$$) db 0
dw 0xAA55编译为平坦格式flp后缀,让vmware把它当作一个启动软盘加载即可运行。
没有出问题的话,它应该会显示一句“Protected mode”。

细节上要注意的点:
1、切模式前务必关中断。用cli即可。如果只是想进保护模式玩玩的话,无需设置IDT和TS。
2、nasm编译器,我用的版本是2.13.01。经过我的测试2.11版有BUG,会导致它无视你的bits 32语句。
3、修改cr0的数值后必须立即跳转。
4、可以不用在跳转前修改段选择子。
5、开头的那几句:
    xor ax,ax
    mov ds,ax
经测试,必须要有。因为引导进来的时候ds并没有指向你的代码所在的段上。不设置这两句的话,lgdt指令并不能正确找到你的gdt表。

Ayala 发表于 2017-6-15 19:56:21

用masm写起来就恶心了 dos bin
DESC STRUC
        lim_00_15 DW ?
        bas_00_15 DW ?
        bas_16_23 DB ?
        access    DB ?
        gran      DB ?
        bas_24_31 DB ?
DESC ENDS

data segment
        GDT_REG label DESC
        ;cs 0
                                dw 0
                               
                                dw 0
                               
                                db 0
                                db 0
                               
                                db 0
                                db 0
        ;cs 08h
                                dw 0FFFFh
                                dw 0
                               
                                db 0
                                db 9ah
                               
                                db 0cfh
                                db 0
        ;es 10h
                                dw 0FFFFh
                                dw 0
                               
                                db 0
                                db 92h
                               
                                db 0cfh
                                db 0
        ;ss 18h
                                dw 0FFFFh
                                dw 0
                               
                                db 0
                                db 92h
                               
                                db 0cfh
                                db 0
        GDT_LENGTHEQU $ - offset GDT_REG
       
       
        GDTR_org         dw 0
                                dd 0
        GDTR_new        dw GDT_LENGTH - 1
                                dd offset GDT_REG
data ends


u16 segment
        assume cs:u16,ds:data
REAL_MODE:

start:
        mov ax,data
        mov ds,ax

        mov ax,u32
.386
        shl eax,4
.8086
        mov GDT_REG.bas_00_15,ax
.386       
        shr eax,16
.8086
        mov GDT_REG.bas_16_23,al
        mov GDT_REG.bas_24_31,ah
       
        mov ax,data
.386
        shl eax,4
        add eax,dword ptr ds:GDTR_new
        mov dword ptr ds:GDTR_new,eax
       
.386p
        cli
        db 66h       
        sgdt fword ptr ds:
       
        db 66h
        lgdt fword ptr ds:

        mov eax,cr0
        oreax,1
        mov cr0,eax
       
        db 66h
        db 0eah
        dd 0
        dw 8

u16 ends

.386

u32 segment use32
PROTECT_MODE:

        mov ax,10h
        mov es,ax

        mov edi,0b8000h
        mov ecx,80*25
        mov al,"*"
        mov ah,11001010b
        rep stosw
       
        jmp $
       
u32 ends

end start

0xAA55 发表于 2017-6-15 21:06:07

Ayala 发表于 2017-6-15 19:56
用masm写起来就恶心了 dos bin
DESC STRUC
        lim_00_15 DW ?


这db 66h让我回忆起了曾经的辛酸

Ayala 发表于 2017-6-15 21:26:05

0xAA55 发表于 2017-6-15 21:06
这db 66h让我回忆起了曾经的辛酸

这种写法 最早出自intel自己呢!

(⊙o⊙) 发表于 2017-10-31 09:44:37

这也可以。
页: [1]
查看完整版本: 【汇编】最简单的切保护模式的源码