宏汇编显示中文字符
由于emum8088CPU支持ASCII字符集,不支持Unicode字符集,需要我们用点阵的形式显示汉字。
首先需要获得汉字的点阵表示形式,即16*16的表示,32个字节。
汉字在Unicode字符集中,由两个字节表示,前一个表示区号,后一个表示偏移地址。
字体库 放在了D盘目录下面:
#include <stdio.h> int main(void) { FILE* fphzk = NULL; errno_t err; int i, j, k, offset; int flag; unsigned char buffer[32]; unsigned char word[3] = "我"; unsigned char key[8] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; //fphzk = fopen("D:/hzk16k", "rb"); err = fopen_s(&fphzk, "D:/hzk16k", "rb" ); //楷体显示的字符 if (fphzk == NULL) { fprintf(stderr, "error hzk16\n"); return 1; } offset = (94 * (unsigned int)(word[0] - 0xa0 - 1) + (word[1] - 0xa0 - 1)) * 32; fseek(fphzk, offset, SEEK_SET); fread(buffer, 1, 32, fphzk); for (k = 0; k < 32; k++) { printf("%02X ", buffer[k]); } for (k = 0; k < 16; k++) { for (j = 0; j < 2; j++) { for (i = 0; i < 8; i++) { flag = buffer[k * 2 + j] & key[i]; printf("%s", flag ? "●" : "○"); } } printf("\n"); } fclose(fphzk); fphzk = NULL; return 0; }
如上图,获得了汉字 “我”的点阵表达形式。
”我的计算机工作正常“ 点阵表示:
WORD1 DB 01H,00H,01H,00H,01H,20H,05H,10H,19H,00H,09H,70H,0FH,80H,38H,90H,0AH,0A0H,0CH,40H,38H,0C0H,0CBH,24H,18H,14H,08H,0CH,00H,04H,00H,00H
WORD2 DB 00H,00H,00H,20H,08H,20H,08H,40H,10H,58H,2CH,0E8H,75H,08H,46H,88H,74H,48H,44H,48H,44H,08H,3CH,08H,24H,28H,00H,10H,00H,00H,00H,00h
WORD3 DB 00H,40H,10H,40H,08H,40H,00H,40H,00H,40H,30H,7CH,0D3H,0C0H,10H,40H,10H,40H,14H,40H,18H,40H,10H,40H,00H,40H,00H,40H,00H,40H,00H,00H
word4 db 08H,58H,0FH,60H,08H,90H,15H,00H,23H,0C0H,04H,40H,07H,40H,04H,40H,07H,0C0H,04H,7EH,7FH,0C0H,04H,40H,04H,40H,08H,40H,10H,40H,00H,00H
word5 db 10H,00H,10H,00H,10H,00H,10H,70H,1CH,90H,70H,0A0H,10H,0A0H,18H,0A0H,34H,0A0H,51H,22H,91H,22H,12H,1EH,14H,00H,10H,00H,00H,00H,00H,00H
word6 db 00H,00H,00H,00H,00H,00H,00H,0E0H,0FH,00H,01H,00H,01H,00H,01H,00H,01H,00H,01H,00H,01H,0FCH,7EH,00H,00H,00H,00H,00H,00H,00H,00H,00H
word7 db 00H,40H,08H,40H,08H,80H,08H,9CH,11H,0E0H,31H,40H,52H,40H,94H,78H,10H,40H,10H,40H,10H,78H,10H,40H,10H,40H,00H,40H,00H,40H,00H,00H
word8 db 00H,00H,00H,00H,00H,0F0H,0FH,00H,01H,00H,01H,00H,09H,30H,09H,0C0H,09H,00H,09H,00H,09H,00H,09H,0FCH,0FEH,00H,00H,00H,00H,00H,00H,00H
word9 db 01H,20H,09H,40H,05H,00H,0FH,0F8H,70H,08H,4FH,0D0H,48H,80H,07H,00H,01H,0E0H,0FH,20H,09H,20H,09H,60H,09H,20H,01H,00H,01H,00H,00H,00H
接下里就是那些汇编程序:
DATAS SEGMENT ;字模数据,可用字模生成程序生成,替换掉此处即可,此处使用的是16*16的黑体字模,32byte/字 TW DB 01H,00H,01H,00H,01H,20H,05H,10H,19H,00H,09H,70H,0FH,80H,38H,90H,0AH,0A0H,0CH,40H,38H,0C0H,0CBH,24H,18H,14H,08H,0CH,00H,04H,00H,00H DB 00H,00H,00H,20H,08H,20H,08H,40H,10H,58H,2CH,0E8H,75H,08H,46H,88H,74H,48H,44H,48H,44H,08H,3CH,08H,24H,28H,00H,10H,00H,00H,00H,00h DB 00H,40H,10H,40H,08H,40H,00H,40H,00H,40H,30H,7CH,0D3H,0C0H,10H,40H,10H,40H,14H,40H,18H,40H,10H,40H,00H,40H,00H,40H,00H,40H,00H,00H db 08H,58H,0FH,60H,08H,90H,15H,00H,23H,0C0H,04H,40H,07H,40H,04H,40H,07H,0C0H,04H,7EH,7FH,0C0H,04H,40H,04H,40H,08H,40H,10H,40H,00H,00H db 10H,00H,10H,00H,10H,00H,10H,70H,1CH,90H,70H,0A0H,10H,0A0H,18H,0A0H,34H,0A0H,51H,22H,91H,22H,12H,1EH,14H,00H,10H,00H,00H,00H,00H,00H db 00H,00H,00H,00H,00H,00H,00H,0E0H,0FH,00H,01H,00H,01H,00H,01H,00H,01H,00H,01H,00H,01H,0FCH,7EH,00H,00H,00H,00H,00H,00H,00H,00H,00H db 00H,40H,08H,40H,08H,80H,08H,9CH,11H,0E0H,31H,40H,52H,40H,94H,78H,10H,40H,10H,40H,10H,78H,10H,40H,10H,40H,00H,40H,00H,40H,00H,00H db 00H,00H,00H,00H,00H,0F0H,0FH,00H,01H,00H,01H,00H,09H,30H,09H,0C0H,09H,00H,09H,00H,09H,00H,09H,0FCH,0FEH,00H,00H,00H,00H,00H,00H,00H db 01H,20H,09H,40H,05H,00H,0FH,0F8H,70H,08H,4FH,0D0H,48H,80H,07H,00H,01H,0E0H,0FH,20H,09H,20H,09H,60H,09H,20H,01H,00H,01H,00H,00H,00H DATAS ENDS STACKS SEGMENT DW 10 DUP(?) STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ;设置数据段寄存器 MOV AX,STACKS MOV SS,AX ;设置栈段寄存器 MOV SP,20 ;设置栈顶偏移地址 MOV AH,0FH INT 10H ;读当前显示方式至AX中 PUSH AX ;当前显示方式入栈 MOV AX,12H INT 10H ;设置显示方式为VGA彩色 MOV DI,(30 * 80 + 10) * 2 ;DI控制显示位置,640*480分辨率,可显示80*60字节,第i行汉字写入时DI为80*16*i~80*16*i+78,相邻汉字DI差2 CALL DISPLAY ;调用显示过程 MOV AH,01 INT 21H ;等待输入,暂停作用 POP AX ;AX出栈 MOV AH,00H INT 10H ;恢复原来显示方式 MOV AX,4C00H ;退出程序 INT 21H ;MOVSW指令将DS:SI中数据按字传送至ES:DI DISPLAY: ;输出 ‘我的计算机工作正常’-------------------- MOV AX,0A000H ;VGA写入起始段地址 MOV ES,AX ;设置传送目标段地址 CLD ;CLD指令使DF=0,正向传输字 MOV CX,9 ;连续的字数,此处“我的计算机工作正常”共9字 LEA SI,TW ;需写入汉字字模的首地址 DIS1: PUSH CX ;多重循环,CX入栈 PUSH SI PUSH DI MOV CX,16 DISWORD1: MOVSW ADD DI,78 ;转到下一行字模写入位置,一个汉字16*16,故需写16行 LOOP DISWORD1 POP DI POP SI POP CX ADD SI,32 ;读取下一个汉字的字模数据,由于一个汉字占用32byte,故加上32 ADD DI,2 ;开始写下一个汉字,默认写在上一个字右边 LOOP DIS1 RET ;-----------------------------