📄 pmstart8.asm
字号:
;----------------------------------------------------------------------------
;pmstart8.asm
;从实模式进入保护模式,进入主任务.
;通过陷阱门INT 0FEh进行字符串输出,提示用户操作
;通过任务状态段TSS进行任务切换
;通过8255的C口读开关量.K0=1返回实模式,K1=1时进入TaskA
;K2=1进入TaskB,K3=1时从TaskA或TaskB返回主任务
;TaskA:点阵扫描
;TaskB:七段数码管显示00-99
;接线:8255CS->0x288
;点阵的行选借280H,列选接290H
;PA0-PA6->七段数码管a-g,PB0-PB1->七段数码管S0-S1.PC0-PC3->K0-K3
;----------------------------------------------------------------------------
include pmstart.inc
.386p
;--------------------------
;全局描述符表GDT
GdtSeg segment para use16 'GDT'
gdt LABEL BYTE
Dummy Desc <>
NormalSel=$-gdt
Normal Desc <0ffffh,,,92h,,>
;视频缓冲区段描述符及选择子
VideoSel=$-gdt
Video Desc <0ffffh,8000h,0bh,92h,,>
effgdt LABEL BYTE
;临时代码段描述符及选择子
TempCodeSel=$-gdt
TempCode Desc <0ffffh,TempCodeSeg,,98H,,>
;主任务代码段描述符及选择子
SysCodeSel=$-gdt
Syscode Desc <SysCodeLen-1,SysCodeSeg,,98H,,>
;主任务状态段TSS描述符及选择子
SysTssSel=$-gdt
SysTss Desc <SysTssLen-1,SysTssSeg,,89h,,>
;主任务LDT描述符及选择子
SysLdtSel=$-gdt
SysLdt Desc <SysLdtLen-1,SysLdtSeg,,82h,,>
;TaskA任务状态段TSS描述符及选择子
TaskATssSel=$-gdt
TaskATss Desc <TaskATssLen-1,TaskATssSeg,,89h,,>
;TaskA任务LDT描述符及选择子
TaskALdtSel=$-gdt
TaskALdt Desc <TaskALdtLen-1,TaskALdtSeg,,82h,,>
TaskBTssSel=$-gdt
TaskBTss Desc <TaskBTssLen-1,TaskBTssSeg,,89h,,>
TaskBLdtSel=$-gdt
TaskBLdt Desc <TaskBLdtLen-1,TaskBLdtSeg,,82h,,>
;显示陷阱处理程序代码段描述符及选择子
EchoCodeSel=$-gdt
EchoCode Desc <EchoCodeLen-1,EchoCodeSeg,,98h,,>
GdtNum=($-effgdt)/(size Desc)
GdtLen =$-gdt
GdtSeg ends
;----------------------------
;中断描述符表IDT
IdtSeg segment
idt LABEL BYTE
REPT 254
GATE < >
ENDM
;0FEh号陷阱门描述符(字符串输出)
INTFE GATE <EchoBegin,EchoCodeSel,,8fH,>
GATE < >
IdtLen=$-idt
IdtSeg ends
;------------------------------------------------------
;主任务的局部描述符表段
SysLdtSeg segment para use16
syldt LABEL BYTE
;主任务数据段描述符及选择子
SysDataSel=$-syldt+TIL
SysData Desc <0ffffh,SysDataSeg,,92H,,>
主任务堆栈段的描述符及选择子
SysStack0Sel=$-syldt+TIL
SysStack Desc <SysStack0Len-1,SysStack0Seg,,93h,,>
;主任务TSS段作为数据段的描述符及选择子
ToSysTssSel=$-syldt+TIL
ToSysTss Desc <SysTssLen-1,SysTssSeg,,92h,,>
SysLdtNum=($-syldt)/(size Desc)
SysLdtLen=$
SysLdtSeg ends
;--------------------------------
;TaskA的局部描述符表段
TaskALdtSeg segment para use16
taldt LABEL BYTE
TaskACodeSel=$-taldt+TIL
TaskACode Desc <TaskACodeLen-1,TaskACodeSeg,,98h,,>
TaskADataSel=$-taldt+TIL
TaskAData Desc <0ffffh,TaskADataSeg,,92H,,>
TaskAStack0Sel=$-taldt+TIL
TaskAStack Desc <TaskAStack0Len-1,TaskAStack0Seg,,93h,,>
TaskALdtNum=($-taldt)/(size Desc)
TaskALdtLen=$
TaskALdtSeg ends
;-----------------------------------------
;TaskB的局部描述符表段
TaskBLdtSeg segment para use16
tbldt LABEL BYTE
TaskBCodeSel=$-tbldt+TIL
TaskBCode Desc <TaskBCodeLen-1,TaskBCodeSeg,,98h,,>
TaskBDataSel=$-tbldt+TIL
TaskBData Desc <0ffffh,TaskBDataSeg,,92H,,>
TaskBStack0Sel=$-tbldt+TIL
TaskBStack Desc <TaskBStack0Len-1,TaskBStack0Seg,,93h,,>
TaskBLdtNum=($-tbldt)/(size Desc)
TaskBLdtLen=$
TaskBLdtSeg ends
;-----------------------------------------
;0FEH号中断处理程序(显示程序)的代码段
EchoCodeSeg SEGMENT PARA USE16
ASSUME CS:EchoCodeSeg
;ds:si指向显示字符串,es:di指向显示缓冲区
EchoBegin: pushad
cld
mov ah,7
mov al,20h
mov cx,80
push di
rep stosw ;清所在显示行
pop di
Echo1: lodsb
or al,al
jz Echo2
stosw ;显示指定字符串
jmp Echo1
Echo2: popad
iretd
EchoCodeLen=$
EchoCodeSeg ENDS
;---------------------------------------------------------
;TaskA的TSS段
TaskATssSeg segment para use16
DD 0 ; trlink。
DD ? ; esp0。
DW ?,0 ; ss0。
DD ? ; esp1。
DW ?,0 ; ss1。
DD ? ; esp2。
DW ?,0 ; ss2。
DD 0 ; cr3。
DW taska,0 ; eip。 *入口地址
DD 0 ; psw。
DD 0 ; eax。
DD 0 ; ecx。
DD 0 ; edx。
DD 0 ; ebx。
DW TaskAStack0Len,0 ; esp。
DD 0 ; ebp。
DD 0 ; esi。
DD 0 ; edi。
DW NormalSel,0 ; es。
DW TaskACodeSel,0 ; cs。
DW TaskAStack0Sel,0 ; ss。
DW NormalSel,0 ; ds。
DW NormalSel,0 ; fs。
DW NormalSel,0 ; gs。
DW TaskALdtSel,0 ; ldt。
DW 0
DW $+2 ;指向I/0许可位图
DB 0FFH ;I/O许可位图结束标志
TaskATssLen=$
TaskATssSeg ends
;-------------------------------------------------------
;TaskA的堆栈段
TaskAStack0Seg SEGMENT PARA USE16 ;0级堆栈
TaskAStack0Len=1024
DB TaskAStack0Len DUP(0)
TaskAStack0Seg ENDS
;----------------
;TaskA的数据段
TaskADataSeg segment para use16
hiapm db ' Now it has entered TaskA! ',0
TaskADataSeg ends
;------------------
;TaskA的代码段
TaskACodeSeg segment para use16
assume cs:TaskACodeSeg,ds:TaskADataSeg
taska:
pushad
push ds
push es
push fs
push gs
mov ax,VideoSel
mov es,ax
mov ax,TaskADataSel
mov ds,ax
lea si,hiapm ;进入TaskA
mov di,160*7
INT 0FEh
mov al,0ffh
mov dx,0c400h
out dx,al
mov ah,01
mov cx,0008h
agn1: mov dx,0c410h
mov al,ah
out dx,al ;红行亮
push cx
mov cx,00fffh
d5: call delay1
loop d5
pop cx
shl ah,01
loop agn1
mov dx,0c40bh
mov al,89h
out dx,al
mov dx,0c40ah
in al,dx
test al,08h
jne returna ;K3=1返回SysCodeSeg
jmp taska
returna: pop gs
pop fs
pop es
pop ds
popad
JUMP16 SysTssSel,0
jmp taska
delay1 proc ;延迟
push cx
mov cx,0ffffh
ccc: loop ccc
pop cx
ret
delay1 endp
TaskACodeLen=$
TaskACodeSeg ends
;-----------------------------------------------------------
;TaskB的TSS段
TaskBTssSeg segment para use16
DD 0 ; trlink。
DD ? ; esp0。
DW ?,0 ; ss0。
DD ? ; esp1。
DW ?,0 ; ss1。
DD ? ; esp2。
DW ?,0 ; ss2。
DD 0 ; cr3。
DW taskb,0 ; eip。 *入口地址
DD 0 ; psw。
DD 0 ; eax。
DD 0 ; ecx。
DD 0 ; edx。
DD 0 ; ebx。
DW TaskBStack0Len,0 ; esp。
DD 0 ; ebp。
DD 0 ; esi。
DD 0 ; edi。
DW NormalSel,0 ; es。
DW TaskBCodeSel,0 ; cs。
DW TaskBStack0Sel,0 ; ss。
DW NormalSel,0 ; ds。
DW NormalSel,0 ; fs。
DW NormalSel,0 ; gs。
DW TaskBLdtSel,0 ; ldt。
DW 0
DW $+2 ;指向I/0许可位图
DB 0FFH ;I/O许可位图结束标志
TaskBTssLen=$
TaskBTssSeg ends
;-------------------------------------------------------
;TaskB的堆栈段
TaskBStack0Seg SEGMENT PARA USE16 ;0级堆栈
TaskBStack0Len=1024
DB TaskBStack0Len DUP(0)
TaskBStack0Seg ENDS
;----------------
;TaskB的数据段
TaskBDataSeg segment para use16
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh ;段码
buffer1 db 0,0 ;存放要显示的十位和个位
bz dw ? ;位码
hibpm db ' Now it has entered TaskB! ',0
TaskBDataSeg ends
;------------------------
;TaskB的代码段
TaskBCodeSeg segment para use16
assume cs:TaskBCodeSeg,ds:TaskBDataSeg
taskb: pushad
push ds
push es
push fs
push gs
mov ax,VideoSel
mov es,ax
mov ax,TaskBDataSel
mov ds,ax
lea si,hibpm ;进入TaskA
mov di,160*9
INT 0FEh
mov dx,0c40bh ;设置8255控制字
mov al,89h
out dx,al
dispnum:
mov di,offset buffer1 ;设di为显示缓冲区
loop1: mov cx,0300h ;循环次数
loop2: mov bh,02
lll: mov byte ptr bz,bh
push di
dec di
add di, bz
mov bl,[di] ;bl为要显示的数
pop di
mov bh,0
mov si,offset led ;置led数码表偏移地址为SI
add si,bx ;求出对应的led数码
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -