由于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
;-----------------------------