📄 dtos.asm
字号:
mov gs,ax ;把演示任务LDT选择子填入TSS
mov WORD PTR gs:DemoTaskSS.TRLDTR,DemoLDT_Sel
mov ax,DemoTSS_Sel
ltr ax ;装载TR
mov ax,DemoData_Sel
mov ds,ax ;装载其它数据段寄存器
mov ax,VideoBuf_Sel
mov es,ax
mov ax,XBuffer_Sel
mov fs,ax
mov ax,EchoData_Sel
mov gs,ax
MOV DX,28BH ;写8255的控制字
MOV AL,80H
OUT DX, AL ;用A口输出
MOV BYTE PTR fs:NOW,01H
JUMP16 DispTSS_Sel,0 ;开始电梯在1楼,数码
MOV DX,288H
MOV AL,00H
OUT DX,AL ;流水灯全灭
in al,imregp
mov savemask,al
CLTS
; mov al,11111110b ;置中断屏蔽字
; out IMREGP,al ;只开发时钟中断
; sti ;开中断
;DemoConti: cmp BYTE PTR FS:Flag,0 ;判标志
; jz DemoConti ;直到不为0
; mov al,0ffh
; out IMREGP,al ;只开发时钟中断
cli ;关中断
choose:
int 0ffh ;接收要模拟的异常类型号
mov al,BYTE PTR fs:KeyASCII ;按接收的字符模拟异常号
cmp al,'Q'
jnz YY
jmp Over
YY: CMP AL,'R'
JNZ LL
MOV BL,BYTE PTR fs:NUM2 ;若键入R 将num2的值赋给 num1
MOV BYTE PTR fs:NUM1,BL ;并将num2置0
MOV AL,0
MOV BYTE PTR fs:NUM2,AL
JMP LOP1
LL: SUB AL,30H
MOV BYTE PTR fs:NUM1,AL ;将键入希望到达楼层数保存在 num1中
CMP BYTE PTR fs:NOW,AL
JZ choose
JUMP16 LedTSS_Sel,0 ;开始电梯在1楼,数码
CLTS
waitrun:
int 0ffh ;接收要模拟的异常类型号
mov al,BYTE PTR fs:KeyASCII ;按接收的字符模拟异常号
CMP AL,'R'
JNZ waitrun
LOP1: MOV AL,BYTE PTR fs:NUM1
CMP AL,BYTE PTR fs:NOW ;希望到达层数与电梯所在层比较
JA UP0 ;若大则上升
JB DOWN0 ;若小则下降
UP0:
int 0fdh ;接收要模拟的异常类型号
mov al,BYTE PTR fs:KeyASCII ;按接收的字符模拟异常号
and al,al
JZ UP1
SUB AL,30H
MOV BYTE PTR fs:NUM2,AL
JUMP16 LedTSS_Sel,0 ;开始电梯在1楼,数码
CMP BYTE PTR fs:NUM1,AL ;第一、二次希望到达层数比较
JB UP1 ;第一次小则电梯继续上升
CMP BYTE PTR fs:NOW,AL ;电梯所在层与第二次希望到达层比较
JA UP1 ;所在层大则电梯继续上升
MOV BL,BYTE PTR fs:NUM1 ;第二次希望到达层在所在层和第一次希望到达
MOV BYTE PTR fs:NUM2,BL ;层之间则交换num1和num2的值后继续上升
MOV BYTE PTR fs:NUM1,AL
UP1:
; CALL TIME ;两秒延时
mov al,11111110b ;置中断屏蔽字
out IMREGP,al
; mov byte ptr gs:messdata, '2' ;只开发时钟中断
; mov byte ptr fs:flag,0
sti ;开中断
DemoConti1: cmp BYTE PTR FS:Flag,0 ;判标志
jz DemoConti1 ;直到不为0
mov al,0ffh
out IMREGP,al ;只开发时钟中断
cli ;关中断
INC BYTE PTR fs:NOW ;now自增
JUMP16 DispTSS_Sel,0 ;开始电梯在1楼,数码
CLTS
MOV AL,BYTE PTR fs:NUM1
CMP BYTE PTR fs:NOW,AL ;判断是否达到希望到达层
JB UP0 ;还没有则继续上升
MOV AL,0 ;到达的话num1清0使对应流水灯熄灭
MOV BYTE PTR fs:NUM1,AL
JUMP16 LedTSS_Sel,0 ;开始电梯在1楼,数码
CLTS
JMP choose ;返回程序起点
DOWN0:
int 0fdh ;接收要模拟的异常类型号
mov al,BYTE PTR fs:KeyASCII ;按接收的字符模拟异常号
and al,al
JZ DOWN1
SUB AL,30H
MOV NUM2,AL
JUMP16 LedTSS_Sel,0 ;
CALL TIME ;两秒延时
CMP BYTE PTR fs:NUM1,AL ;第一、二次希望到达层数比较
JA DOWN1 ;第一次大则电梯继续下降
CMP BYTE PTR fs:NOW,AL ;电梯所在层与第二次希望到达层比较
JB DOWN1 ;所在层小则电梯继续上升
MOV BL,BYTE PTR fs:NUM1 ;第二次希望到达层在所在层和第一次希望到达
MOV BYTE PTR fs:NUM2,BL ;层之间则交换num1和num2的值后继续下降
MOV BYTE PTR fs:NUM1,AL
DOWN1:
CALL TIME ;两秒延时
DEC BYTE PTR fs:NOW ;now自减
JUMP16 DispTSS_Sel,0 ;开始电梯在1楼,数码管显示
CLTS
MOV AL,BYTE PTR fs:NUM1
CMP BYTE PTR fs:NOW,AL ;判断是否达到希望到达层
JA DOWN0 ;还没有则继续下降
MOV AL,0
MOV BYTE PTR fs:NUM1,AL ;到达的话num1清0使对应流水灯熄灭
JUMP16 LedTSS_Sel,0 ;开始电梯在1楼,数码
JMP choose ;返回程序起点
TIME PROC NEAR ;2秒延时子程序
PUSH CX
PUSH DI
mov cx,0FFFFH
de1: mov di,9000
de0: dec di
jnz de0
loop de1
POP DI
POP CX
RET
TIME ENDP
Over:
mov al,savemask
out imregp,al
;转临时代码段
JUMP16 TempCode_Sel,<OFFSET ToDos>
DemoBegin ENDP
;----------------------------------------------------------------------------
DemoCodeLen = $
DemoCodeSeg ENDS
;----------------------------------------------------------------------------
TempCodeSeg SEGMENT PARA USE16 ;临时任务的代码段
ASSUME CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual PROC FAR
JUMP16 DemoCode_Sel,DemoBegin ;转演示任务
ToDos: mov ax,Normal_Sel ;恢复实方式段描述符高速缓存
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
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伪描述符
VIDTR PDesc <IDTLen-1,> ;IDT伪描述符
NORVIDTR PDesc <3ffh,> ;用于保存原IDTR值
SPVar DW ? ;用于保存实方式下的SP
SSVar DW ? ;用于保存实方式下的SS
MESS DB 0AH,0DH,'Press 1-8 to reach your desired the floor'
DB 0AH,0DH,'Press Q to quit '
DB 0AH,0DH,'Press R to run '
DB 0AH,0DH,'$'
RDataSeg ENDS
;----------------------------------------------------------------------------
RCodeSeg SEGMENT PARA USE16 ;实方式代码段
ASSUME CS:RCodeSeg,DS:RDataSeg
;---------------------------------------------------------------------------,
Start PROC
mov ax,RDataSeg
mov ds,ax
cld
call InitGDT ;初始化全局描述符表GDT
call InitIDT ;初始化中断描述符表IDT
mov ax,GKeyLDTSeg
mov fs,ax
mov cx,GKeyLDNum
mov si,OFFSET GLDT
CALL InitLDT
mov ax,KeyLDTSeg
mov fs,ax
mov cx,KeyLDNum
mov si,OFFSET KLDT
CALL InitLDT
mov ax,DispLDTSeg
mov fs,ax
mov cx,DispLDNum
mov si,OFFSET DiLDT
CALL InitLDT
mov ax,LedLDTSeg
mov fs,ax
mov cx,LedLDNum
mov si,OFFSET LeLDT
CALL InitLDT
mov ax,DemoLDTSeg
mov fs,ax
mov cx,DemoLDNum
mov si,OFFSET DLDT
CALL InitLDT
mov SSVar,ss ;保存堆栈指针
mov SPVar,sp
lgdt QWORD PTR VGDTR ;装载GDTR
sidt QWORD PTR NORVIDTR ;保存IDTR
cli ;关中断
lidt QWORD PTR VIDTR ;装载IDTR
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 ;又回到实方式
lidt QWORD PTR NORVIDTR
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
;----------------------------------------------------------------------------
InitIDT PROC
mov bx,16
mov ax,IDTSeg
mul bx
mov WORD PTR VIDTR.Base,ax
mov WORD PTR VIDTR.Base+2,dx
ret
InitIDT ENDP
;-,---------------------------------------------,----------------------------
;入口参数:FS:SI=第一个要初始化的描述符,CX=要初始化的描述符数
;----------------------------------,-----------------------------------------
InitLDT PROC
ILDT: 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 ILDT
ret
InitLDT ENDP
;----------------------------------------------------------------------------
RCodeSeg ENDS
END Start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -