演示任务切换的实例(实例五)--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
;................................
- 演示任务切换的实例(实例五)--RadASM编译
- AsyncTask实例代码演示Android异步任务
- zthread学习 实例五 非任务对象的生存期
- zthread学习 实例五 非任务对象的生存期
- Java与Highcharts实例(五) - 切换主题
- Activiti——工作流之流程实例、任务的执行(五)
- ant的任务实例
- 异步任务的实例
- 安卓(android)五大布局总结以及实例演示
- (转)wait和sleep的区别 以及 实例演示
- Auth权限控制的实例代码演示(thinkphp)
- 实例演示(列表一个开其余的关)
- html中的简单实例演示(checkbox)的使用
- Spring学习(六)实例演示Spring的使用
- 一个多线程和队列的实例演示
- SQL_Server全文索引的使用实例演示
- 实例演示Java的内存分析
- 【数据结构】红黑树插入的实例演示
- 关于字库中字模的偏移量算法
- STL—其它容器
- TrueType core fonts for the Web EULA问题解决方案
- tomcat限制ip访问
- Oracle创建自动增长列
- 演示任务切换的实例(实例五)--RadASM编译
- UIView的layout(布局)与draw(绘图)
- Java中怎样实现批量删除操作(Java对数据库进行事务处理)?
- ffmepg框架阅读之三:AVIOContext的标准初始化
- NFC标签及标签种类
- http://blog.csdn.net/xpp1993/article/details/9002598
- OpenSSL证书创建、验证及加解密过程总结
- 关于联想新电脑安装win7系统的一些问题
- windows消息从User32 内核出来之后逆向过程