演示任务切换的实例(实例五)--RadASM编译

来源:互联网 发布:微信业务域名是什么 编辑:程序博客网 时间:2024/06/05 05:05

以下代码用RadASM编译(其实也是用MASM编译的),BOCHS调试成功。

红色字体是经过增加或修改的,否则不能编译成功,相信会节省初学者不少精力。

INCLUDE         386SCD.INC
;----------------------------------------------------------------------------


GDTSEG          SEGMENT PARA USE16                ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
                ;全局描述符表
GDT             LABEL   BYTE
                ;空描述符
DUMMY           DESCRIPTOR    <>
                ;规范段描述符及选择子
Normal          DESCRIPTOR    <0ffffh,0,0,ATDW,0>
Normal_Sel      =       Normal-GDT
                ;视频缓冲区段描述符(DPL=3)及选择子
EFFGDT          LABEL   BYTE
               ;演示任务的任务状态段描述符及选择子
DemoTSS         DESCRIPTOR    <DemoTSSLen-1,DemoTSSSeg,,AT386TSS,>
DemoTSS_Sel     =       DemoTSS-GDT


                ;演示任务的局部描述符表段的描述符及选择子
DemoLDTab       DESCRIPTOR    <DemoLDTLen-1,DemoLDTSeg,,ATLDT,>
DemoLDT_Sel     =       DemoLDTab-GDT
 
                ;临时任务的任务状态段描述符及选择子
TempTSS         DESCRIPTOR    <TempTSSLen-1,TempTSSSeg,,AT386TSS+DPL2,>
TempTSS_Sel     =       TempTSS-GDT
                ;临时代码段描述符及选择子
TempCode        DESCRIPTOR    <0ffffh,TempCodeSeg,,ATCE,>
TempCode_Sel    =       TempCode-GDT
               
                ;子程序代码段描述符及选择子
SubR            DESCRIPTOR    <SubRLen32-1,SubRSeg,,ATCE+D32,>
SubR_Sel        =       SubR-GDT+RPL3


; VIDEOBUFF       DESCRIPTOR    <0ffffh,8000h,0bh, ATDW+DPL3,>
VIDEOBUFF DESCRIPTOR<0FFFFH,0,0,0F00H+ATDW+DPL3,0>
Video_SEL = VIDEOBUFF   - GDT
;----------------------------------------------------------------------------


GDNUM           =       ($-EFFGDT)/(SIZE DESCRIPTOR)    ;需处理基地址的描述符个数
GDTLen          =       $-GDT                     ;全局描述符表长度


;----------------------------------------------------------------------------
GDTSEG          ENDS                              ;全局描述符表段定义结束
;----------------------------------------------------------------------------
DemoLDTSeg      SEGMENT PARA USE16                ;局部描述符表数据段(16位)


;----------------------------------------------------------------------------
DemoLDT         LABEL   BYTE                      ;局部描述符表
                ;0级堆栈段描述符(32位段)及选择子
DemoStack0      DESCRIPTOR    <DemoStack0Len-1,DemoStack0Seg,,ATDW+D32,>


DemoStack0_Sel  =       DemoStack0-DemoLDT+TIL
                ;2级堆栈段描述符(32位段)及选择子
DemoStack2      DESCRIPTOR    <DemoStack2Len-1,DemoStack2Seg,,ATDW+DPL2+D32,>


DemoStack2_Sel  =       DemoStack2-DemoLDT+TIL+RPL2
                ;演示任务代码段描述符(32位段,DPL=2)及选择子
DemoCode        DESCRIPTOR    <DemoCodeLen32-1,DemoCodeSeg,,ATCE+DPL2+D32,>


DemoCode_Sel    =       DemoCode-DemoLDT+TIL+RPL2
                ;演示任务数据段描述符(32位段,DPL=3)及选择子
DemoData        DESCRIPTOR    <DemoDataLen32-1,DemoDataSeg,,ATDW+DPL3+D32,>


DemoData_Sel    =       DemoData-DemoLDT+TIL
                ;把LDT作为普通数据段描述的描述符(DPL=2)及选择子
ToDLDT          DESCRIPTOR    <DemoLDTLen-1,DemoLDTSeg,,ATDW+DPL2,>


ToDLDT_Sel      =       ToDLDT-DemoLDT+TIL
                ;把TSS作为普通数据段描述的描述符(DPL=2)及选择子
ToTTSS          DESCRIPTOR    <TempTSSLen-1,TempTSSSeg,,ATDW+DPL2,>


ToTTSS_Sel      =       ToTTSS-DemoLDT+TIL
;----------------------------------------------------------------------------
DemoLDNum       =       ($-DemoLDT)/(SIZE DESCRIPTOR)   ;需处理基地址的LDT描述符数


;----------------------------------------------------------------------------
                ;指向子程序SubRB代码段的调用门(DPL=3)及选择子
ToSubR          GATE    <SubRB32,SubR_Sel,0,AT386CGAT+DPL3,0>
ToSubR_Sel      =       ToSubR-DemoLDT+TIL+RPL2
                ;指向临时任务Temp的任务门(DPL=3)及选择子


ToTempT         GATE    <0,TempTSS_Sel,0,ATTASKGAT+DPL3,0>
ToTempT_Sel     =       ToTempT-DemoLDT+TIL


;----------------------------------------------------------------------------
DemoLDTLen      =       $-DemoLDT
;----------------------------------------------------------------------------
DemoLDTSeg      ENDS                              ;局部描述符表段定义结束
;----------------------------------------------------------------------------
DemoTSSSeg      SEGMENT PARA USE16                ;任务状态段TSS


;----------------------------------------------------------------------------
                DD      0                         ;链接字
                DD      DemoStack0Len             ;0级堆栈指针
                DW      DemoStack0_Sel,0          ;0级堆栈选择子


                DD      0                         ;1级堆栈指针(实例不使用)
                DW      ?,0                       ;1级堆栈选择子(实例不使用)
                
                DD      DemoStack2Len                        ;2级堆栈指针
                DW      DemoStack2_Sel,0                       ;2级堆栈选择子
                DD      0                         ;CR3
                DW      DemoBegin32,0               ;EIP


                DD      0                         ;EFLAGS
                DD      0                         ;EAX
                DD      0                         ;ECX


                DD      0                         ;EDX
                DD      0                         ;EBX
                DD      DemoStack2Len             ;ESP


                DD      0                         ;EBP
                DD      0                         ;ESI
                DD      0b8000h                  ;EDI
                DW      Video_SEL,0               ;ES
                DW      DemoCode_Sel,0            ;CS


                DW      DemoStack2_Sel,0          ;SS
                DW      DemoData_Sel,0            ;DS


                DW      ToDLDT_Sel,0              ;FS
                DW      ToTTSS_Sel,0              ;GS


                DW      DemoLDT_Sel,0             ;LDTR
                DW      0                         ;调试陷阱标志
                DW      $+2                       ;指向I/O许可位图


                DB      0ffh                      ;I/O许可位图结束标志
DemoTSSLen      =       $ - DemoTSSSeg
DemoTSSSeg      ENDS                              ;任务状态段TSS结束


;----------------------------------------------------------------------------




DemoStack0Seg   SEGMENT PARA USE32                ;演示任务0级堆栈段(32位段)
DemoStack0Len   =       1024
                DB      DemoStack0Len DUP(0)


DemoStack0Seg   ENDS                              ;演示任务0级堆栈段结束
;----------------------------------------------------------------------------
DemoStack2Seg   SEGMENT PARA USE32               ;演示任务2级堆栈段(32位段)
DemoStack2Len   =       512


                DB      DemoStack2Len DUP(0)
DemoStack2Seg   ENDS                              ;演示任务2级堆栈段结束
;----------------------------------------------------------------------------
DemoDataSeg     SEGMENT PARA USE32                ;演示任务数据段(32位段)


Message         DB      'Value=',0
DemoDataLen32 equ this word
DemoDataLen     =       $ - DemoDataSeg
DemoDataSeg     ENDS                              ;演示任务数据段结束


;----------------------------------------------------------------------------
SubRSeg         SEGMENT PARA USE32                ;子程序代码段(32位)
                ASSUME  CS:SubRSeg
;----------------------------------------------------------------------------
SubRB32 equ this word
SubRB           PROC    FAR
                push    ebp
                mov     ebp,esp


                pushad                            ;保护现场
                mov     esi,DWORD PTR [ebp+12]    ;从0级栈中取出显示串偏移


                mov     ah,4ah                    ;设置显示属性
                jmp     SHORT SubR2
SubR1:          stosw


SubR2:          lodsb
                or      al,al
                jnz     SubR1
                mov     ah,4eh                    ;设置显示属性


                mov     edx,DWORD PTR [ebp+16]    ;从0级栈中取出显示值


                mov     ecx,8
SubR3:          rol     edx,4
                mov     al,dl


                call    HToASCII
                stosw
                loop    SubR3
                popad
                pop     ebp


                ret     8
SubRB           ENDP
;----------------------------------------------------------------------------
HToASCII        PROC
                and     al,0fh


                add     al,90h
                daa
                adc     al,40h
                daa
                ret
HToASCII        ENDP
SubRLen32 equ this word
SubRLen         =       $ - SubRSeg
SubRSeg         ENDS                              ;子程序代码段结束


;----------------------------------------------------------------------------
DemoCodeSeg     SEGMENT PARA USE32                ;演示任务的32位代码段
                ASSUME  CS:DemoCodeSeg


;----------------------------------------------------------------------------
DemoBegin32 equ this word
DemoBegin :     
                ;把要复制的参数个数置入调用门
                mov     BYTE PTR fs:ToSubR.DCOUNT,2


                ;向2级堆栈中压入参数
                push    DWORD PTR gs:TempTask.TREIP
                push    OFFSET Message
                ;通过调用门调用SubRB


                CALL32  ToSubR_Sel,0
                ;把指向规范数据段描述符的选择子填入临时任务TSS
                ASSUME  DS:TempTSSSeg
                push    gs


                pop     ds
                mov     ax,Normal_Sel
                mov     WORD PTR TempTask.TRDS,ax


                mov     WORD PTR TempTask.TRES,ax
                mov     WORD PTR TempTask.TRFS,ax


                mov     WORD PTR TempTask.TRGS,ax
                mov     WORD PTR TempTask.TRSS,ax


                ;通过任务门切换到临时任务
                JUMP32  ToTempT_Sel,0
       DemoCodeLen32 equ this word
DemoCodeLen     =       $ - DemoCodeSeg
DemoCodeSeg     ENDS                              ;演示任务的32位代码段结束




;----------------------------------------------------------------------------
TempTSSSeg      SEGMENT PARA USE16                ;临时任务的任务状态段TSS


TempTask        TASKSS     <>
                DB      0ffh                      ;I/O许可位图结束标志
TempTSSLen      =       $  
TempTSSSeg      ENDS


;----------------------------------------------------------------------------
TempCodeSeg     SEGMENT PARA USE16                ;临时任务的代码段
                ASSUME  CS:TempCodeSeg
;----------------------------------------------------------------------------


Virtual  :
                mov     ax,TempTSS_Sel            ;装载TR
                ltr     ax


                JUMP16  DemoTSS_Sel,0             ;直接切换到演示任务
         ToReal:
                clts                              ;清任务切换标志
                mov     eax,cr0                   ;准备返回实模式


                and     al,0fffffffeh
                mov     cr0,eax
                JUMP16  <SEG Real>,<OFFSET Real>
TempCodeLEN = $ - TempCodeSeg


TempCodeSeg     ENDS
;============================================================================
RDataSeg        SEGMENT PARA USE16                ;实方式数据段


VGDTR           PDESC   <GDTLen-1,>               ;GDT伪描述符
SPVar           DW      ?                         ;用于保存实方式下的SP
SSVar           DW      ?                         ;用于保存实方式下的SS


RDataSeg        ENDS
;----------------------------------------------------------------------------
RCODESEG        SEGMENT PARA USE16
                ASSUME  CS:RCODESEG,DS:RDataSeg,ES:RDataSeg


;----------------------------------------------------------------------------
Start  :        
;jmp $ ;bochs调试时使用,CTRL+C中断后,set $eip = 2 ,C运行即可。
                mov     ax,RDataSeg
                mov     ds,ax


                cld
                call    INIT_GDT                   ;初始化全局描述符表GDT
                mov     ax,DemoLDTSeg
                mov     fs,ax


                mov     si,OFFSET DemoLDT
                mov     cx,DemoLDNum
                call    INIT_LDT                   ;初始化局部描述符表LDT


                mov     SSVar,ss
                mov     SPVar,sp
                lgdt    FWORD PTR VGDTR           ;装载GDTR并切换到保护方式


                cli
                mov     eax,cr0
                or      al,1


                mov     cr0,eax
                JUMP16  <TempCode_Sel>,<OFFSET Virtual>
Real:           mov     ax,RDataSeg
                mov     ds,ax


                lss     sp,DWORD PTR SPVar        ;又回到实方式
                sti
                mov     ax,4c00h


                int     21h


;----------------------------------------------------------------------------
;初始化全局描述表的子程序
;(1)把定义时预置的段值转移成32位段基地址并置入描述符内相应字段;初始化GDT中的描述符
;(2)初始化为GDTR准备的伪描述符                                  ;初始化GDT伪描述符
INIT_GDT        PROC    NEAR               
PUSH    DS
        MOV     AX,GDTSEG
        MOV     DS,AX
        MOV     CX,GDNUM                ;GDNUM是初始化的描述符个数
        MOV     SI,OFFSET EFFGDT        ;EFFGDT是开始偏移值
        ASSUME SI:PTR DESCRIPTOR
INITG:  MOV     AX,[SI].BASEL           ;取出预置的段值
        MOVZX   EAX,AX                  ;扩展到32位
        SHL     EAX,4
        SHLD    EDX,EAX,16              ;分解到2个16位寄存器
        MOV     [SI].BASEL,AX
        MOV     [SI].BASEM,DL           ;置入描述符相应字段
        MOV     [SI].BASEH,DH
        ADD     SI,SIZE DESCRIPTOR      ;调整到下一描述符
        LOOP    INITG
        ASSUME SI:NOTHING
        POP     DS
        ;
        MOV     BX,16                   ;初始化为GDTR准备的伪描述符
        MOV     AX,GDTSEG
        MUL     BX
        MOV     WORD PTR VGDTR.BASE,AX
        MOV     WORD PTR VGDTR.BASE+2,DX
        ret
INIT_GDT endp
;
;初始化演示任务局部描述符的子程序
;把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
;入口参数:FS:SI=第一个要初始化的描述符
;         CX  = 要初始化的描述符个数
INIT_LDT        PROC
        ASSUME SI:PTR DESCRIPTOR


ILDT:   MOV     AX,FS:[SI].BASEL
        MOVZX   EAX,AX
        SHL     EAX,4
        SHLD    EDX,EAX,16
        MOV     FS:[SI].BASEL,AX
        MOV     FS:[SI].BASEM,DL
        MOV     FS:[SI].BASEH,DH
        ADD     SI,SIZE DESCRIPTOR
        LOOP    ILDT
        ASSUME SI:NOTHING
        ret
INIT_LDT endp
RCODESEG        ENDS
END Start


运行结果:见图





386SCD.INC

;..........................
.386P
;存储段和系统段描述符
DESCRIPTOR STRUC
LIMITL     DW 0
BASEL      DW 0
BASEM      DB 0
ATTRIBUTES DW 0
BASEH      DB 0


DESCRIPTOR ENDS
;.........................
;门描述符
GATE STRUC
OFFSETL  DW 0
SELECTOR DW 0
DCOUNT   DB 0
GTYPE    DB 0
OFFSETH  DW 0
GATE ENDS




;.........................
;伪描述符
PDESC STRUC
LIMIT DW 0
BASE  DD 0
PDESC ENDS
;.........................


;TASKSS任务状态段内容
TASKSS STRUC
TRLINK DW ?,0
TRESP0 DD ?
TRSS0   DW ?,0
TRESP1 DD ?
TRSS1   DW ?,0
TRESP2 DD ?
TRSS2   DW ?,0
TRCR3   DD ?
TREIP   DD ?
TREFLAG DW ?,?
TREAX   DD ?
TRECX   DD ?
TREDX   DD ?
TREBX   DD ?
TRESP   DD ?
TREBP   DD ?
TRESI   DD ?
TREDI   DD ?
TRES    DW ?,0
TRCS    DW ?,0
TRSS DW ?,0
TRDS DW ?,0
TRFS DW ?,0
TRGS DW ?,0
TRLDT DW ?,0
TRFLAG DW 0
TRIOMAP DW $+2
TASKSS ENDS
;..........................
;存储段描述符类型值说明
ATDR =90H
ATDW =92H
ATDWA =93H
ATCE =98H
ATCER =9AH
ATCCO =9CH
ATCCOR =9EH
;系统段描述符和门描述符类型值说明
ATLDT =82H
ATTASKGAT =85H
AT386TSS =89H
AT386CGAT =8CH
AT386IGAT =8EH
AT386TGAT =8FH
;DPL和RPL值说明
;..........................


DPL1 =20H
DPL2 =40H
DPL3 =60H
RPL1 =01H
RPL2 =02H
RPL3 =03H
IOPL1 =1000H
IOPL2 =2000H
IOPL3 =3000H
;.............................






;其它常量说明
D32 =4000H
TIL =04H
VMFL =0002H
IFL =0200H
;.............................


;段间转移及段间调用宏
JUMP32 MACRO selector,offsetv
DB 0EAH
DW offsetv
DW 0
DW selector
ENDM
CALL32 MACRO selector,offsetv
DB 09AH
DW offsetv
DW 0
DW selector
ENDM


JUMP16 MACRO selector,offsetv
DB 0EAH
DW offsetv
DW selector
ENDM
CALL16 MACRO selector,offsetv
DB 9AH
DW offsetv
DW selector
ENDM


;................................

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 发烧没药怎么办怎样退烧快 小孩发烧怎么办怎样退烧快 发烧头疼怎么办最快最有效 发烧头晕怎么办最快最有效 婴儿发烧怎么办最快最有效 孩子一直37度8怎么办 一岁半宝宝37度5怎么办 发烧打了针35度怎么办 小孩发烧吃了鱼怎么办 八个月婴儿发烧39度怎么办 婴儿反复发烧39度怎么办 宝宝发烧了怎么办如何退烧 宝宝烧到38.8度怎么办 小孩发烧到39度怎么办 宝贝发烧到40度怎么办 孩子发烧39度8怎么办 儿子发烧39度该怎么办 孩子发烧39度7怎么办 7个月婴儿发烧怎么办 感冒了头发很油怎么办 5岁宝宝发烧39度怎么办 婴儿烧到39.5度怎么办 1岁多宝宝39.5度怎么办 宝宝发烧40多度怎么办 7岁宝宝发烧了怎么办 宝宝反复发烧39度怎么办 一岁半宝宝反复发烧39度怎么办 七岁发烧38度怎么办 小孩一直37度1怎么办 婴儿一直37度多怎么办 1岁半高烧39度怎么办 反复发烧39度多怎么办 孩子不爱喝水怎么办%3f 8岁儿童不爱喝水怎么办 儿子14岁了不爱说话怎么办 我孩子长得老慢怎么办 老公嫌你烦了怎么办 2岁宝宝吃饭不嚼怎么办 2岁宝宝挑食厌食怎么办 孩子不爱和家长交流怎么办 孩子发烧在医院查不出病因怎么办