📄 disp.asm
字号:
;FILENAME: DISP.ASM
.MODEL HUGE
.386P
;常量定义
FALSE EQU 0
TRUE EQU 1
TAB_KEY EQU 09H
CR_KEY EQU 0DH
LF_KEY EQU 0AH
FLAG_OF_FILE_END EQU 0FFH
INCLUDE 386SCD.ASM
INCLUDE MACRO.MAC
INCLUDE IDT.ASM
;--------------------------------------------------------------------------------------------------------------
;堆栈段
REAL_STACK_SEG SEGMENT STACK PARA USE16 'STACK'
;堆栈大小
REAL_STACK_LEN = 100H
DB REAL_STACK_LEN DUP(0)
REAL_STACK_SEG ENDS
;---------------------------------------------------------------------------------------------------------------
;数据段
REAL_DATA_SEG SEGMENT PARA USE16 'DATA'
FILE_NAME DB 'DISP.ASM',0
DB 30H DUP(0)
;文件句柄
FILE_HANDLE DW 0
;文件结束标志
FILE_OVER DW FALSE
;提示信息
OPEN_FILE_ERR_MSG DB 0DH,0AH,'OPEN FILE ERROR !$'
READ_FILE_ERR_MSG DB 0DH,0AH,'READ FILE ERROR !$'
REAL_BEGIN_MSG DB 0DH,0AH,'REAL MODE BEGIN !$'
PROMPT_1 DB 'PRESS ANY KEY TO CONTINUE !$'
PROMPT_2 DB 'PRESS ANY KEY TO QUIT THIS PROGRAM !$'
AUTHER_MESSAGE LABEL BYTE
LINE_1 DB '* --------------------------------------- *$'
LINE_2 DB '| |$'
LINE_3 DB '| DESIGNED BY: |$'
LINE_4 DB '| |$'
LINE_5 DB '| 08000118 DAI HUA |$'
LINE_6 DB '| 08000129 XU XIN |$'
LINE_7 DB '| 08000130 ZHAO TINGHAI |$'
LINE_8 DB '| |$'
LINE_9 DB '| THANK YOU FOR TESTING |$'
LINE_A DB '| |$'
LINE_B DB '* --------------------------------------- *$'
;保存实模式下GDTR,IDTR,SS,SP的内容
REAL_GDT DW 4 DUP(0)
REAL_IDT DW 4 DUP(0)
REAL_SS DW ?
REAL_SP DW ?
;实模式下的文件缓冲区
REAL_DATA_BUF DB 1024 DUP(?)
;每次读到的文件大小
DATA_BUF_SIZE DW 0
;文件总大小
DATA_BUF_SUM DD 0
;EDI的备份
SAVE_EDI DD 0
;保护模式下的GDTR和IDTR
VGDTR PDESC <GDT_LEN-1,>
VIDTR PDESC <IDT_LEN-1,>
REAL_DATA_SEG ENDS
;----------------------------------------------------------------------------------------------------------------------
;全局描述符表段
GDT_SEG SEGMENT PARA USE16
GDT LABEL BYTE
NULL_DESC DESCRIPTOR <>
NORMAL DESCRIPTOR <0FFFFH,,,ATDW,,>
NORMAL_SEL = NORMAL-GDT
GDT_INIT_BEGIN LABEL BYTE
REAL_STACK_DESC DESCRIPTOR <REAL_STACK_LEN-1,REAL_STACK_SEG,,ATDWA,,>
REAL_STACK_SEL = REAL_STACK_DESC-GDT
REAL_DATA_DESC DESCRIPTOR <0FFFFH,REAL_DATA_SEG,,ATDWA,,>
REAL_DATA_SEL = REAL_DATA_DESC-GDT
REAL_CODE_DESC DESCRIPTOR <0FFFFH,REAL_CODE_SEG,,ATCER,,>
REAL_CODE_SEL = REAL_CODE_DESC-GDT
IDT_STACK_DESC DESCRIPTOR <IDT_STACK_LEN-1,IDT_STACK_SEG,,ATDW,,>
IDT_STACK_SEL = IDT_STACK_DESC-GDT
IDT_DATA_DESC DESCRIPTOR <0FFFFH,IDT_DATA_SEG,,ATDW,,>
IDT_DATA_SEL = IDT_DATA_DESC-GDT
IDT_CODE_DESC DESCRIPTOR <0FFFFH,IDT_CODE_SEG,,ATCER,,>
IDT_CODE_SEL = IDT_CODE_DESC-GDT
GDNUM = ($-GDT_INIT_BEGIN)/(SIZE DESCRIPTOR)
;
VRAM_DESC DESCRIPTOR <0FFFFH,08000H,0BH,ATDW,,>
VRAM_SEL = VRAM_DESC-GDT
DATA_BUF_DESC DESCRIPTOR <0FFFFH,,20H,ATDW,0FH,>
DATA_BUF_SEL = DATA_BUF_DESC-GDT
GDT_LEN = $-GDT
GDT_SEG ENDS
;---------------------------------------------------------------------------------------------------------------------------
;中断描述符表段
IDT_SEG SEGMENT PARA USE16
IDT LABEL BYTE
IDT_0H GATE <>
IDT_1H DW 128 DUP(0) ;20H * 4 = 80H (80H = 128D)
;自定义的DOS INT21H中断描述符
IDT_DOS_21H GATE <(OFFSET INT21H),IDT_CODE_SEL,,AT386IGATE,>
IDT_LEN = $-IDT
IDT_SEG ENDS
;--------------------------------------------------------------------------------------------------------------------------
;代码段
REAL_CODE_SEG SEGMENT PARA USE16
ASSUME CS:REAL_CODE_SEG,DS:REAL_DATA_SEG,SS:REAL_STACK_SEG
;程序入口点
MODE_T_START:
MOV AX,REAL_DATA_SEG
MOV ES,AX
MOV SI,80H
MOV CL,DS:[SI]
CMP CL,0
;显示文件
JZ DISP_DEFAULT_FILE
DEL_SPACE: INC SI
MOV AL,DS:[SI]
CMP AL,20H
JZ DEL_SPACE ;LET SI POINT TO THE FIRST CHARACTER
;WHITCH IS NOT A SPACE
MOV DI,0H
CLD
;得到文件名
GET_FILE_NAME:
MOV AL,DS:[SI]
CMP AL,0DH
JE FORM_ASCIIZS
MOVSB
JMP GET_FILE_NAME
FORM_ASCIIZS: INC DI
MOV ES:[DI],0
DISP_DEFAULT_FILE:
CLI
MOV AX,REAL_STACK_SEG
MOV SS,AX
MOV AX,REAL_DATA_SEG
MOV DS,AX
MOV REAL_SS,SS
MOV SP,REAL_STACK_LEN
MOV REAL_SP,SP
STI
MOV AX,REAL_DATA_SEG
MOV DS,AX
;打开第20根地址线
CALL OPEN_A20
;保存实模式下的GDTR和IDTR
SGDT FWORD PTR REAL_GDT
SIDT FWORD PTR REAL_IDT
;初始化GDT和IDT
CALL INIT_GDT
CALL INIT_IDT
;调用文件读取宏(文件->实模式下缓冲区->保护模式下缓冲区)
READFILE FILE_NAME
;将扩展内存中的数据写到显示内存
MOVE_DATA_TO_VRAM:
MOV AX,REAL_DATA_SEL
MOV FS,AX
MOV AX,DATA_BUF_SEL
MOV GS,AX
MOV AX,VRAM_SEL
MOV ES,AX
MOV ECX,DATA_BUF_SUM
;置文件结束符
MOV GS:[ECX],FLAG_OF_FILE_END
MOV EDI,0
;调用清屏宏
CLEAR_SCREEN
REPEAT_MOVE: MOV AH,07H
MOV AL,GS:[EDI]
;读到文件结束标志
IF_FILE_END:
CMP AL,FLAG_OF_FILE_END
JE FILE_DISP_END ;文件显示结束
;读到TAB键
IF_TAB_KEY: CMP AL,09H
JNE IF_CR_KEY
MOV CX,8
;TAB键处理部分(加空格)
FILL_TO_8_BLANK: MOV AX,0720H
MOV ES:[EBX],AX
MOV EAX,EBX
INC EBX
INC EBX
XOR EDX,EDX
PUSH EBX
MOV EBX,16
DIV EBX
POP EBX
CMP EDX,14
JNZ FILL_TO_8_BLANK
INC EDI
JMP REPEAT_MOVE
;读到回车键
IF_CR_KEY: CMP AL,CR_KEY
JNZ GO_ON_DISPLAYING
INC EDI
INC EDI
;回车键处理部分(加空格至行尾)
FILL_BLANK_TO_LINE_END: MOV AX,0720H
MOV ES:[EBX],AX
MOV EAX,EBX
INC EBX
INC EBX
XOR EDX,EDX
PUSH EBX
MOV EBX, 160
DIV EBX
POP EBX
CMP EDX,158
JNZ FILL_BLANK_TO_LINE_END
;判断是否写满一屏
CMP EAX,23
;若写满一屏,跳至显示下一屏的功能块
JZ SHOW_NEXT_PAGE
;若未写满一屏,则继续显示
JMP REPEAT_MOVE
GO_ON_DISPLAYING:
MOV ES:[EBX],AX
INC EBX
INC EBX
INC EDI
JMP REPEAT_MOVE
SHOW_NEXT_PAGE:
PUSH ECX
MOV AH,09H
MOV CX,1820H
LEA DX,PROMPT_1
INT 21H
;在保护模式下调用自己写的中断INT21H-09H号功能,显示按"任意键继续"的提示信息
;响铃并等待键盘输入
PRP_BELL
CLEAR_SCREEN
POP ECX
MOV EBX,0
JMP REPEAT_MOVE
;文件显示结束
FILE_DISP_END:
LEA DX,PROMPT_2
MOV CX,1820H
MOV AH,9
INT 21H
PRP_BELL
CLEAR_SCREEN
;显示版权提示信息
MOV AH,09H
START_OFFSET = 0620H
IRP LINE_NUM,<1,2,3,4,5,6,7,8,9,A,B>
MOV CX,START_OFFSET
LEA DX,LINE_&LINE_NUM
INT 21H
START_OFFSET = START_OFFSET + 0100H
ENDM
;全部操作结束,转实模式
;置NORMAL描述符选择子
MOV AX,NORMAL_SEL
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
CLI
MOV EAX,CR0
AND EAX,0FFFFFFFEH
MOV CR0,EAX
JUMP16 REAL_CODE_SEG,REAL_MODE
REAL_MODE:
;恢复已保存的实模式下相应寄存器内容
MOV AX,REAL_DATA_SEG
MOV DS,AX
MOV SS,DS:REAL_SS
MOV SP,DS:REAL_SP
;关闭第20根地址线
CALL CLOSE_A20
LGDT FWORD PTR REAL_GDT
LIDT FWORD PTR DS:REAL_IDT
STI
;退出程序
MOV AX,4C00H
INT 21H
;-------------------------------------------------------------------------------
;初始化全局描述符表并得到保护模式下的VGDTR的内容
INIT_GDT PROC NEAR
PUSH DS
MOV AX,GDT_SEG
MOV DS,AX
MOV CX,GDNUM
MOV SI,OFFSET GDT_INIT_BEGIN
INITG: MOV AX,[SI].BASEL
MOVZX EAX,AX
SHL EAX,4
SHLD EDX,EAX,16
MOV [SI].BASEL,AX
MOV [SI].BASEM,DL
MOV [SI].BASEH,DH
ADD SI,SIZE DESCRIPTOR
LOOP INITG
POP DS
;
MOV BX,10H
MOV AX,GDT_SEG
MUL BX
MOV WORD PTR VGDTR.BASE,AX
MOV WORD PTR VGDTR.BASE+2,DX
RET
INIT_GDT ENDP
;--------------------------------------------------------------------------------------------
;得到保护模式下的VIDTR的内容
INIT_IDT PROC NEAR
MOV BX,10H
MOV AX,IDT_SEG
MUL BX
MOV WORD PTR VIDTR.BASE,AX
MOV WORD PTR VIDTR.BASE+2,DX
RET
INIT_IDT ENDP
;----------------------------------------------------------
;打开第20根地址线的子程序
OPEN_A20 PROC FAR
PUSH AX
IN AL,92H
OR AL,2
OUT 92H,AL
POP AX
RETF
OPEN_A20 ENDP
;----------------------------------------------------------
;关闭第20根地址线的子程序
CLOSE_A20 PROC FAR
PUSH AX
IN AL,92H
AND AL,0FDH
OUT 92H,AL
POP AX
RETF
CLOSE_A20 ENDP
;----------------------------------------------------------
;响铃并等待键盘输入的子程序
_BELL PROC FAR
PUSH AX
PUSH DX
MOV DL,7
MOV AH,2
INT 21H
MOV AH,07H
INT 21H
POP DX
POP AX
RETF
_BELL ENDP
REAL_CODE_SEG ENDS
END MODE_T_START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -