宏汇编显示中文字符

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

posted @ 2020-05-23 14:09  为红颜  阅读(157)  评论(0编辑  收藏