⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 98_hzk_gb2312_v1.0.asm

📁 汇编语言 参考书 包含作业与答案 从入门到精通 通俗易懂
💻 ASM
字号:
;╔━┅━┅━┅━┅━┅━┅━┅━┅━━┅━┅━┅━┅━┅━┅━╗
;┃≡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      ★★★    ├══╯
;              ╰───────────────────────╯     
;━┅━┅━┅━┅━┅━┅━┅━┅━━┅━┅━┅━┅━┅━┅━┅━
;----------------------------------------------------------------
		.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(?),'$'
				;file_read	db	'test.txt',0
				handle_read	dw	?				;读取文件句柄
				buffer_read	dw	?
				char_offset	db	4	DUP(?),'$'
				print_buffer	db	3	DUP(?),'  $'
				linex		dw	?
				liney		dw	?
				;msg_screenfull	db	'---------more-------','$'
				;scrollnum	db	?
				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
;;;;;;;;;;;;;;;;;;;;;;;;;;;		
		lea	dx,inputfilename				;调用 21号中断的a号功能,读入文件名及路径信息
		mov	ah,9
		INT	21h
		mov	dx,offset maxlen
		mov	ah,0ah
		INT	21h
		mov	si,offset filename
		mov	bl,actlen
		xor	bh,bh
		add	si,bx
		xor	bx,bx
		mov	[si],bx

		mov	dl,10			;输出一个回车符
		mov	ah,2
		INT	21h

		lea	dx,inputmodel					;再读入字型转置方式,默认为正常显示
		mov	ah,9
		INT	21h
		mov	ah,1
		INT	21h
		mov	model,al

		mov	dl,10			;输出一个回车符
		mov	ah,2
		INT	21h

;;*************************************************************************
open_file:

		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,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,464
	jae	reset_x
	jmp	changerow	
reset_x:
	;mov	dh,29
	;mov	dl,0
	;mov	ah,2
	;INT	10h
	;lea	dx,msg_screenfull		;可用来在最下端提示按键换页,未实现
	;mov	ah,9
	;INT	21h
	mov	ah,08			;按键但不回显,并且上滚20行
	INT	21h

	mov	al,10
	mov	ah,6h
	xor	cx,cx
	mov	dh,29
	mov	dl,80
	mov	bh,0
	INT	10h
	
	sub	linex,160	;恢复到上一行	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;换行
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
	cmp	ax,0
	jz	cannotdiv_x
	div	bl
	mov	dh,al
	jmp	get_y
cannotdiv_x:
	mov	dh,0

get_y:
	mov	ax,liney
	cmp	ax,0
	jz	cannotdiv_y
	mov	bl,8
	div	bl
	mov	dl,al
	jmp	positionisok
cannotdiv_y:
	mov	dl,0
	
positionisok:
	mov	ah,2h
	INT	10h

		mov dx,buffer_read
		mov ah,2h
		INT 21h
	
		jmp	change
;;****************************************************************  ;错误处理程序		
open_cclib_error:	lea	dx,msg_open_cclib_error
			jmp	msgshow
open_read_error:	lea	dx,msg_open_read_error
			jmp	msgshow
read_cclib_error:	lea	dx,msg_read_cclib_error
			jmp	msgshow
read_read_error:	lea	dx,msg_read_read_error
msgshow:
		mov ah,9h
		INT 21h
		jmp donewithoutclose
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;		
done:

	mov     ax,3e00h
	mov     bx,handle_cclib
	int     21h
	mov     ax,3e00h
	mov     bx,handle_read
	int     21h

	mov     ax,0800h
	int     21h
	;mov     ax,0003h		;在WINDOWS下不用此结束后会产生花屏???
	;int     10h
donewithoutclose:
		mov ah,4ch
		INT 21h


;;****************************************************************  ;正常显示汉字子程序
print_normal	proc	near
					
	mov	dx,linex		;设置X轴的坐标
	mov	cx,16			;每个汉字显示为16行
	lea	si,buffer_cclib
writex:
	push	cx
	mov	bx,liney		;设置Y轴的坐标
	;;;;;;;;;;
	mov	cx,8			;一个汉字为16列,此为第一个字节显示
	mov	ah,[si]
writey:
	shl	ah,1
	jc	iszero
	xor	al,al
	jmp	goon
iszero:
	mov	al,7h
goon:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	bx
	loop	writey
	;;;;;;;;;;;;;	

inc	si
	mov	cx,8
	mov	ah,[si]
writey2:
	shl	ah,1
	jc	iszero2
	xor	al,al
	jmp	goon2
iszero2:
	mov	al,7h
goon2:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	bx		;bx代替CX来计算列地址,右移一列
	loop	writey2
;;;;;;;;;;;;;;;;

	pop	cx
	inc	dx		;DX为行地址,下移一行
	inc	si
	loop	writex		;开始行循环

	RET
print_normal	ENDP
;;****************************************************************  ;左转90度显示汉字子程序
print_left	proc	near
					
	mov	bx,liney		;设置X轴的坐标
	;add	bx,16
	mov	cx,16			;每个汉字显示为16行
	lea	si,buffer_cclib
writex:
	push	cx
	mov	dx,linex		;设置Y轴的坐标
	add	dx,16
	;;;;;;;;;;
	mov	cx,8			;一个汉字为16列,此为第一个字节显示
	mov	ah,[si]
writey:
	shl	ah,1
	jc	iszero
	xor	al,al
	jmp	goon
iszero:
	mov	al,7h
goon:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	dec	dx
	loop	writey
	;;;;;;;;;;;;;	

inc	si
	mov	cx,8
	mov	ah,[si]
writey2:
	shl	ah,1
	jc	iszero2
	xor	al,al
	jmp	goon2
iszero2:
	mov	al,7h
goon2:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	dec	dx		;bx代替CX来计算列地址,右移一列
	loop	writey2
;;;;;;;;;;;;;;;;

	pop	cx
	inc	bx		;DX为行地址,下移一行
	inc	si
	loop	writex		;开始行循环

	RET
print_left	ENDP
;;****************************************************************  ;右转90度显示汉字子程序
print_right	proc	near
					
	mov	bx,liney		;设置X轴的坐标
	add	bx,16
	mov	cx,16			;每个汉字显示为16行
	lea	si,buffer_cclib
writex:
	push	cx
	mov	dx,linex		;设置Y轴的坐标
	;add	dx,16
	;;;;;;;;;;
	mov	cx,8			;一个汉字为16列,此为第一个字节显示
	mov	ah,[si]
writey:
	shl	ah,1
	jc	iszero
	xor	al,al
	jmp	goon
iszero:
	mov	al,7h
goon:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	dx
	loop	writey
	;;;;;;;;;;;;;	

inc	si
	mov	cx,8
	mov	ah,[si]
writey2:
	shl	ah,1
	jc	iszero2
	xor	al,al
	jmp	goon2
iszero2:
	mov	al,7h
goon2:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	dx		;bx代替CX来计算列地址,右移一列
	loop	writey2
;;;;;;;;;;;;;;;;

	pop	cx
	dec	bx		;DX为行地址,下移一行
	inc	si
	loop	writex		;开始行循环

	RET
print_right	ENDP
;;****************************************************************  ;倒转显示汉字子程序
print_reverse	proc	near
					
	mov	dx,linex		;设置X轴的坐标
	add	dx,16
	mov	cx,16			;每个汉字显示为16行
	lea	si,buffer_cclib
writex:
	push	cx
	mov	bx,liney		;设置Y轴的坐标
	;;;;;;;;;;
	mov	cx,8			;一个汉字为16列,此为第一个字节显示
	mov	ah,[si]
writey:
	shl	ah,1
	jc	iszero
	xor	al,al
	jmp	goon
iszero:
	mov	al,7h
goon:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	bx
	loop	writey
	;;;;;;;;;;;;;	

inc	si
	mov	cx,8
	mov	ah,[si]
writey2:
	shl	ah,1
	jc	iszero2
	xor	al,al
	jmp	goon2
iszero2:
	mov	al,7h
goon2:
	push	ax
	mov	ah,0ch
	xchg	cx,bx
	push	bx
	xor	bx,bx
	INT	10h
	pop	bx
	xchg	cx,bx	
	pop	ax
	
	inc	bx		;bx代替CX来计算列地址,右移一列
	loop	writey2
;;;;;;;;;;;;;;;;
	pop	cx
	dec	dx		;DX为行地址,下移一行
	inc	si
	loop	writex		;开始行循环

	RET
print_reverse	ENDP
;;********************************************************************************************
main	ENDP
END	main					

⌨️ 快捷键说明

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