98_hzk_gb2312_v1.2_2005.1.20.asm

来自「汇编语言 参考书 包含作业与答案 从入门到精通 通俗易懂」· 汇编 代码 · 共 533 行 · 第 1/2 页

ASM
533
字号
;╔━┅━┅━┅━┅━┅━┅━┅━┅━━┅━┅━┅━┅━┅━┅━ ╗
;┃≡TYPEGB of HZK V1.0		-----powered by BlasterKai! ≡ ┃
;┃ - ¤╭⌒╮ ╭⌒╮                                          ┃
;┃ ╱◥██◣ ╭ ⌒                                           ┃
;┃ |田︱田田| ╰---------一切都精彩-------缘自Buaa!!        ┃
;┃︵﹏~︵﹏~︵﹏~︵﹏~︵﹏~︵                            ┃
;╚┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━┅━ ╝
;----------------------------------------------------------------
;                      ╭═══════════════╮
;                      ║     TYPEGB of HZK V1.0        ║
;        ╭══════┤    -powered by BlasterKai!    ├═════╮
;        ║            ║    	      --2004.10.31      ║           ║
;        ║            ╰═══════════════╯            ║
;       ║              ★ 汇编语言 (研究型大作业)★              ║
;       ║      |---------------------------------------------|     ║
;       ║ 3. 在VGA 12h模式下,在屏幕上显示汉字,字库源于UCDOS中的  ║
;        ║CCLIB或24X24字库。并让其支持字型转置。                    ║ 
;        ║                                                          ║
;        ║                                                          ║
;        ║                 算法简述                                 ║
;        ║            -----------------------                       ║
;        ║   ;调用 21号中断的a号功能,读入文件名及路径信息           ║
;        ║   ;再读入字型转置方式,默认为正常显示                    ║
;        ║   ;打开所读文件                                          ║
;      ║   ;读当前光标的位置                                      ║
;        ║   ;从待显示的文件中读取两个字节	                     ║
;        ║   ;测试文件是否结束当为0时,表示EOF                      ║
;        ║   ;计算在CCLIB中的偏移量   qh=c1-0xa0 wh=c2-0xa0       ║
;        ║   ;从CCLIB中读入16*16的点阵,32个字节                    ║
;        ║   ;依据字型转置方式来输出汉字                            ║
;        ║   ;屏幕满时开始上滚一行                                  ║
;        ║   ;用来显示一些非汉字字符,即ASCII字符                   ║
;        ║   ;错误处理程序                                          ║
;        ║   ;显示汉字子程序                                        ║
;        ║                                                          ║
;        ║                                                          ║
;        ║    ╭──────────────────────╮      ║
;        ╰══┤     ★★★       Made in Buaa      ★★★   ├══╯
;              ╰──────────────────────╯     
;━┅━┅━┅━┅━┅━┅━┅━┅━━┅━┅━┅━┅━┅━┅━┅━
;TypeGB of HZK v1.1	---2004.11.12		
;	update:	1。汉字显示过程得到精简。	2。真正实现30行一滚屏,并有滚屏提示信息
;	2005.1.20	1.可以用直接写屏的方法,可以得到更高的显示速度。
;			2.程序的大部分集中在一个主程序中,应该多用子程序。
;				可读性比较差,有待改进。
;			3.现在感觉实现点阵汉字显示并不是很复杂,而当时却是花了很多时间。但还是有收获的。
;----------------------------------------------------------------
	.MODEL SMALL
	.STACK 100H
	.DATA
				inputfilename	db	'Please input the file path and name : ','$'
				maxlen		db	32
				actlen		db	?
				filename	db	32 DUP(?)
				inputmodel	db	'Please input the model(normal,left,right,iverse) : ','$'
				model		db	'n'
				file_cclib	db	'hzk16',0
				handle_cclib	dw	?				; CCLIB 文件句柄
				buffer_cclib 	db	32	DUP(?),'$'
				handle_read	dw	?				;读取文件句柄
				buffer_read	dw	?
				linex		dw	?
				liney		dw	?
				msg_screenfull	db	'Press any key to continue ...','$'
				msg_goonscroll	db	'                             ','$'
				scrollnum	db	27
				msg_open_cclib_error	db	'Could not find HZK16!','$'
				msg_open_read_error	db	'There is no such file!','$'
				msg_read_cclib_error	db	'HZK16 read wrong!','$'
				msg_read_read_error	db	'File read wrong!','$'
				
	.CODE
;;*****************************************************************************************************************
MAIN	PROC	FAR
		MOV	AX,@DATA
		MOV	DS,AX

		CALL	GET_FILE_NAME
		
;;*************************************************************************
		LEA	DX,FILENAME		;打开所读文件
		MOV	AL,0
		MOV 	AH,3DH
		INT 	21H
		JC	OPEN_READ_ERROR
		MOV	HANDLE_READ,AX		;保存文件句柄
		
		LEA	 DX,FILE_CCLIB		;打开CCLIB
		MOV	 AL,0
		MOV 	AH,3DH
		INT 	21H
		JC	OPEN_CCLIB_ERROR
		MOV 	HANDLE_CCLIB,AX		;保存字库句柄		

;;*************************************************************************
		MOV	BH,0H		;读当前光标的位置
		MOV	AH,3H
		INT	10H
		
		MOV	AX,16		;保存光标位置,按象素点的行列保存
		MUL	DH
		;MOV	LINEX,0		
		MOV	LINEX,AX		
		MOV	LINEY,0
			
		MOV	AL,12H		;设置显示模式为640*480,16色模式
		MOV	AH,0H
		INT	10H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   读取并显示一个汉字,并循环
GETWORD_FILE:			;从待显示的文件中读取两个字节			
		MOV	BX,HANDLE_READ		;INT  21H   42号功能移动文件指针
		MOV	CX,0
		MOV	DX,0H
		MOV	AL,1		;移动方式,从当前位置开始移动
		MOV 	AH,42H
		INT 	21H
;上面的好像有点多余		
		MOV 	BX,HANDLE_READ		;读文件,INT  21H,3F号功能
		MOV 	CX,1			;只读取一个字节
		LEA 	DX,BUFFER_READ		;保存位置
		MOV 	AH,3FH
		INT 	21H
		JC	READ_READ_ERROR		
	;;;;;;;;;;;;;;;	
		TEST	AX,0FFFFH		;测试文件是否结束,AX中为实际写入的字节数,当为0时,表示EOF
		JZ	DONE
	;;;;;;;;;;;;;;;
		MOV 	AX,BUFFER_READ		;判断读到的字符是否为ACSII字符,是则用INT  21H号中断显示
		CMP	AL,0A0H
		JB	PRINT_ANSI_CHAR
	;;;;;;;;;;;;;;;;		
		MOV	BX,HANDLE_READ		;若为汉字,则再读取一个字节,并保存之后
		MOV 	CX,1
		LEA	DX,BUFFER_READ+1
		MOV 	AH,3FH
		INT 	21H
		JC	READ_READ_ERROR
;***************************************************************
COUNT_OFFSET:					;计算在CCLIB中的偏移量   QH=C1-0XA0 WH=C2-0XA0 
	;;;;;;;;;;;;;;;;;;;;;;			;该汉字在字库中离起点的位置是: OFFSET=(94*(QH-1)+(WH-1))*32L
		MOV 	BX,BUFFER_READ
		SUB	BH,0A0H
		SUB	 BL,0A0H
		DEC 	BH
		DEC 	BL
		
		XOR 	AX,AX
		MOV	AL,BL
		MOV	CL,94					;此时不会溢出
		MUL	CL
		
		XOR 	CX,CX
		MOV	CL,BH
		ADD 	AX,CX
		MOV 	CX,32
		MUL 	CX
		;MOV BUFFER_READ,AX		;结果保存在DX+AX中,可再写入BUFFER_READ
;;****************************************************************	
READ_CCLIB:					;从CCLIB中读入16*16的点阵,32个字节,并保存在BUFFER_CCLIB中
		MOV	BX,HANDLE_CCLIB
		MOV	CX,DX			;COUNT_OFFSET计算所得偏移量保存在DX:AX中,现在放入CX:DX中,42号功能
		MOV	DX,AX
		MOV	AL,0		;从文件头开始读取,与待显示的文件指针移动方式不同
		MOV 	AH,42H
		INT 	21H
		
		MOV	BX,HANDLE_CCLIB
		MOV 	CX,32		;32个字节
		LEA	DX,BUFFER_CCLIB
		MOV 	AH,3FH
		INT 	21H
		JC	READ_CCLIB_ERROR		
;;**************************************************************	;依据字型转置方式来输出汉字
		MOV	BH,MODEL
		MOV	BL,BH
		CMP	BL,'l'
		JZ	ISLEFT
		MOV	BL,BH
		CMP	BL,'r'
		JZ	ISRIGHT
		MOV	BL,BH
		CMP	BL,'i'
		JZ	ISREVERSE
		CALL	PRINT_NORMAL
		JMP	CHANGE
ISLEFT:	
		CALL	PRINT_LEFT
		JMP	CHANGE
ISRIGHT:
		CALL	PRINT_RIGHT
		JMP	CHANGE
ISREVERSE:
		CALL 	PRINT_REVERSE
		JMP	CHANGE

;;****************************************************************************
CHANGE:					;屏幕满时开始上滚一行
		CMP	LINEX,448
		JAE	RESET_X
		JMP	CHANGEROW	
RESET_X:
		INC	SCROLLNUM
		CMP	SCROLLNUM,28
		JE	FULLSCREEN
		JMP	GOONSCROLL
	;;;;;;;;;;;;;;;;;;			;换页功能
FULLSCREEN:			;可用来在最下端提示按键换页,实现
		MOV	DH,29
		MOV	DL,0
		MOV	AH,2
		INT	10H
		LEA	DX,MSG_SCREENFULL	;最下端换页信息		
		MOV	AH,9
		INT	21H
		
		MOV	AH,00H			;按键但不回显,并且上滚20行
		INT	16H			;用DOS 21--8号功能可能出现按一次键滚两屏的现象,用BIOS16号则不会有???
		MOV	SCROLLNUM,0
		
		MOV	DH,29			;删除换页提示信息
		MOV	DL,0
		MOV	AH,2
		INT	10H
		LEA	DX,MSG_GOONSCROLL		;
		MOV	AH,9
		INT	21H
;;;;;;;;;;;;;;	
GOONSCROLL:			;滚屏
		MOV	AL,1
		MOV	AH,6H
		XOR	CX,CX
		MOV	DH,28
		MOV	DL,80
		MOV	BH,0
		INT	10H
		
		SUB	LINEX,16	;恢复到上一行	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;换行
CHANGEROW:
		CMP	LINEY,616
		JAE	RESET_Y		;大于等于跳至换行
		ADD	LINEY,16
		MOV	DX,BUFFER_READ
		CMP	DL,0A0H		;由于输出为非汉字,只占用8个象素,所以要-8
		JB	NEEDSUB8
		JMP	NEXT
NEEDSUB8:
		SUB	LINEY,8
		JMP	NEXT
RESET_Y:
		MOV	LINEY,0H
		ADD	LINEX,16
;;************************************************************				;开始读第二个字
NEXT:
		JMP GETWORD_FILE	;LOOP	GETWORD_FILE	;为什么用LOOP提示超出NEAR的范围,如何解决?
;;********************************************************	;附加的一些处理程序段			
PRINT_ANSI_CHAR:		;用来显示一些非汉字字符,即ASCII字符
		MOV DX,BUFFER_READ
		CMP	DL,10		;手动输出换行符
		JZ	NEEDCHANGELINE
		JMP	GOGOGO
NEEDCHANGELINE:
		MOV	LINEY,624		;置Y轴的坐标大于边界,跳至上边会自动换行。  不用在此强制换行MOV LINEY,0并且不会产生换行多两个字符的BUG
		JMP	CHANGE		
GOGOGO:
		MOV	BL,16		;计算行列值,非象素值
		MOV	AX,LINEX

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?