首页
社区
课程
招聘
保护模式编程起步问题求助
发表于: 2013-4-28 21:57 4889

保护模式编程起步问题求助

2013-4-28 21:57
4889
;名称:386SCD.INC
;功能:符号常量等的定义
;----------------------------------------------------------------------------
;IFNDEF         __386SCD_INC
;__386SCD_INC   EQU     1
;----------------------------------------------------------------------------
.386P
;----------------------------------------------------------------------------
;打开A20地址线
;----------------------------------------------------------------------------
EnableA20       MACRO
                push    ax
                in      al,92h
                or      al,00000010b
                out     92h,al
                pop     ax
                ENDM
;----------------------------------------------------------------------------
;关闭A20地址线
;----------------------------------------------------------------------------
DisableA20      MACRO
                push    ax
                in      al,92h
                and     al,11111101b
                out     92h,al
                pop     ax
                ENDM
;----------------------------------------------------------------------------
;16位偏移的段间直接转移指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
JUMP16          MACRO   Selector,Offset
                DB      0eah     ;操作码
                DW      Offset   ;16位偏移量
                DW      Selector ;段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;32位偏移的段间直接转移指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT <JUMP32>
JUMP32          MACRO   Selector,Offset
                DB      0eah     ;操作码
                DD      OFFSET
                DW      Selector ;段值或段选择子
                ENDM
<JUMP32>
;-------------------------------------------------
JUMP32          MACRO   Selector,Offset
                DB      0eah     ;操作码
                DW      OFFSET
                DW      0
                DW      Selector ;段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;16位偏移的段间调用指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
CALL16          MACRO   Selector,Offset
                DB      9ah      ;操作码
                DW      Offset   ;16位偏移量
                DW      Selector ;段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;32位偏移的段间调用指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT <CALL32>
CALL32          MACRO   Selector,Offset
                DB      9ah      ;操作码
                DD      Offset
                DW      Selector ;段值或段选择子
                ENDM
<CALL32>
;-------------------------------------------------
CALL32          MACRO   Selector,Offset
                DB      9ah      ;操作码
                DW      Offset
                DW      0
                DW      Selector ;段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;存储段描述符结构类型定义
;----------------------------------------------------------------------------
Desc            STRUC
LimitL          DW      0 ;段界限(BIT0-15)
BaseL           DW      0 ;段基地址(BIT0-15)
BaseM           DB      0 ;段基地址(BIT16-23)
Attributes      DB      0 ;段属性
LimitH          DB      0 ;段界限(BIT16-19)(含段属性的高4位)
BaseH           DB      0 ;段基地址(BIT24-31)
Desc            ENDS
;----------------------------------------------------------------------------
;门描述符结构类型定义
;----------------------------------------------------------------------------
Gate            STRUC
OffsetL         DW      0 ;32位偏移的低16位
Selector        DW      0 ;选择子
DCount          DB      0 ;双字计数
GType           DB      0 ;类型
OffsetH         DW      0 ;32位偏移的高16位
Gate            ENDS
;----------------------------------------------------------------------------
;伪描述符结构类型定义(用于装入全局或中断描述符表寄存器)
;----------------------------------------------------------------------------
PDesc           STRUC
Limit           DW      0 ;16位界限
Base            DD      0 ;32位基地址
PDesc           ENDS
;----------------------------------------------------------------------------
;任务状态段结构类型定义
;----------------------------------------------------------------------------
TSS             STRUC
TRLink          DW      0      ;链接字段
                DW      0      ;不使用,置为0
TRESP0          DD      0      ;0级堆栈指针
TRSS0           DW      0      ;0级堆栈段寄存器
                DW      0      ;不使用,置为0
TRESP1          DD      0      ;1级堆栈指针
TRSS1           DW      0      ;1级堆栈段寄存器
                DW      0      ;不使用,置为0
TRESP2          DD      0      ;2级堆栈指针
TRSS2           DW      0      ;2级堆栈段寄存器
                DW      0      ;不使用,置为0
TRCR3           DD      0      ;CR3
TREIP           DD      0      ;EIP
TREFlag         DD      0      ;EFLAGS
TREAX           DD      0      ;EAX
TRECX           DD      0      ;ECX
TREDX           DD      0      ;EDX
TREBX           DD      0      ;EBX
TRESP           DD      0      ;ESP
TREBP           DD      0      ;EBP
TRESI           DD      0      ;ESI
TREDI           DD      0      ;EDI
TRES            DW      0      ;ES
                DW      0      ;不使用,置为0
TRCS            DW      0      ;CS
                DW      0      ;不使用,置为0
TRSS            DW      0      ;SS
                DW      0      ;不使用,置为0
TRDS            DW      0      ;DS
                DW      0      ;不使用,置为0
TRFS            DW      0      ;FS
                DW      0      ;不使用,置为0
TRGS            DW      0      ;GS
                DW      0      ;不使用,置为0
TRLDTR          DW      0      ;LDTR
                DW      0      ;不使用,置为0
TRTrip          DW      0      ;调试陷阱标志(只用位0)
TRIOMap         DW      $+2    ;指向I/O许可位图区的段内偏移
TSS             ENDS
;----------------------------------------------------------------------------
;存储段描述符类型值说明
;----------------------------------------------------------------------------
ATDR            EQU     90h ;存在的只读数据段类型值
ATDW            EQU     92h ;存在的可读写数据段属性值
ATDWA           EQU     93h ;存在的已访问可读写数据段类型值
ATCE            EQU     98h ;存在的只执行代码段属性值
ATCER           EQU     9ah ;存在的可执行可读代码段属性值
ATCCO           EQU     9ch ;存在的只执行一致代码段属性值
ATCCOR          EQU     9eh ;存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
;系统段描述符类型值说明
;----------------------------------------------------------------------------
ATLDT           EQU     82h ;局部描述符表段类型值
ATTaskGate      EQU     85h ;任务门类型值
AT386TSS        EQU     89h ;可用386任务状态段类型值
AT386CGate      EQU     8ch ;386调用门类型值
AT386IGate      EQU     8eh ;386中断门类型值
AT386TGate      EQU     8fh ;386陷阱门类型值
;----------------------------------------------------------------------------
;DPL值说明
;----------------------------------------------------------------------------
DPL0            EQU     00h ;DPL=0
DPL1            EQU     20h ;DPL=1
DPL2            EQU     40h ;DPL=2
DPL3            EQU     60h ;DPL=3
;----------------------------------------------------------------------------
;RPL值说明
;----------------------------------------------------------------------------
RPL0            EQU     00h ;RPL=0
RPL1            EQU     01h ;RPL=1
RPL2            EQU     02h ;RPL=2
RPL3            EQU     03h ;RPL=3
;----------------------------------------------------------------------------
;IOPL值说明
;----------------------------------------------------------------------------
IOPL0           EQU     0000h ;IOPL=0
IOPL1           EQU     1000h ;IOPL=1
IOPL2           EQU     2000h ;IOPL=2
IOPL3           EQU     3000h ;IOPL=3
;----------------------------------------------------------------------------
;其它常量值说明
;----------------------------------------------------------------------------
D32             EQU     40h       ;32位代码段标志
GL              EQU     80h       ;段界限以4K为单位标志
TIL             EQU     04h       ;TI=1(局部描述符表标志)
VMFL            EQU     00020000h ;VMF=1
VMFLW           EQU     0002h
IFL             EQU     00000200h ;IF=1
RFL             EQU     00010000h ;RF=1(重启动标志,为1表示忽略调试故障)
RFLW            EQU     0001h
NTL             EQU     00004000h ;NT=1
;----------------------------------------------------------------------------
;分页机制使用的常量说明
;----------------------------------------------------------------------------
PL              EQU     1     ;页存在属性位
RWR             EQU     0     ;R/W属性位值,读/执行
RWW             EQU     2     ;R/W属性位值,读/写/执行
USS             EQU     0     ;U/S属性位值,系统级
USU             EQU     4     ;U/S属性位值,用户级
;----------------------------------------------------------------------------
;ENDIF

;名称:ASM1.ASM
;功能:演示实方式和保护方式切换(切换到16位代码段)
;----------------------------------------------------------------------------
INCLUDE         386SCD.INC
;----------------------------------------------------------------------------
;字符显示宏指令的定义
;----------------------------------------------------------------------------
EchoCh          MACRO   ascii
                mov     ah,2
                mov     dl,ascii
                int     21h
                ENDM
;----------------------------------------------------------------------------
DSEG            SEGMENT USE16                 ;16位数据段
;----------------------------------------------------------------------------
GDT             LABEL   BYTE                  ;全局描述符表
DUMMY           Desc    <>                    ;空描述符
Code            Desc    <0ffffh,,,ATCE,,>     ;代码段描述符
DataS           Desc    <0ffffh,0,11h,ATDW,,> ;源数据段描述符
DataD           Desc    <0ffffh,,,ATDW,,>     ;目标数据段描述符
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                 ;全局描述符表长度
VGDTR           PDesc   <GDTLen-1,>           ;伪描述符
;----------------------------------------------------------------------------
Code_Sel        =       Code-GDT              ;代码段选择子
DataS_Sel       =       Datas-GDT             ;源数据段选择子
DataD_Sel       =       DataD-GDT             ;目标数据段选择子
;----------------------------------------------------------------------------
BufLen          =       256                   ;缓冲区字节长度
Buffer          DB      BufLen DUP(0)         ;缓冲区
;----------------------------------------------------------------------------
DSEG            ENDS                          ;数据段定义结束
;----------------------------------------------------------------------------
CSEG            SEGMENT USE16                 ;16位代码段
                ASSUME  CS:CSEG,DS:DSEG
;----------------------------------------------------------------------------
Start           PROC
                mov     ax,DSEG
                mov     ds,ax
                ;准备要加载到GDTR的伪描述符
                mov     bx,16
                mul     bx
                add     ax,OFFSET GDT          ;计算并设置基地址
                adc     dx,0                   ;界限已在定义时设置好
                mov     WORD PTR VGDTR.Base,ax
                mov     WORD PTR VGDTR.Base+2,dx
                ;设置代码段描述符
                mov     ax,cs
                mul     bx
                mov     WORD PTR Code.BaseL,ax ;代码段开始偏移为0
                mov     BYTE PTR Code.BaseM,dl ;代码段界限已在定义时设置好
                mov     BYTE PTR Code.BaseH,dh
                ;设置目标数据段描述符
                mov     ax,ds
                mul     bx                     ;计算并设置目标数据段基址
                add     ax,OFFSET Buffer
                adc     dx,0
                mov     WORD PTR DataD.BaseL,ax
                mov     BYTE PTR DataD.BaseM,dl
                mov     BYTE PTR DataD.BaseH,dh
                ;加载GDTR
                lgdt    QWORD PTR VGDTR
                cli                            ;关中断
                EnableA20                      ;打开地址线A20
                ;切换到保护方式
                mov     eax,cr0
                or      eax,1
                mov     cr0,eax
                ;清指令预取队列,并真正进入保护方式
                JUMP16  Code_Sel,<OFFSET Virtual>
Virtual:        ;现在开始在保护方式下运行
                mov     ax,DataS_Sel
                mov     ds,ax                  ;加载源数据段描述符
                mov     ax,DataD_Sel
                mov     es,ax                  ;加载目标数据段描述符
                cld
                xor     si,si
                xor     di,di                  ;设置指针初值
                mov     cx,BufLen/4            ;设置4字节为单位的缓冲区长度
                repz    movsd                  ;传送
                ;切换回实模式
                mov     eax,cr0
                and     al,11111110b
                mov     cr0,eax
                ;清指令预取队列,进入实方式
                JUMP16  <SEG Real>,<OFFSET Real>
Real:           ;现在又回到实方式
                DisableA20
                sti
                mov     ax,DSEG
                mov     ds,ax
                mov     si,OFFSET Buffer
                cld
                mov     bp,BufLen/16
NextLine:       mov     cx,16
NextCh:         lodsb
                push    ax
                shr     al,1
                call    ToASCII
                EchoCh  al
                pop     ax
                call    ToASCII
                EchoCh  al
                EchoCh  ' '
                loop    NextCh
                EchoCh  0dh
                EchoCh  0ah
                dec     bp
                jnz     NextLine
                mov     ax,4c00h
                int     21h
Start           ENDP
;----------------------------------------------------------------------------
ToASCII         PROC
                and     al,0fh
                add     al,90h
                daa
                adc     al,40h
                daa
                ret
ToASCII         ENDP
;----------------------------------------------------------------------------
CSEG            ENDS                           ;代码段定义结束
;----------------------------------------------------------------------------
                END     Start

;名称:ASM2.ASM
;功能:演示实方式和保护方式切换(切换到32位代码段)
;----------------------------------------------------------------------------
INCLUDE         386SCD.INC
;----------------------------------------------------------------------------
DSEG            SEGMENT USE16                     ;16位数据段
;----------------------------------------------------------------------------
GDT             LABEL   BYTE                      ;全局描述符表
DUMMY           Desc    <>                        ;空描述符
Normal          Desc    <0ffffh,,,ATDW,,>         ;规范段描述符
Code32          Desc    <C32Len-1,,,ATCE,D32,>    ;32位代码段描述符
Code16          Desc    <0ffffh,,,ATCE,,>         ;16位代码段描述符
DataS           Desc    <DataLen-1,0,10h,ATDR,,>  ;源数据段描述符
DataD           Desc    <3999,8000h,0bh,ATDW,,>   ;显示缓冲区描述符
Stacks          Desc    <StackLen-1,,,ATDW,,>     ;堆栈段描述符
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                     ;全局描述符表长度
VGDTR           PDesc   <GDTLen-1,>               ;伪描述符
;----------------------------------------------------------------------------
SaveSP          DW      ?                         ;用于保存SP寄存器
SaveSS          DW      ?                         ;用于保存SS寄存器
;----------------------------------------------------------------------------
Normal_Sel      =       Normal-GDT                ;规范段描述符选择子
Code32_Sel      =       Code32-GDT                ;32位代码段选择子
Code16_Sel      =       Code16-GDT                ;16位代码段选择子
DataS_Sel       =       Datas-GDT                 ;源数据段选择子
DataD_Sel       =       DataD-GDT                 ;目标数据段选择子
Stacks_Sel      =       Stacks-GDT                ;堆栈段描述符选择子
;----------------------------------------------------------------------------
DataLen         =       16
;----------------------------------------------------------------------------
DSEG            ENDS                              ;数据段定义结束
;----------------------------------------------------------------------------
StackSeg        SEGMENT PARA STACK USE16
StackLen        =       256
                DB      StackLen DUP(0)
StackSeg        ENDS
;----------------------------------------------------------------------------
CSEG1           SEGMENT USE16 'REAL'              ;16位代码段
                ASSUME  CS:CSEG1,DS:DSEG
;----------------------------------------------------------------------------
Start           PROC
                mov     ax,DSEG
                mov     ds,ax
                ;准备要加载到GDTR的伪描述符
                mov     bx,16
                mul     bx
                add     ax,OFFSET GDT             ;计算并设置基地址
                adc     dx,0                      ;界限已在定义时设置好
                mov     WORD PTR VGDTR.Base,ax
                mov     WORD PTR VGDTR.Base+2,dx
                ;设置32位代码段描述符
                mov     ax,CSEG2
                mul     bx
                mov     WORD PTR Code32.BaseL,ax
                mov     BYTE PTR Code32.BaseM,dl
                mov     BYTE PTR Code32.BaseH,dh
                ;设置16位代码段描述符
                mov     ax,CSEG3
                mul     bx
                mov     WORD PTR Code16.BaseL,ax  ;代码段开始偏移为0
                mov     BYTE PTR Code16.BaseM,dl  ;代码段界限已在定义时设置好
                mov     BYTE PTR Code16.BaseH,dh
                ;设置堆栈段描述符
                mov     ax,ss
                mov     WORD PTR SaveSS,ax
                mov     WORD PTR SaveSP,sp
                mov     ax,StackSeg
                mul     bx
                mov     WORD PTR Stacks.BaseL,ax
                mov     BYTE PTR Stacks.BaseM,dl
                mov     BYTE PTR Stacks.BaseH,dh
                ;加载GDTR
                lgdt    QWORD PTR VGDTR
                cli                               ;关中断
                EnableA20                         ;打开地址线A20
                ;切换到保护方式
                mov     eax,cr0
                or      al,1
                mov     cr0,eax
                ;清指令预取队列,并真正进入保护方式
                JUMP16  Code32_Sel,<OFFSET SPM32>
ToReal:         ;现在又回到实方式
                mov     ax,DSEG
                mov     ds,ax
                mov     sp,SaveSP
                mov     ss,SaveSS
                DisableA20
                sti
                mov     ax,4c00h
                int     21h
Start           ENDP
;----------------------------------------------------------------------------
CSEG1           ENDS                              ;代码段定义结束
;----------------------------------------------------------------------------
CSEG2           SEGMENT USE32 'PM32'
                ASSUME  CS:CSEG2
;----------------------------------------------------------------------------
SPM32           PROC
                mov     ax,Stacks_Sel
                mov     ss,ax
                mov     esp,StackLen
                mov     ax,DataS_Sel
                mov     ds,ax
                mov     ax,DataD_Sel
                mov     es,ax
                xor     esi,esi
                xor     edi,edi
                mov     ecx,DataLen
                cld
Next:           lodsb
                push    ax
                CALL    ToASCII
                mov     ah,7
                shl     eax,16
                pop     ax
                shr     al,4
                CALL    ToASCII
                mov     ah,7
                stosd
                mov     al,20h
                stosw
                loop    Next
                JUMP32   Code16_Sel,<OFFSET SPM16>
SPM32           ENDP
;----------------------------------------------------------------------------
ToASCII         PROC
                and     al,00001111b
                add     al,30h
                cmp     al,39h
                jbe     Isdig
                add     al,7
IsDig:          ret
ToASCII         ENDP
;----------------------------------------------------------------------------
C32Len          =       $
;----------------------------------------------------------------------------
CSEG2           ENDS
;----------------------------------------------------------------------------
CSEG3           SEGMENT USE16 'PM16'
                ASSUME  CS:CSEG3
;----------------------------------------------------------------------------
SPM16           PROC
                xor     si,si
                mov     di,DataLen*3*2
                mov     ah,7
                mov     cx,DataLen
AGain:          lodsb
                stosw
                loop    AGain
                mov     ax,Normal_sel
                mov     ds,ax
                mov     es,ax
                mov     ss,ax
                mov     eax,cr0
                and     al,11111110b
                mov     cr0,eax
                jmp     FAR PTR ToReal
SPM16           ENDP
;----------------------------------------------------------------------------
CSEG3           ENDS
;----------------------------------------------------------------------------
                END     Start
以上代码是从教程中复制的
但有以下问题不解:
1、这个要怎么编译链接
2、生成可执行程序要在什么系统下运行,其实跟第一个问题有点重复
3、如何调试。

我使用MASM6.1的MASM命令编译,两个程序都无法通过编译,第一个程序将装载GDT的那一行代码: lgdt    QWORD PTR VGDTR改成lgdt VGDTR既可通过编译,但无法在虚拟DOS下运行。
而第二个程序,无论使用MASM还是ML命令都无法通过编译。

刚起步,什么都不懂,请讲解时讲得“白”一些。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 18
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
要用到一些工具,masm link等system32下的工具,
masm工具生成obj文件,用link将obj文件生成exe,
在cmd下执行哦,
2013-4-29 14:31
0
雪    币: 183
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
CMD下无法执行。其实,执行不了也猜到了,具体原因却不太清楚。
程序就死在 lgdt   VGDTR这一行。如果这一句成功了,那么,全局描述符表就要换成应用程序里设置的了,整个WINDOWS是不是要死掉。WINDOWS不想死,所以不让程序这么做?
怎么做到的?是因为程序的权限被设为三级?三级之下不能加载GDTR?进而程序也不能把自己的权限提升到0级。那么那句.386P在编译时又做了些什么呢?
OF01662000在纯DOS下能否执行呢?为什么?
2013-4-29 21:25
0
雪    币: 183
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
程序1在实DOS下程序可执行,但调试还是没有办法。另外,程序2的编译……
2013-4-29 22:38
0
雪    币: 2242
活跃值: (488)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
5
调试用bochs
2013-4-29 22:49
0
雪    币: 183
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
用bochs,是不是要在虚拟盘上模拟DOS?
2013-4-30 00:28
0
雪    币: 183
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
INCLUDE         386SCD.INC
;----------------------------------------------------------------------------
DSEG            SEGMENT USE16                     ;16位数据段
;----------------------------------------------------------------------------
GDT             LABEL   BYTE                      ;全局描述符表
DUMMY           Desc    <>                        ;空描述符
Normal          Desc    <0ffffh,,,ATDW,,>         ;规范段描述符
Code32          Desc    <0,,,ATCE,D32,>    ;32位代码段描述符
Code16          Desc    <0ffffh,,,ATCE,,>         ;16位代码段描述符
DataS           Desc    <DataLen-1,0,10h,ATDR,,>  ;源数据段描述符
DataD           Desc    <3999,8000h,0bh,ATDW,,>   ;显示缓冲区描述符
Stacks          Desc    <StackLen-1,,,ATDW,,>     ;堆栈段描述符
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                     ;全局描述符表长度
VGDTR           PDesc   <GDTLen-1,>               ;伪描述符
;----------------------------------------------------------------------------
SaveSP          DW      ?                         ;用于保存SP寄存器
SaveSS          DW      ?                         ;用于保存SS寄存器
;----------------------------------------------------------------------------
Normal_Sel      =       Normal-GDT                ;规范段描述符选择子
Code32_Sel      =       Code32-GDT                ;32位代码段选择子
Code16_Sel      =       Code16-GDT                ;16位代码段选择子
DataS_Sel       =       Datas-GDT                 ;源数据段选择子
DataD_Sel       =       DataD-GDT                 ;目标数据段选择子
Stacks_Sel      =       Stacks-GDT                ;堆栈段描述符选择子
;----------------------------------------------------------------------------
DataLen         =       16
;----------------------------------------------------------------------------
DSEG            ENDS                              ;数据段定义结束
;----------------------------------------------------------------------------
StackSeg        SEGMENT PARA STACK USE16
StackLen        =       256
                DB      StackLen DUP(0)
StackSeg        ENDS
;----------------------------------------------------------------------------
CSEG1           SEGMENT USE16 'REAL'              ;16位代码段
                ASSUME  CS:CSEG1,DS:DSEG
;----------------------------------------------------------------------------
Start           PROC
                mov     ax,DSEG
                mov     ds,ax
push bx
mov ebx,C32Len
mov code32.limitl,bx
pop bx
                ;准备要加载到GDTR的伪描述符
                mov     bx,16
                mul     bx
                add     ax,OFFSET GDT             ;计算并设置基地址
                adc     dx,0                      ;界限已在定义时设置好
                mov     WORD PTR VGDTR.Base,ax
                mov     WORD PTR VGDTR.Base+2,dx
                ;设置32位代码段描述符
                mov     ax,CSEG2
                mul     bx
                mov     WORD PTR Code32.BaseL,ax
                mov     BYTE PTR Code32.BaseM,dl
                mov     BYTE PTR Code32.BaseH,dh
                ;设置16位代码段描述符
                mov     ax,CSEG3
                mul     bx
                mov     WORD PTR Code16.BaseL,ax  ;代码段开始偏移为0
                mov     BYTE PTR Code16.BaseM,dl  ;代码段界限已在定义时设置好
                mov     BYTE PTR Code16.BaseH,dh
                ;设置堆栈段描述符
                mov     ax,ss
                mov     WORD PTR SaveSS,ax
                mov     WORD PTR SaveSP,sp
                mov     ax,StackSeg
                mul     bx
                mov     WORD PTR Stacks.BaseL,ax
                mov     BYTE PTR Stacks.BaseM,dl
                mov     BYTE PTR Stacks.BaseH,dh
                ;加载GDTR
                lgdt    VGDTR;QWORD PTR VGDTR
                cli                               ;关中断
                EnableA20                         ;打开地址线A20
                ;切换到保护方式
                mov     eax,cr0
                or      al,1
                mov     cr0,eax
                ;清指令预取队列,并真正进入保护方式
                JUMP16  Code32_Sel,<OFFSET SPM32>
ToReal:         ;现在又回到实方式
                mov     ax,DSEG
                mov     ds,ax
                mov     sp,SaveSP
                mov     ss,SaveSS
                DisableA20
                sti
                mov     ax,4c00h
                int     21h
Start           ENDP
;----------------------------------------------------------------------------
CSEG1           ENDS                              ;代码段定义结束
;----------------------------------------------------------------------------
CSEG2           SEGMENT USE32 'PM32'
                ASSUME  CS:CSEG2
;----------------------------------------------------------------------------
SPM32           PROC
                mov     ax,Stacks_Sel
                mov     ss,ax
                mov     esp,StackLen
                mov     ax,DataS_Sel
                mov     ds,ax
                mov     ax,DataD_Sel
                mov     es,ax
                xor     esi,esi
                xor     edi,edi
                mov     ecx,DataLen
                cld
Next:           lodsb
                push    ax
                CALL    ToASCII
                mov     ah,7
                shl     eax,16
                pop     ax
                shr     al,4
                CALL    ToASCII
                mov     ah,7
                stosd
                mov     al,20h
                stosw
                loop    Next
                JUMP32   Code16_Sel,<OFFSET SPM16>
SPM32           ENDP
;----------------------------------------------------------------------------
ToASCII         PROC
                and     al,00001111b
                add     al,30h
                cmp     al,39h
                jbe     Isdig
                add     al,7
IsDig:          ret
ToASCII         ENDP
;----------------------------------------------------------------------------
C32Len          =       $
;----------------------------------------------------------------------------
CSEG2           ENDS
;----------------------------------------------------------------------------
CSEG3           SEGMENT USE16 'PM16'
                ASSUME  CS:CSEG3
;----------------------------------------------------------------------------
SPM16           PROC
                xor     si,si
                mov     di,DataLen*3*2
                mov     ah,7
                mov     cx,DataLen
AGain:          lodsb
                stosw
                loop    AGain
                mov     ax,Normal_sel
                mov     ds,ax
                mov     es,ax
                mov     ss,ax
                mov     eax,cr0
                and     al,11111110b
                mov     cr0,eax
                jmp     FAR PTR ToReal
SPM16           ENDP
;----------------------------------------------------------------------------
CSEG3           ENDS
;----------------------------------------------------------------------------
                END     Start

这样的教程还真是让人头疼
2013-5-3 20:28
0
雪    币: 276
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
不能用CMD命令执行,那个是模拟80X86,必须是在实模式下DOS系统执行,即必须装一未装载内存驱动,最大内存为1M的DOS系统下运行。。。
2013-6-1 21:37
0
游客
登录 | 注册 方可回帖
返回
//