📄 98_hzk_gb2312_v1.0.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 + -