汇编教程:控制转移(3)
2009-10-12 09:36:41 来源:WEB开发网<六>演示任务切换的实例(实例五)
下面给出一个用于演示任务切换的实例。该实例的逻辑功能是在切换后显示原任务的挂起点(EIP)的值。该实例演示内容包括:直接通过TSS段的任务切换,通过任务门的任务切换,任务内特权级的变换及参数传递。
1.实现步骤
为了达到演示任务切换和特权级变换的目的,实例五在保护方式下涉及到两个任务,一个任务称为临时任务,另一个任务称为演示任务。演示任务的功能是演示通过调用门实现特权级的变换和堆栈间参数的自动复制。临时任务和演示任务配合展示任务切换。实例五的主要实现步骤如下:
(1)实模式下初始化;
(2)切换到保护模式;
(3)设置TR对应临时任务,特权级为0;
(4)直接切换到演示任务,演示任务的特权级为2;
(5)把入口参数压入堆栈,经调用门进入显示信息子程序,显示信息子程序的特权级为0;
(6)从堆栈中取出入口参数并处理;
(7)从显示信息子程序返回特权级为2的演示代码段;
(8)为切换回实模式作部分准备工作;
(9)经任务门切换到特权级为0的临时任务;
(10)准备返回实模式;
(11)切换到实模式;
(12)实模式下的恢复工作。
在任务切换时,把原任务的现场保存到TR所指示的TSS内,然后再把指向目标任务的TSS描述符的选择子装入TR,所以在从临时任务切换到演示任务之前,要把指向临时任务TSS描述符的选择子装入TR。通过把演示任务的TSS初始化成恢复点在特权级2的代码段,使得从临时任务切换到演示任务后,当前特权级CPL=2。
2.源程序组织和清单
实例五由如下部分组成:
(1)全局描述符表GDT。GDT含有演示任务的TSS描述符和LDT段描述符,还含有临时任务TSS描述符和临时任务的代码段描述符,此外,还含有子程序代码段描述符、规范数据段描述符和视频缓冲区段描述符。
(2)演示任务的TSS。以根据演示要求初始化。
(3)演示任务的LDT段。它含有演示任务的0级和2级堆栈段描述符、代码段和数据段描述符、分别以数据段方式描述LDT和临时任务TSS的数据段描述符、以及指向子程序的调用门和指向临时任务的任务门。
(4)演示任务的0级和2级堆栈段。32位段,特权级分别为0和2。
(5)演示任务数据段。32位段,特权级3。
(6)子程序代码段。32位代码段,特权级0。
(7)演示任务代码段。32位代码段,特权级2。
(8)临时任务的TSS段。未初始化。
(9)临时任务代码段。16位代码段,特权级0。
(10)实模式下的数据和代码段。
该实例的逻辑功能是在切换后显示原任务的挂起点(EIP)的值。源程序清单如下:
;名称:ASM5.ASM
;功能:演示任务切换和任务内有特权级变换的转移
;编译:TASM ASM5.ASM
;链接:TLINK /32 ASM5.OBJ
;----------------------------------------------------------------------------
INCLUDE 386SCD.INC
;----------------------------------------------------------------------------
GDTSeg SEGMENT PARA USE16 ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
;全局描述符表
GDT LABEL BYTE
;空描述符
DUMMY Desc <>
;规范段描述符及选择子
Normal Desc <0ffffh,,,ATDW,,>
Normal_Sel = Normal-GDT
;视频缓冲区段描述符(DPL=3)及选择子
VideoBuf Desc <0ffffh,8000h,0bh,ATDW+DPL3,,>
Video_Sel = VideoBuf-GDT
;----------------------------------------------------------------------------
EFFGDT LABEL BYTE
;演示任务的局部描述符表段的描述符及选择子
DemoLDTab Desc <DemoLDTLen-1,DemoLDTSeg,,ATLDT,,>
DemoLDT_Sel = DemoLDTab-GDT
;演示任务的任务状态段描述符及选择子
DemoTSS Desc <DemoTSSLen-1,DemoTSSSeg,,AT386TSS,,>
DemoTSS_Sel = DemoTSS-GDT
;临时任务的任务状态段描述符及选择子
TempTSS Desc <TempTSSLen-1,TempTSSSeg,,AT386TSS+DPL2,,>
TempTSS_Sel = TempTSS-GDT
;临时代码段描述符及选择子
TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel = TempCode-GDT
;子程序代码段描述符及选择子
SubR Desc <SubRLen-1,SubRSeg,,ATCE,D32,>
SubR_Sel = SubR-GDT
;----------------------------------------------------------------------------
GDNum = ($-EFFGDT)/(SIZE Desc) ;需处理基地址的描述符个数
GDTLen = $-GDT ;全局描述符表长度
;----------------------------------------------------------------------------
GDTSeg ENDS ;全局描述符表段定义结束
;----------------------------------------------------------------------------
DemoLDTSeg SEGMENT PARA USE16 ;局部描述符表数据段(16位)
;----------------------------------------------------------------------------
DemoLDT LABEL BYTE ;局部描述符表
;0级堆栈段描述符(32位段)及选择子
DemoStack0 Desc <DemoStack0Len-1,DemoStack0Seg,,ATDW,D32,>
DemoStack0_Sel = DemoStack0-DemoLDT+TIL
;2级堆栈段描述符(32位段)及选择子
DemoStack2 Desc <DemoStack2Len-1,DemoStack2Seg,,ATDW+DPL2,D32,>
DemoStack2_Sel = DemoStack2-DemoLDT+TIL+RPL2
;演示任务代码段描述符(32位段,DPL=2)及选择子
DemoCode Desc <DemoCodeLen-1,DemoCodeSeg,,ATCE+DPL2,D32,>
DemoCode_Sel = DemoCode-DemoLDT+TIL+RPL2
;演示任务数据段描述符(32位段,DPL=3)及选择子
DemoData Desc <DemoDataLen-1,DemoDataSeg,,ATDW+DPL3,D32,>
DemoData_Sel = DemoData-DemoLDT+TIL
;把LDT作为普通数据段描述的描述符(DPL=2)及选择子
ToDLDT Desc <DemoLDTLen-1,DemoLDTSeg,,ATDW+DPL2,,>
ToDLDT_Sel = ToDLDT-DemoLDT+TIL
;把TSS作为普通数据段描述的描述符(DPL=2)及选择子
ToTTSS Desc <TempTSSLen-1,TempTSSSeg,,ATDW+DPL2,,>
ToTTSS_Sel = ToTTSS-DemoLDT+TIL
;----------------------------------------------------------------------------
DemoLDNum = ($-DemoLDT)/(SIZE Desc) ;需处理基地址的LDT描述符数
;----------------------------------------------------------------------------
;指向子程序SubRB代码段的调用门(DPL=3)及选择子
ToSubR Gate <SubRB,SubR_Sel,,AT386CGate+DPL3,>
ToSubR_Sel = ToSubR-DemoLDT+TIL+RPL2
;指向临时任务Temp的任务门(DPL=3)及选择子
ToTempT Gate <,TempTSS_Sel,,ATTaskGate+DPL3,>
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,0 ;1级堆栈选择子(实例不使用)
DD 0 ;2级堆栈指针
DW 0,0 ;2级堆栈选择子
DD 0 ;CR3
DW DemoBegin,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 1986 ;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 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
DemoDataLen = $
DemoDataSeg ENDS ;演示任务数据段结束
;----------------------------------------------------------------------------
SubRSeg SEGMENT PARA USE32 ;子程序代码段(32位)
ASSUME CS:SubRSeg
;----------------------------------------------------------------------------
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
;----------------------------------------------------------------------------
SubRLen = $
SubRSeg ENDS ;子程序代码段结束
;----------------------------------------------------------------------------
DemoCodeSeg SEGMENT PARA USE32 ;演示任务的32位代码段
ASSUME CS:DemoCodeSeg,DS:DemoDataSeg
;----------------------------------------------------------------------------
DemoBegin PROC FAR
;把要复制的参数个数置入调用门
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
jmp DemoBegin
DemoBegin ENDP
DemoCodeLen = $
;----------------------------------------------------------------------------
DemoCodeSeg ENDS ;演示任务的32位代码段结束
;----------------------------------------------------------------------------
TempTSSSeg SEGMENT PARA USE16 ;临时任务的任务状态段TSS
TempTask TSS <>
DB 0ffh ;I/O许可位图结束标志
TempTSSLen = $
TempTSSSeg ENDS
;----------------------------------------------------------------------------
TempCodeSeg SEGMENT PARA USE16 ;临时任务的代码段
ASSUME CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual PROC FAR
mov ax,TempTSS_Sel ;装载TR
ltr ax
JUMP16 DemoTSS_Sel,0 ;直接切换到演示任务
clts ;清任务切换标志
mov eax,cr0 ;准备返回实模式
and al,11111110b
mov cr0,eax
JUMP16 <SEG Real>,<OFFSET Real>
Virtual ENDP
;----------------------------------------------------------------------------
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 PROC
mov ax,RDataSeg
mov ds,ax
cld
call InitGDT ;初始化全局描述符表GDT
mov ax,DemoLDTSeg
mov fs,ax
mov si,OFFSET DemoLDT
mov cx,DemoLDNum
call InitLDT ;初始化局部描述符表LDT
mov SSVar,ss
mov SPVar,sp
lgdt QWORD 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
Start ENDP
;----------------------------------------------------------------------------
InitGDT PROC
push ds
mov ax,GDTSeg
mov ds,ax
mov cx,GDNum
mov si,OFFSET EFFGDT
InitG: mov ax,[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR [si].BaseL,ax
mov BYTE PTR [si].BaseM,dl
mov BYTE PTR [si].BaseH,dh
add si,SIZE Desc
loop InitG
pop ds
mov bx,16
mov ax,GDTSeg
mul bx
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
ret
InitGDT ENDP
;----------------------------------------------------------------------------
;入口参数:FS:SI=第一个要初始化的描述符,CX=要初始化的描述符数
;----------------------------------------------------------------------------
InitLDT PROC
mov ax,WORD PTR fs:[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR fs:[si].BaseL,ax
mov BYTE PTR fs:[si].BaseM,dl
mov BYTE PTR fs:[si].BaseH,dh
add si,SIZE Desc
loop InitLDT
ret
InitLDT ENDP
;----------------------------------------------------------------------------
RCodeSeg ENDS
END Start
更多精彩
赞助商链接