进入保护模式完整代码(汇编)

一开始使用C编写进入PM代码,因为内嵌汇编太多,不易查询汇编如何出错,所以改用纯汇编编写。

 过程中学到一个小技巧,当赋值的数太大时,编译会报错,这时在数前加个0即可解决。

 程序编译完成,基本过程已然了解,但是在测试机上跑的时候会自动重启。

;;;;;;;;;;;;;;;;;;;程序开始;;;;;;;;;;;;;;;;;;  
;data struct  
  
jump macro selector, offset  
db 0eah  
dw offset  
dw selector  
endm  
  
desp struc  
segLimit   dw 0; byte0, 1  
segBaseLow dw 0; byte2, 3  
segBaseMid db 0; byte4  
segAttribute dw 0; byte5, 6  
segBaseHigh db 0; byte7  
desp ends  
  
pgdt struc  
segLimit dw 0ffffh; byte 0, 1  
segBase  dd 0; byte 2, 3, 4, 5  
pgdt ends  
  
  
;-------------------------------------------------------------  
  
-------  
; real mode data segment begin  
;.data  
  
.386p; if not p, lgdt is not defined  
dseg segment use16   
; gdt segment begin  
gdt label byte  
DUMMY desp <>; 空描述符!!!  
dataSegDesp desp <0ffffh,0h,0h,092h,> ; data segment is   
  
started with: 0x00000000h  
dataSegSel = dataSegDesp - gdt   
  
codeSegDesp desp <0ffffh,,,098h,>  
codeSegSel = codeSegDesp - gdt  
  
extSegDesp desp <0ffffh,,88h,092h,> ; ext segment is started with: 0x00880000h  
  
extSegSel = extSegDesp -  gdt  
gdtLen = $ - gdt  
pgdtr pgdt <gdtLen-1, >  
; gdt segment end  
  
; pmode data segment begin  
buffers db 256 dup('@')  
bufferLen = $ - offset buffers  
  
msgLen = $ - offset msg  
; pmode data segment end  
  
bufferd db 256 dup('y')  
bufferd2 db 256 dup('x')  
dseg ends  
; real mode data segment end  
  
;-------------------------------------------------------------  
  
-------  
cseg segment use16  
;.code  
assume cs:cseg, ds:dseg  
  
start:  
MOV ax, dseg  
MOV ds, ax  
  
;prepare to jump to pmode  
;1>. init gdtr  
;2>. init code descriptor  
;3>. init data descriptor  
;4>. enable a20 address  
;5>. set cr0  
;6>. jump pmode  
  
;1>. init gdtr  
MOV bx, 16  
MUL bx  
ADD ax, offset gdt  
ADC dx, 0  
MOV WORD PTR pgdtr.segBase, ax  
MOV WORD PTR pgdtr.segBase+2, dx  
  
;2>. init code descriptor  
MOV ax, cs  
MUL bx  
MOV codeSegDesp.segBaseLow, ax  
MOV codeSegDesp.segBaseMid, dl  
MOV codeSegDesp.segBaseHigh, dh  
  
;3>. init data descriptor  
MOV ax, ds  
MUL bx  
ADD ax, offset buffers  
adc dx, 0  
MOV dataSegDesp.segBaseLow, ax  
MOV dataSegDesp.segBaseMid, dl  
MOV dataSegDesp.segBaseHigh, dh  
lgdt pgdtr  
  
;4>. enable A20 address  
cli  
;call enableA20  
PUSH ax  
in al, 92h  
or al, 2  
out 92h, al  
POP ax  
  
;5>. set cr0  
MOV eax, cr0  
or eax, 1  
MOV cr0, eax  
  
;6>. jump to pmode  
;JMP pmode  
jump <codeSegSel>,<offset pmode>  
  
pmode:  
MOV ax, dataSegSel  
MOV ds, ax  
MOV ax, extSegSel  
MOV es, ax  
  
;;;;;;;访问SPI空间的内容;;;;;;;;;  
mov ebx,[0fed1f800h]  
mov ds:[0000],ebx  
mov dx,0  
mov ah,9  
int 21h  
;;;;;;;;;;;;;;;;  
  
MOV eax, cr0  
and eax, 0fffffffeh  
MOV cr0, eax  
JMP rmode  
  
rmode:  
call disableA20  
sti  
  
MOV ax, dseg  
MOV ds, ax  
  
disableA20 proc  
PUSH ax  
in al, 92h  
and al, 0fdh  
out 92h, al  
POP ax  
RET  
disableA20 endp  
  
MOV ah, 4ch  
int 21h  
cseg ends  
END start  

 

转载于:https://www.cnblogs.com/wudibuzaijia/p/8484100.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值