返回
12.1 多模块编程方法
12.2 图形处理应用
12.3 操作系统接口应用
12.4 C语言与汇编语言混合编程
12.5 综合应用程序举例 —汉字显示技术
一个有实用价值的 C语言应用程序往往较大,需
要划分成不同的模块,分配给不同的程序员去完成。
因此,在实用软件的开发中,往往需要采用多模块编
程技术。
12.1 多模块编程方法
使用多模块编程技术的处理过程大致如下:
1,首先 将一个大的源程序根据其功能合理地划分成
若干个小的源程序, 每个小源程序均以程序文件 (.C)
的形式保存在磁盘上 。 并建立一个包括各个源程序
模块的文件名的工程文件 (.prj)。
12.1.1 程序模块组织
下一页
第 12章 C语言综合应用程序举例
上一页
2,然后 用编译器进行编译,将工程文件中指定的
多个源程序文件进行编译,生成多个目标文件和一
个可执行文件。注意,在分模块单独编译处理的各
个程序模块中,必须有且只有一个主函数 main( ) 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.1.2 模块之间的通信
1,使用外部变量
即一个程序文件 file1.c中定义一个外部变量,另
一个程序文件 file2.c中的函数可以通过外部变量说明
后来使用这个变量,以实现模块间的通信。
说明形式,extern 类型说明符 外部变量名 ;
注意:只是进行了说明,并不是变量定义
2,举例
利用外部变量实现程序模块 f1.c与程序模块 f2.c之
间的通信 。
设程序模块文件 f1.c的内容如下:
#include<stdio.h>
int var=8; /* 全局变量的定义 */
main()
{ printf(―%d‖,var);
proc1();
printf(―%d\n‖,var);
}
下一页
第 12章 C语言综合应用程序举例
上一页
程序模块文件 f2.c的内容如下:
extern int var; /* 外部变量的说明 */
proc1()
{
var = 25 ;
}
程序编译连接
生成可执行文
件, 执行结果
为,8 25
下一页
第 12章 C语言综合应用程序举例
上一页
12.1.3 预处理命令 #include的应用
1,#include命令经过预处理后,会将其后有关文件
的内容拷贝到命令所在的源程序文件中。
2,在上一个例子中, 程序要能够编译运行, 需 建立
一个工程文件 f12.prj,其内容为:
f1.c
f2.c
然后对 f12.prj文件编译运行即可 。
3,也可以在 f1.c文件开头 加一预处理命令,
#include<stdio.h>
#include<f2.c>
int var=8;
main()
{ …… }
对 f1.c文件直接编译运行即可。
第 12章 C语言综合应用程序举例
上一页 返回
12.2 图形处理应用
图形处理是计算机应用的一个极具特色的领域,有
很好的应用前景,可以增强程序的趣味性、实用性。
12.2.1 基本图形处理库函数
Turbo C支持多种显示适配器的各种显示模式, 提
供了画点, 线, 圆, 椭圆, 多边形以及输出各种字
体等功能的函数 。
这些函数包含在图形头文件 ( graphics.h) 中, 在
进 行 目 标 程 序 连 接 时, 也 必 须 将 图 形 库 文 件
graphics.lib连接到目标程序中去, 其图形接口还包
括图形显示驱动程序 ( *.BGI) 等 。
下一页
第 12章 C语言综合应用程序举例
上一页
作用:将一个图形驱动程序装入内存, 并将系统设置成
图形模式;
说明,gd指定 所用的图形驱动程序, 其值可参照书上
的图形驱动程序常量表;
gm说明初始化的图形模式, 其取值见附录 ;
path指定驱动程序目录路径, 空字符时表示驱动
程序就在当前目录下 。
例如:若已知所用的图形适配器为 CGA,并打算使用
640× 200高分辨率模式 CGAHI,则图形初始化
部分可写成:
1,图形系统初始化函数
⑴ 显示模式控制函数 initgraph(gd,gm,path)
int gd = CGA,gm = CGAHI;
initgraph(&gd,&gm,―\\TC‖ );
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 自动检测显示器硬件的函数 detectgraph(gd,gm)
作用:当编程者不知所用的图形适配器的类型,
或者需要编写在不同图形模式下均能运行
的图形程序, 使用该函数可以完成对适配
器的检查, 获取显示器类型号 ( 赋给 gd)
及相应的显示模式 ( 赋给 gm) 。
例如:图形初始化部分可以写成:
int gd,gm;
detectgraph(&gd,&dm); /*自动测试硬件 */
initgraph(&gd,&gm,―\\TC‖ );
/* 根据测试结果进行图形初始化 */
下一页
第 12章 C语言综合应用程序举例
上一页
⑷ 恢复显示方式函数 closegraph( )
作用,关闭图形系统, 返回文本工作方式 。
⑸ 恢复工作模式函数 restorecrtmode( )
设置图形工作模式函数 setgraphmode( )
作用,使显示器工作方式在图形和文本方式
之间来回切换 。
⑶ 清屏函数 cleardevice( )
作用:用于 画图前进行清除屏幕 ;
作用范围为整个屏幕 。
下一页
第 12章 C语言综合应用程序举例
上一页
2,基本图形函数
⑴ 三种最基本的图形函数:画点, 线, 圆函数
画点函数 putpixel(x,y,color);
作用:将在坐标 x,y指定的位置上画一点,
该点的颜色由 color值决定 。
画线函数 line(startx,starty,endx,endy);
作用:在 (startx,starty)和 (endx,endy)两点
间画一直线, 颜色为系统当前颜色 。
画圆函数 circle(x,y,radius);
作用:用当前颜色画一个圆心在 (x,y)处, 半
径大小为 radius的圆 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 画圆弧, 扇形, 椭圆函数
画圆弧函数 arc(x,y,start,end,radius);
作用:用当前颜色,以 (x,y)为圆心,(start,end)
为起 止角,radius为半径画圆弧。
画扇形函数 pieslice(x,y,start,end,radius);
作用:用当前颜色,以 (x,y)为圆心,(start,end)
为起 止角,radius为半径画扇形。
画椭圆函数 ellipse(x,y,start,end,xradius,yradius);
作用:用当前画线颜色,以 (x,y)为中心,
(start,end)为起止角,(xradius,yradius)为
两轴半径画圆。
说明,start,end均以角度为单位 。 下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 画多边形, 矩形和条形图函数
画多边形函数 drawpoly(numpoints,points);
作用:用当前颜色画一个多边形,多边形的顶
点数 为 numpoints,而 points指向的整形数
组连续存放着各顶点的 (x,y)坐标。
画 矩形 函数 rectangle(left,top,right,bottom);
作用:用当前颜色,以 (left,top)为左上角坐标,
以 (right,bottom)为右下角坐标画一个矩形。
画 条形图 函数 bar(left,top,right,bottom);
bar3d(left,top,right,bottom,depth,topflag);
作用:用当前颜色,画一实心条形图;
depth决定 bar3d()产生的三维条形图的厚度,
topflag决定是否加顶盖。
下一页
第 12章 C语言综合应用程序举例
上一页
3,颜色控制函数
屏幕上显示出的点、线、面的颜色称为前景色,
而衬托它们的背景颜色称为背景色。在 Turbo C中常
使用的 16个标准色为:
下一页
第 12章 C语言综合应用程序举例
上一页
⑴ 颜色设置 函数 setcolor(color);
作用,用颜色值 color设置当前画图颜色 。
⑵ 图形填充 函数 floodfill(x,y,bordercolor);
作用:该函数对任意封闭图形进行填充,其颜色和
模式由设定的或缺省的颜色与图形模式决定。
说明:编程时该函数位于画图函数之后 ;参数 (x,y)
为封闭图形中的任意一点, bordercolor是封
闭图形的边框颜色 。
⑶ 填充模式 函数 setfillstyle(pattern,color);
作用,来设定 floodfill( )函数 的填充模式 。
说明,参数 pattern的值及其符号如下表所示 。
下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
举例,利用基本作图函数及颜色控制函数画图。 点击
4,图形模式下字符输出函数
⑴ 字符输出 函数 outtext(str);
作用,在当前位置输出由 str指定的字符串 。
说明:它能用不同的字型, 大小, 和不同的显示
方向输出文字 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 字符输出属性函数
settextstyle(font,direction,charsize);
作用,改变输出字符串的字型, 大小和方向 。
说明:参数 font确定所用的字型;
direction的值表示字符的显示方向 。 它可以
是 HORIZ-DIR( 水平输出, 值为 0), 或是
VERT-DIR( 垂直输出, 值为 1) 。
charsize是增加字符大小的倍数 ( 0 ~ 10) 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 字符输出定位函数 outtextxy(x,y,str);
作用,将 str指向的字符串输出到窗口位置 (x,y) 上。
5,视口操作函数
Turbo C所有图形函数实际上都是在视口(即窗
口)上操作的(在没有定义视口的情况下,它是整
个屏幕)。用户可以同时建立多个不同大小的视口,
每个视口操作函数的参数都是以其左上角(坐标为
0,0)为参考点的相对坐标。
⑴ 设置视口 函数 setviewport(x1,y1,x2,y2,clipflag);
作用:设置 左上角坐标为 (x1,y1),右下角坐标
为 (x2,y2)的视口。
说明,clipflag决定是否显示超出视口的图形部
分。 0—显 示; 1—不 显示。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 视口清除 函数 clearviewport( );
作用,清除视口内的图形 。
注意,使用 setviewport( )函数 可以在屏幕上开
辟多个视口, 这些视口可以重迭, 但最近一次设置
的视口才是当前视口 。 各图形函数都是在当前视口
中操作 。 其它视口中的内容只要不被清除, 就可以
保持在屏幕上 。
通过改变坐标位置移动视口,从而实现一个
立方体的连续往左移动。程序请
下一页
第 12章 C语言综合应用程序举例
上一页
点击
例如
6,建立独立运行的图形处理程序
要脱离 Turbo C 集成环境,建立可独立运行的
可执行图形程序,必须将图形驱动程序(有的还要
将字体驱动程序)连接到可执行的图形程序中。
⑴ 在 \tc子目录 下输入命令:
C:\TC>BGIOBJ EGAVGA ↙
作用:将驱动程序 EGAVGA.BGI 转换成相应的目
标文件 EGAVGA.OBJ。
⑵ 在 \tc子目录 下输入命令:
C:\TC>TLIB LIB\graphics.lib+EGAVGA·OBJ↙
作用:将目标文件 EGAVGA·OBJ 添加到
graphics.lib 库文件中 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 在用户程序调用 initgraph()函数 之前应加一语句:
registerbgidriver(EGAVGA-driver);
字体驱动程序的连接类似 。 经过 上述处理, 经编
译连接后的执行程序便可在任何目录或其它兼容机
上运行了 。
12.2.2 图形处理库函数应用示例
第 12章 C语言综合应用程序举例
上一页
举例:设有一组实验数据存于数组 val中,将它们用
曲 线表示在 x-y 坐标平面上。程序请 点击
返回
12.3 操作系统接口应用
1,DOS 基本组成
由引导程序模块, 基本输入输出系统, 文件管理和系
统调用模块, 命令处理模块等几个部分组成 。
C语言可以通过库函数实现与操作系统接口,即调
用操作系统中的子程序,从而实现用户应用程序的深层
次的开发。
12.3.1 DOS 操作系统简介
下一页
第 12章 C语言综合应用程序举例
上一页
DOS为用户引用其功能子程序,利用了系统的软件中
断。通过 CPU 的软中断指令 INT n 调用相应的程序。指
令中的 n是中断调用号(也称中断类型号),中断调用号
不同,则调用的程序就不同。
2,操作系统接口
?通过软件中断调用 BIOS 中的基本 I/O服务子程序,
这种方法常被称为低层接口。 常用的有,利用 INT 10
指令调用有关显示器服务程序;利用 INT 16H 指令
调用键盘服务程序。
下一页
第 12章 C语言综合应用程序举例
上一页
例:设置显示器显示模式为 320*200彩色图形模式的
汇编语言程序段如下:
MOVAL,4 ; 设显示模式
MOVAH,0 ; 设功能号
INT 10H ; 系统功能调用
?通过软件中断调用 IBMDOS模块中的功能程序, 即所谓
系统功能调用, 是高层接口 。 如 INT 21H 指令便是典型
的软件接口, 该接口包括了许多子功能 。
例,向显示器输出字符, A‖的汇编语言程序段如下:
MOV DL,,A‖ ; 置显示字符
MOV AH,2 ; 设功能号
INT 21H ; 系统功能调用
?使用这两种接口, 用户就可以在不与极复杂的硬件接口
打交道的情况下, 使用系统资源, 开发各种应用软件 。
?C语言作为一种中级语言, 它的一些库函数 实际上 就是
调用了一些系统功能调用子程序, 用户可以利用它们来
调用 BIOS及 DOS软件接口, 以实现特定功能 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.3.2 操作系统接口库函数
1,通用软中断调用库函数 int86()
int86(int intno,union REGS *inregs,union REGS
*outregs);
说明:参数 intno表示调用类型号, 相当于中断指令
int n调用的中断类型号 n;参数 inregs用于接收调用
功能号及相关的一些入口参数;参数 outregs用于接
收调用后的返回值, 即出口参数 。
下一页
第 12章 C语言综合应用程序举例
上一页
举例,在屏幕的 35行,20列处显示字符 串
,COMPUTER‖。程序请 点击
2,系统功能调用库函数 intdos()和 intdosx()
intdos(union REGS *inregs,union REGS *outregs );
intdosx(union REGS *inregs,union REGS *outregs,
struct REGS *segregs);
说明:与 DOS的系统功能调用 ( INT21H) 相对应 。
参数 inregs是入口参数, 表示相应的功能号;参数
outregs是出口参数, 保存调用后的返回值;参数
segregs是一个结构 SREGS类型的指针,用来设
置和保存 CPU段寄存器的值。
3,发送 DOS命令库函数 system()
system(char *cmd);
说明,cmd为 DOS系统下的命令字符串 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.3.3 鼠标器及其应用
安装好鼠标器驱动程序,并进行初始化后,然
后在应用程序中利用 INT 33H 功能调用管理鼠标
器的各种操作。
例 1,编写一个 C语言函数,完成鼠标器初始化工作,
测试鼠标安装情况,显示检查结果。
#include <dos.h>
union REGS regs;
int Msinit( )
{ int recored;
regs, x, ax = 0; /* 0# 功能, 初始化鼠标 */
int86(0x33,®s,®s); /* 调 BIOS子程序 */
recored = regs, x, ax;
/* 调用结果返回在 AX寄存器中 */ 下一页
第 12章 C语言综合应用程序举例
上一页
if (recored==0)
{ printf(―Mousenot found or Mouse driver
not installed.\n―);
return 0; } /* 初始化不成功 */
else return recored; /* 初始化成功 */
}
例 2,编写读取鼠标状态和鼠标位置的函数。
void Msget ( int *px,int *py,int *pbuttons )
{ regs, x, ax = 3; /* 调用 3号功能测试鼠标器 */
int86(0x33,®s,®s);
*px = regs, x, cx; / * 返回鼠标位置 */
*py = regs, x, dx; /* 返回鼠标位置 */
*buttons = regs, x, bx; /* 返回鼠标状态 */
}
第 12章 C语言综合应用程序举例
上一页 返回
12.4 C语言与汇编语言混合编程
由 C语言程序直接调用汇编语言程序的方法有两种:
在程序中嵌入汇编代码或直接调用汇编语言子程序。
12.4.1 汇编语言子程序的一般格式
.MODEL 内存模式
.DATA
…… ;定义数据
.CODE
PUBLIC _子程序名 ;说明在 C中调用的子程序名
_子程序名 PROC 过程类型
…… ;子程序体
RET
_子程序名 ENDP ;子程序定义结束
END ;程序结束 下一页
第 12章 C语言综合应用程序举例
上一页
说明:
1、汇编子程序和 C语言的
内存模式应一致;
2,过程类型有 FAR和
NEAR两种,表示 调用程
序和被调用程序是否在同
一个段内;
3,C语言对应的汇编语言
中,函数名和变量名前多
加了一个下划线( _),
因此在汇编语言中,子程
序名前应有下划线。
汇编语言子程序示例
.model small
.data
time db 10 ;10毫秒
.code
public _delay ;延迟
10ms
_delay proc
mov bl,time
delay,mov cx,2801
wait,loop wait
dec bl
jnz delay
ret
_delay endp
end
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.2 全局变量的传递
C语言程序 ( extern) 和汇编语言程序 ( public) 可以
通过全局变量传递信息, 其数据类型的对应关系如下表
所示 。
由于 C语言大小写是有区别的, 从而在与汇编语言混
合编程时, 最好在 options菜单下的 Linker子项中将
Case-Sensitive Link置成 off状态来取消 其区别 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.3 参数和返回值的传递
?C语言程序和汇编语言程序的参数传递是通过堆栈来
完成的 。 所谓堆栈, 实质就是一种先进后出的内存区域,
且只在一端进行出栈和入栈操作 。
?对 C语言而言, 参数进栈的顺序是从右到左 。 如在 C语
言程序中有语句 power2(int para1,int para2),则执行该
语句时堆栈中的内容如下图 所示, 通过 sp便可得到参数
值, 从而完成参数的数据传递 。
下一页
第 12章 C语言综合应用程序举例
上一页
举例:设某 C语言程序如下:
#include ―stdio.h‖
int power2(int,int);
main( )
{ printf(―2 的 4次方乘以 8为,%d‖,power2(8,4) ); } }
?当汇编语言子程序有返回值时, 是通过 ax和 dx寄存
器来进行传递的 。
下一页
第 12章 C语言综合应用程序举例
上一页
汇编语言子程序如下:
.model small
.code
public _power2
_power2 proc
push bp
mov bp,sp
mov ax,[bp+4] ; 将第一个参数的值 8送到 ax中
mov cx,[bp+6] ; 将第二个参数的值 4送到 cx中
shl ax,cl; 将 ax的内容左移 cl次,每移一次表示乘 2
pop bp
ret
_power2 endp
end
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.4 汇编语言子程序的汇编及与 C程序的连接
1,在集成环境下, 进行混合编程的程序编译连接
时, 需要先用宏汇编 ( MASM.EXE) 将汇编语言程
序进行汇编, 生成 OBJ文件 。 然后, 将此 OBJ文件
加入到 C程序中 。 最后进行连接, 生成 EXE文件 。
2,将 OBJ文件加入到 C程序, 对 Turbo C而言, 非
常简单 。 先编辑一个工程文件 ( *.prj), 其内容是
需要连接的汇编 OBJ文件和 C语言文件名列表, 如:
myc.c
mymasm.obj
3,然后在 Turbo C的集成环境中选择 project 主菜单
中的 project name 项, 将上面 编辑的工程文件名写
入, 便可进行连接 。 下一页
第 12章 C语言综合应用程序举例
上一页
12.4.5 内嵌汇编指令的 C 程序结构
在 C程序嵌入汇编指令的格式为:
asm <操作码 > <操作数 > <;或换行 >
例如:
int max( int a,int b)
{
asm mov ax,a
asm cmp ax,b
asm jg ok
asm mov ax,b
ok,return _ax; /*_ax为 Turbo C定义的伪寄存器变量名 */
}
下一页
第 12章 C语言综合应用程序举例
上一页
⑴ 在汇编语言代码中使用的 C语言变量应该初始化
且用 ptr指明对应的汇编语言类型;
⑵ 伪指令如 db 等不能嵌入;
⑶ 在 _asm 块中的注释为汇编语言的注释, 即分号;
⑷ 不应在 _asm 块中用 ret 指令返回, 而应用 C语言
的 return返回;
⑸ 汇编语言指令不需以分号 ( ; ) 作语句结束;
⑹ 也可用, _asm<操作码 > <操作数 > <;或换行 >‖的
形式加一行汇编语言指令 。
下一页
第 12章 C语言综合应用程序举例
上一页
说明
#include "iostream.h"
int asmmax(int a,int b)
{ int maxn=0; /* 初始化 maxn */
_asm
{ mov ax,word ptr a ; 将 a的值赋给 ax寄存器
mov dx,word ptr b ; 将 b的值赋给 dx寄存器
cmp ax,dx ; 比较 ax和 dx的大小
jg ok ; ax比 dx大则转标号 ok处
mov ax,dx } ; 将 dx的值赋给 ax
ok,_asm mov word ptr maxn,ax ; 将 ax的值赋给 maxn
return maxn ;
}
main( )
{ printf(―%d‖,asmmax(10,50));
return 0; }
下一页
第 12章 C语言综合应用程序举例
上一页
例如
12.4.6 内嵌汇编指令的 C 程序的编译和连接
对于 Turbo C而言, 内嵌汇编指令的 C程序要用 TCC命
令行来实现编译连接, 其形式是:
TCC<命令行选项 ><文件名 >
―命令行选项, 中与 内嵌汇编指令程序 有关的选项参考书
本 。
例如, TCC –I c:\tc\include –L c:\tc\lib –B –ml P1 P2.asm
mylib.lib
它表示:在 c:\tc\include目录中找包含文件 ( -I) ;
在 c:\tc\lib目录中找库文件 mylib.lib( -L) ;
用大模式 ( -ml) 编译文件 P1.c,调用 TASM对
P2.asm进行编译, 连接生成可执行文件 P1.exe。
第 12章 C语言综合应用程序举例
上一页 返回
12.5 综合应用程序示例 -- 汉字显示技术
12.5.1 汉字显示的基本原理
1,国标汉字字符集与区位码
区位码:每个汉字在汉字库中有确定的区号和位
号。区号在前,位号在后,合成一个 4位的十进制数字,
这就是所谓的区位码,用两个字节存放,第一个字节
表示区号,第二个字节表示位号。只要知道了区位码,
就可知道该汉字在字库中的地址。
下一页
第 12章 C语言综合应用程序举例
上一页
每个汉字在字库中以点阵字模形式存储,点阵有
16 x 16, 24 x 24及 32 x 32等多种。 16 x 16点阵
字库中,每个点阵字模用 32个字节来描述,其中的
每个点使用一个二进制位。当需要显示时,把某个
汉字的 16 x 16点阵信息直接送到显示器上,值为 1
的点可以在屏上显示一个亮点;值为 0的点则不亮,
这样就可显现出相应的汉字。
国标码,与区位码之间存在着一种简单的换算关系:
国标码的区号 = 区位码的区号 + 32( 或 20H)
国标码的位号 = 区位码的位号 + 32( 或 20H)
例如,, 计, 字的区位码为 2838(或 1C26H),其
国标码为 6070(或 3C46H)。 下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
2,汉字内码
汉字内码是汉字信息处理系统内部标示汉字的
编码,也称机内码。它与国标码也存在一种简单的
对应关系:
机内码区号 = 国标码的区号 + 128( 或 80H)
机内码位号 = 国标码的位号 + 128( 或 80H)
例如,,啊, 字的区位码为 1602( 1002H),国
标码为 3022H,机内码为 B0A2H。
下一页
第 12章 C语言综合应用程序举例
上一页
在西文状态下,对使用汉字的 C语言程序采用如
下方法:读出汉字的内码,将其转换成字库的区位
码,然后直接到字库中去找出汉字字模。再用有关
的位操作和循环语句,对字模各个字节的每一位进
行判断。如果某位是 1,则按设置的颜色在屏幕的相
应位置画点,若该位为 0则不画点。这样就可按预先
设置的颜色在相应的位置显示出该汉字来。
下一页
第 12章 C语言综合应用程序举例
上一页
3,区位码与内码的转化关系及字模显示技术
汉字内码与区位码存在着固定的转换关系:
设某汉字内码的十六进制数表示形式为 0xkkjj,
则相应区位码的区号 qh 和位号 wh 分别为:
qh=0xkk - 0xa0; wh=0xjj - 0xa0;
下一页
第 12章 C语言综合应用程序举例
上一页
若用十进制数表示内码为 c1c2,则
qh=c1-160; wh=c2-160;
即区位码 qw 为,qw=100*(c1-160)+(c2-160);
反之亦可由区位码 qw求得区号和位号:
qh=qw/100; wh=qw-100*qh;
对于国标 2312-80汉字字库, 汉字库分成 94个区,
每个区有 94个位, 每个位存放一个汉字, 当汉字点
阵为 16× 16 时, 每 个 汉 字 的 字 模 大 小 为
(16× 16)/8=32个字节 。 因而该汉字在汉字库中离
起点的偏移位置 ( 以字节为单位 ), 可由如下表达
式计算:
offset=(94*(qh-1)+(wh-1))*32L;
下一页
第 12章 C语言综合应用程序举例
上一页
注意, 偏移量对于不同的汉字库是不相同的 。 下
面给出几种常用汉字库中地址码 offset的计算 公式:
⑴ ucdos中的字库 CCLIB.DAT存放 16x16点阵字模:
offset=((qh-1)*94+(wh-1))*32L;
⑵ CCDOS 2.13中的字库 HZK16存放 16x16点阵字模:
offset=((qh-16)*94+wh-1+15*94)*32L;
⑶ SPDOS5.0的简体字库 CCLIB.DAT存放 16x16点阵
字模:
offset=((qh-7)*94+wh-1)*32L;
⑷ CCDOS 2.13中的字库 hzk24存放 24x24点阵字模:
offset=((qh-16)*94+wh-1)*72L;
下一页
第 12章 C语言综合应用程序举例
上一页
12.5.2 西文 DOS环境下的汉字显示
1,汉字显示方法
在西文 DOS环境下,可以采用画点或画线的方法。
⑴ 利用画点函数 putpixel()显示汉字
根据汉字字模点阵信息的各个字节每位的状态来
判断是否在相应的位置上画点 。 若该位为 1,则在相
应的位置上用函数 putpixel( )画一点;若是 0则跳过 。
这样形成的亮点组合起来就是一个汉字的字形 。
下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 利用画线函数 lineto()显示汉字
根据汉字字模点阵信息可以确定组成汉字 16线
每条线的线型参数, 用 setlinestyle()设置线型,
再由 lineto()函数画 16点长的线, 重复 16次这样的
过程, 画 16条不同的线型的直线, 就可组成一个汉
字 。
设置线型函数 setlinestyle(linestyle,upattern,thickness);
说明,参数 linestyle 用于指定画线的线型;参数
upattern 仅当线型参数为 USERBIT_LINE时才起作用 。
可用 16位二进制, 4位 16进制或十进制数来表示 。 表示
成 16位二进制数时, 每位代表一个象素点 。 若某位是 1,
则线中的对应像素用当前颜色画出来;否则对应的象素
点用背景色显示;参数 thickness用于指定画线的宽度 。
下一页
第 12章 C语言综合应用程序举例
上一页
汉字的垂直输出是指将汉字逆时针方向旋转 90度,
然后进行输出显示。即将按行输出汉字字模改为按
列输出就可以实现。放大汉字的方法是将字模数据
中的每一位用一个填充长方形或椭圆来表示。
在 C应用程序中使用的汉字量一般都比较少。因此,
可以把在程序中用到的汉字制作成小字库,当程序运
行时,首先把小字库加载到内存,在显示汉字时可直
接从内存中读取汉字字模数据。这样既可提高汉字的
显示速度,又避免了由于加载整个汉字库所造成的内
存浪费或影响程序的运行。
下一页
第 12章 C语言综合应用程序举例
上一页
2,汉字的垂直输出与放大显示
3,小字库技术
举例,编写创建一个名为 USER.LIB小字库的程序。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXNUM 100 /*小字库最多可容纳的汉字数 */
unsigned char *hzstring=‖‖;
main()
{ unsigned char hzmatrix[MAXNUM][32];
int hzcde[MAXNUM];
long p;
int i,j;
int quma,weima;
unsigned char buf[32];
下一页
第 12章 C语言综合应用程序举例
上一页
FILE *fp,*cclibfile;
fp=fopen(user.lib,‖wb‖);
if(fp==NULL)
{printf(―\Can’topen write file! Press any key to halt… ‖);
getch();
exit(1);
}
cclibfile=fopen(―hzk16‖,‖rb‖);
if(cclibfile==NULL)
{printf(―\Can’topen hzk16 file! Press any to halt… ‖);
getch();
exit(1);
}
下一页
第 12章 C语言综合应用程序举例
上一页
i=0;
While(*hzstring)
{ quma=*hzstring-0xa0; /*计算区号 */
weima=*(hzstring+1)-0xa0; /*计算位号 */
p=(quma-1)*94+weima-1;
/*计算汉字字模的记录号 */
p*=32; /*字模首址 */
hzcode[i]=100*quma+weima;
/*保存区位码, 作为汉字索引 */
fseek(cclibfile,(long)p,SEEK_SET);
/*将文件指针指向字模首地址 */
fread(buf,sizeof(unsigned char),32,cclibfile);
/*读取字模数据 */
下一页
第 12章 C语言综合应用程序举例
上一页
for(j=0;j<32;j++)
hzmatrix[i][j]=buf[j];/*将字模数据存入 hzmatrix*/
hzstring+=2;
i++;
}
fwrite(hzcode,sizeof(hzcode),1,fp);
/*记录区位码 */
fwrite(hzmatrix,sizeof(hzmatrix),1,fp);
/* 向字库文件写入字模 */
fclose(fp);
fclose(cclibfile);
}
第 12章 C语言综合应用程序举例
上一页
例题:小字库的使用。
参照教材。
返回
12.1 多模块编程方法
12.2 图形处理应用
12.3 操作系统接口应用
12.4 C语言与汇编语言混合编程
12.5 综合应用程序举例 —汉字显示技术
一个有实用价值的 C语言应用程序往往较大,需
要划分成不同的模块,分配给不同的程序员去完成。
因此,在实用软件的开发中,往往需要采用多模块编
程技术。
12.1 多模块编程方法
使用多模块编程技术的处理过程大致如下:
1,首先 将一个大的源程序根据其功能合理地划分成
若干个小的源程序, 每个小源程序均以程序文件 (.C)
的形式保存在磁盘上 。 并建立一个包括各个源程序
模块的文件名的工程文件 (.prj)。
12.1.1 程序模块组织
下一页
第 12章 C语言综合应用程序举例
上一页
2,然后 用编译器进行编译,将工程文件中指定的
多个源程序文件进行编译,生成多个目标文件和一
个可执行文件。注意,在分模块单独编译处理的各
个程序模块中,必须有且只有一个主函数 main( ) 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.1.2 模块之间的通信
1,使用外部变量
即一个程序文件 file1.c中定义一个外部变量,另
一个程序文件 file2.c中的函数可以通过外部变量说明
后来使用这个变量,以实现模块间的通信。
说明形式,extern 类型说明符 外部变量名 ;
注意:只是进行了说明,并不是变量定义
2,举例
利用外部变量实现程序模块 f1.c与程序模块 f2.c之
间的通信 。
设程序模块文件 f1.c的内容如下:
#include<stdio.h>
int var=8; /* 全局变量的定义 */
main()
{ printf(―%d‖,var);
proc1();
printf(―%d\n‖,var);
}
下一页
第 12章 C语言综合应用程序举例
上一页
程序模块文件 f2.c的内容如下:
extern int var; /* 外部变量的说明 */
proc1()
{
var = 25 ;
}
程序编译连接
生成可执行文
件, 执行结果
为,8 25
下一页
第 12章 C语言综合应用程序举例
上一页
12.1.3 预处理命令 #include的应用
1,#include命令经过预处理后,会将其后有关文件
的内容拷贝到命令所在的源程序文件中。
2,在上一个例子中, 程序要能够编译运行, 需 建立
一个工程文件 f12.prj,其内容为:
f1.c
f2.c
然后对 f12.prj文件编译运行即可 。
3,也可以在 f1.c文件开头 加一预处理命令,
#include<stdio.h>
#include<f2.c>
int var=8;
main()
{ …… }
对 f1.c文件直接编译运行即可。
第 12章 C语言综合应用程序举例
上一页 返回
12.2 图形处理应用
图形处理是计算机应用的一个极具特色的领域,有
很好的应用前景,可以增强程序的趣味性、实用性。
12.2.1 基本图形处理库函数
Turbo C支持多种显示适配器的各种显示模式, 提
供了画点, 线, 圆, 椭圆, 多边形以及输出各种字
体等功能的函数 。
这些函数包含在图形头文件 ( graphics.h) 中, 在
进 行 目 标 程 序 连 接 时, 也 必 须 将 图 形 库 文 件
graphics.lib连接到目标程序中去, 其图形接口还包
括图形显示驱动程序 ( *.BGI) 等 。
下一页
第 12章 C语言综合应用程序举例
上一页
作用:将一个图形驱动程序装入内存, 并将系统设置成
图形模式;
说明,gd指定 所用的图形驱动程序, 其值可参照书上
的图形驱动程序常量表;
gm说明初始化的图形模式, 其取值见附录 ;
path指定驱动程序目录路径, 空字符时表示驱动
程序就在当前目录下 。
例如:若已知所用的图形适配器为 CGA,并打算使用
640× 200高分辨率模式 CGAHI,则图形初始化
部分可写成:
1,图形系统初始化函数
⑴ 显示模式控制函数 initgraph(gd,gm,path)
int gd = CGA,gm = CGAHI;
initgraph(&gd,&gm,―\\TC‖ );
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 自动检测显示器硬件的函数 detectgraph(gd,gm)
作用:当编程者不知所用的图形适配器的类型,
或者需要编写在不同图形模式下均能运行
的图形程序, 使用该函数可以完成对适配
器的检查, 获取显示器类型号 ( 赋给 gd)
及相应的显示模式 ( 赋给 gm) 。
例如:图形初始化部分可以写成:
int gd,gm;
detectgraph(&gd,&dm); /*自动测试硬件 */
initgraph(&gd,&gm,―\\TC‖ );
/* 根据测试结果进行图形初始化 */
下一页
第 12章 C语言综合应用程序举例
上一页
⑷ 恢复显示方式函数 closegraph( )
作用,关闭图形系统, 返回文本工作方式 。
⑸ 恢复工作模式函数 restorecrtmode( )
设置图形工作模式函数 setgraphmode( )
作用,使显示器工作方式在图形和文本方式
之间来回切换 。
⑶ 清屏函数 cleardevice( )
作用:用于 画图前进行清除屏幕 ;
作用范围为整个屏幕 。
下一页
第 12章 C语言综合应用程序举例
上一页
2,基本图形函数
⑴ 三种最基本的图形函数:画点, 线, 圆函数
画点函数 putpixel(x,y,color);
作用:将在坐标 x,y指定的位置上画一点,
该点的颜色由 color值决定 。
画线函数 line(startx,starty,endx,endy);
作用:在 (startx,starty)和 (endx,endy)两点
间画一直线, 颜色为系统当前颜色 。
画圆函数 circle(x,y,radius);
作用:用当前颜色画一个圆心在 (x,y)处, 半
径大小为 radius的圆 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 画圆弧, 扇形, 椭圆函数
画圆弧函数 arc(x,y,start,end,radius);
作用:用当前颜色,以 (x,y)为圆心,(start,end)
为起 止角,radius为半径画圆弧。
画扇形函数 pieslice(x,y,start,end,radius);
作用:用当前颜色,以 (x,y)为圆心,(start,end)
为起 止角,radius为半径画扇形。
画椭圆函数 ellipse(x,y,start,end,xradius,yradius);
作用:用当前画线颜色,以 (x,y)为中心,
(start,end)为起止角,(xradius,yradius)为
两轴半径画圆。
说明,start,end均以角度为单位 。 下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 画多边形, 矩形和条形图函数
画多边形函数 drawpoly(numpoints,points);
作用:用当前颜色画一个多边形,多边形的顶
点数 为 numpoints,而 points指向的整形数
组连续存放着各顶点的 (x,y)坐标。
画 矩形 函数 rectangle(left,top,right,bottom);
作用:用当前颜色,以 (left,top)为左上角坐标,
以 (right,bottom)为右下角坐标画一个矩形。
画 条形图 函数 bar(left,top,right,bottom);
bar3d(left,top,right,bottom,depth,topflag);
作用:用当前颜色,画一实心条形图;
depth决定 bar3d()产生的三维条形图的厚度,
topflag决定是否加顶盖。
下一页
第 12章 C语言综合应用程序举例
上一页
3,颜色控制函数
屏幕上显示出的点、线、面的颜色称为前景色,
而衬托它们的背景颜色称为背景色。在 Turbo C中常
使用的 16个标准色为:
下一页
第 12章 C语言综合应用程序举例
上一页
⑴ 颜色设置 函数 setcolor(color);
作用,用颜色值 color设置当前画图颜色 。
⑵ 图形填充 函数 floodfill(x,y,bordercolor);
作用:该函数对任意封闭图形进行填充,其颜色和
模式由设定的或缺省的颜色与图形模式决定。
说明:编程时该函数位于画图函数之后 ;参数 (x,y)
为封闭图形中的任意一点, bordercolor是封
闭图形的边框颜色 。
⑶ 填充模式 函数 setfillstyle(pattern,color);
作用,来设定 floodfill( )函数 的填充模式 。
说明,参数 pattern的值及其符号如下表所示 。
下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
举例,利用基本作图函数及颜色控制函数画图。 点击
4,图形模式下字符输出函数
⑴ 字符输出 函数 outtext(str);
作用,在当前位置输出由 str指定的字符串 。
说明:它能用不同的字型, 大小, 和不同的显示
方向输出文字 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 字符输出属性函数
settextstyle(font,direction,charsize);
作用,改变输出字符串的字型, 大小和方向 。
说明:参数 font确定所用的字型;
direction的值表示字符的显示方向 。 它可以
是 HORIZ-DIR( 水平输出, 值为 0), 或是
VERT-DIR( 垂直输出, 值为 1) 。
charsize是增加字符大小的倍数 ( 0 ~ 10) 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 字符输出定位函数 outtextxy(x,y,str);
作用,将 str指向的字符串输出到窗口位置 (x,y) 上。
5,视口操作函数
Turbo C所有图形函数实际上都是在视口(即窗
口)上操作的(在没有定义视口的情况下,它是整
个屏幕)。用户可以同时建立多个不同大小的视口,
每个视口操作函数的参数都是以其左上角(坐标为
0,0)为参考点的相对坐标。
⑴ 设置视口 函数 setviewport(x1,y1,x2,y2,clipflag);
作用:设置 左上角坐标为 (x1,y1),右下角坐标
为 (x2,y2)的视口。
说明,clipflag决定是否显示超出视口的图形部
分。 0—显 示; 1—不 显示。
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 视口清除 函数 clearviewport( );
作用,清除视口内的图形 。
注意,使用 setviewport( )函数 可以在屏幕上开
辟多个视口, 这些视口可以重迭, 但最近一次设置
的视口才是当前视口 。 各图形函数都是在当前视口
中操作 。 其它视口中的内容只要不被清除, 就可以
保持在屏幕上 。
通过改变坐标位置移动视口,从而实现一个
立方体的连续往左移动。程序请
下一页
第 12章 C语言综合应用程序举例
上一页
点击
例如
6,建立独立运行的图形处理程序
要脱离 Turbo C 集成环境,建立可独立运行的
可执行图形程序,必须将图形驱动程序(有的还要
将字体驱动程序)连接到可执行的图形程序中。
⑴ 在 \tc子目录 下输入命令:
C:\TC>BGIOBJ EGAVGA ↙
作用:将驱动程序 EGAVGA.BGI 转换成相应的目
标文件 EGAVGA.OBJ。
⑵ 在 \tc子目录 下输入命令:
C:\TC>TLIB LIB\graphics.lib+EGAVGA·OBJ↙
作用:将目标文件 EGAVGA·OBJ 添加到
graphics.lib 库文件中 。
下一页
第 12章 C语言综合应用程序举例
上一页
⑶ 在用户程序调用 initgraph()函数 之前应加一语句:
registerbgidriver(EGAVGA-driver);
字体驱动程序的连接类似 。 经过 上述处理, 经编
译连接后的执行程序便可在任何目录或其它兼容机
上运行了 。
12.2.2 图形处理库函数应用示例
第 12章 C语言综合应用程序举例
上一页
举例:设有一组实验数据存于数组 val中,将它们用
曲 线表示在 x-y 坐标平面上。程序请 点击
返回
12.3 操作系统接口应用
1,DOS 基本组成
由引导程序模块, 基本输入输出系统, 文件管理和系
统调用模块, 命令处理模块等几个部分组成 。
C语言可以通过库函数实现与操作系统接口,即调
用操作系统中的子程序,从而实现用户应用程序的深层
次的开发。
12.3.1 DOS 操作系统简介
下一页
第 12章 C语言综合应用程序举例
上一页
DOS为用户引用其功能子程序,利用了系统的软件中
断。通过 CPU 的软中断指令 INT n 调用相应的程序。指
令中的 n是中断调用号(也称中断类型号),中断调用号
不同,则调用的程序就不同。
2,操作系统接口
?通过软件中断调用 BIOS 中的基本 I/O服务子程序,
这种方法常被称为低层接口。 常用的有,利用 INT 10
指令调用有关显示器服务程序;利用 INT 16H 指令
调用键盘服务程序。
下一页
第 12章 C语言综合应用程序举例
上一页
例:设置显示器显示模式为 320*200彩色图形模式的
汇编语言程序段如下:
MOVAL,4 ; 设显示模式
MOVAH,0 ; 设功能号
INT 10H ; 系统功能调用
?通过软件中断调用 IBMDOS模块中的功能程序, 即所谓
系统功能调用, 是高层接口 。 如 INT 21H 指令便是典型
的软件接口, 该接口包括了许多子功能 。
例,向显示器输出字符, A‖的汇编语言程序段如下:
MOV DL,,A‖ ; 置显示字符
MOV AH,2 ; 设功能号
INT 21H ; 系统功能调用
?使用这两种接口, 用户就可以在不与极复杂的硬件接口
打交道的情况下, 使用系统资源, 开发各种应用软件 。
?C语言作为一种中级语言, 它的一些库函数 实际上 就是
调用了一些系统功能调用子程序, 用户可以利用它们来
调用 BIOS及 DOS软件接口, 以实现特定功能 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.3.2 操作系统接口库函数
1,通用软中断调用库函数 int86()
int86(int intno,union REGS *inregs,union REGS
*outregs);
说明:参数 intno表示调用类型号, 相当于中断指令
int n调用的中断类型号 n;参数 inregs用于接收调用
功能号及相关的一些入口参数;参数 outregs用于接
收调用后的返回值, 即出口参数 。
下一页
第 12章 C语言综合应用程序举例
上一页
举例,在屏幕的 35行,20列处显示字符 串
,COMPUTER‖。程序请 点击
2,系统功能调用库函数 intdos()和 intdosx()
intdos(union REGS *inregs,union REGS *outregs );
intdosx(union REGS *inregs,union REGS *outregs,
struct REGS *segregs);
说明:与 DOS的系统功能调用 ( INT21H) 相对应 。
参数 inregs是入口参数, 表示相应的功能号;参数
outregs是出口参数, 保存调用后的返回值;参数
segregs是一个结构 SREGS类型的指针,用来设
置和保存 CPU段寄存器的值。
3,发送 DOS命令库函数 system()
system(char *cmd);
说明,cmd为 DOS系统下的命令字符串 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.3.3 鼠标器及其应用
安装好鼠标器驱动程序,并进行初始化后,然
后在应用程序中利用 INT 33H 功能调用管理鼠标
器的各种操作。
例 1,编写一个 C语言函数,完成鼠标器初始化工作,
测试鼠标安装情况,显示检查结果。
#include <dos.h>
union REGS regs;
int Msinit( )
{ int recored;
regs, x, ax = 0; /* 0# 功能, 初始化鼠标 */
int86(0x33,®s,®s); /* 调 BIOS子程序 */
recored = regs, x, ax;
/* 调用结果返回在 AX寄存器中 */ 下一页
第 12章 C语言综合应用程序举例
上一页
if (recored==0)
{ printf(―Mousenot found or Mouse driver
not installed.\n―);
return 0; } /* 初始化不成功 */
else return recored; /* 初始化成功 */
}
例 2,编写读取鼠标状态和鼠标位置的函数。
void Msget ( int *px,int *py,int *pbuttons )
{ regs, x, ax = 3; /* 调用 3号功能测试鼠标器 */
int86(0x33,®s,®s);
*px = regs, x, cx; / * 返回鼠标位置 */
*py = regs, x, dx; /* 返回鼠标位置 */
*buttons = regs, x, bx; /* 返回鼠标状态 */
}
第 12章 C语言综合应用程序举例
上一页 返回
12.4 C语言与汇编语言混合编程
由 C语言程序直接调用汇编语言程序的方法有两种:
在程序中嵌入汇编代码或直接调用汇编语言子程序。
12.4.1 汇编语言子程序的一般格式
.MODEL 内存模式
.DATA
…… ;定义数据
.CODE
PUBLIC _子程序名 ;说明在 C中调用的子程序名
_子程序名 PROC 过程类型
…… ;子程序体
RET
_子程序名 ENDP ;子程序定义结束
END ;程序结束 下一页
第 12章 C语言综合应用程序举例
上一页
说明:
1、汇编子程序和 C语言的
内存模式应一致;
2,过程类型有 FAR和
NEAR两种,表示 调用程
序和被调用程序是否在同
一个段内;
3,C语言对应的汇编语言
中,函数名和变量名前多
加了一个下划线( _),
因此在汇编语言中,子程
序名前应有下划线。
汇编语言子程序示例
.model small
.data
time db 10 ;10毫秒
.code
public _delay ;延迟
10ms
_delay proc
mov bl,time
delay,mov cx,2801
wait,loop wait
dec bl
jnz delay
ret
_delay endp
end
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.2 全局变量的传递
C语言程序 ( extern) 和汇编语言程序 ( public) 可以
通过全局变量传递信息, 其数据类型的对应关系如下表
所示 。
由于 C语言大小写是有区别的, 从而在与汇编语言混
合编程时, 最好在 options菜单下的 Linker子项中将
Case-Sensitive Link置成 off状态来取消 其区别 。
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.3 参数和返回值的传递
?C语言程序和汇编语言程序的参数传递是通过堆栈来
完成的 。 所谓堆栈, 实质就是一种先进后出的内存区域,
且只在一端进行出栈和入栈操作 。
?对 C语言而言, 参数进栈的顺序是从右到左 。 如在 C语
言程序中有语句 power2(int para1,int para2),则执行该
语句时堆栈中的内容如下图 所示, 通过 sp便可得到参数
值, 从而完成参数的数据传递 。
下一页
第 12章 C语言综合应用程序举例
上一页
举例:设某 C语言程序如下:
#include ―stdio.h‖
int power2(int,int);
main( )
{ printf(―2 的 4次方乘以 8为,%d‖,power2(8,4) ); } }
?当汇编语言子程序有返回值时, 是通过 ax和 dx寄存
器来进行传递的 。
下一页
第 12章 C语言综合应用程序举例
上一页
汇编语言子程序如下:
.model small
.code
public _power2
_power2 proc
push bp
mov bp,sp
mov ax,[bp+4] ; 将第一个参数的值 8送到 ax中
mov cx,[bp+6] ; 将第二个参数的值 4送到 cx中
shl ax,cl; 将 ax的内容左移 cl次,每移一次表示乘 2
pop bp
ret
_power2 endp
end
下一页
第 12章 C语言综合应用程序举例
上一页
12.4.4 汇编语言子程序的汇编及与 C程序的连接
1,在集成环境下, 进行混合编程的程序编译连接
时, 需要先用宏汇编 ( MASM.EXE) 将汇编语言程
序进行汇编, 生成 OBJ文件 。 然后, 将此 OBJ文件
加入到 C程序中 。 最后进行连接, 生成 EXE文件 。
2,将 OBJ文件加入到 C程序, 对 Turbo C而言, 非
常简单 。 先编辑一个工程文件 ( *.prj), 其内容是
需要连接的汇编 OBJ文件和 C语言文件名列表, 如:
myc.c
mymasm.obj
3,然后在 Turbo C的集成环境中选择 project 主菜单
中的 project name 项, 将上面 编辑的工程文件名写
入, 便可进行连接 。 下一页
第 12章 C语言综合应用程序举例
上一页
12.4.5 内嵌汇编指令的 C 程序结构
在 C程序嵌入汇编指令的格式为:
asm <操作码 > <操作数 > <;或换行 >
例如:
int max( int a,int b)
{
asm mov ax,a
asm cmp ax,b
asm jg ok
asm mov ax,b
ok,return _ax; /*_ax为 Turbo C定义的伪寄存器变量名 */
}
下一页
第 12章 C语言综合应用程序举例
上一页
⑴ 在汇编语言代码中使用的 C语言变量应该初始化
且用 ptr指明对应的汇编语言类型;
⑵ 伪指令如 db 等不能嵌入;
⑶ 在 _asm 块中的注释为汇编语言的注释, 即分号;
⑷ 不应在 _asm 块中用 ret 指令返回, 而应用 C语言
的 return返回;
⑸ 汇编语言指令不需以分号 ( ; ) 作语句结束;
⑹ 也可用, _asm<操作码 > <操作数 > <;或换行 >‖的
形式加一行汇编语言指令 。
下一页
第 12章 C语言综合应用程序举例
上一页
说明
#include "iostream.h"
int asmmax(int a,int b)
{ int maxn=0; /* 初始化 maxn */
_asm
{ mov ax,word ptr a ; 将 a的值赋给 ax寄存器
mov dx,word ptr b ; 将 b的值赋给 dx寄存器
cmp ax,dx ; 比较 ax和 dx的大小
jg ok ; ax比 dx大则转标号 ok处
mov ax,dx } ; 将 dx的值赋给 ax
ok,_asm mov word ptr maxn,ax ; 将 ax的值赋给 maxn
return maxn ;
}
main( )
{ printf(―%d‖,asmmax(10,50));
return 0; }
下一页
第 12章 C语言综合应用程序举例
上一页
例如
12.4.6 内嵌汇编指令的 C 程序的编译和连接
对于 Turbo C而言, 内嵌汇编指令的 C程序要用 TCC命
令行来实现编译连接, 其形式是:
TCC<命令行选项 ><文件名 >
―命令行选项, 中与 内嵌汇编指令程序 有关的选项参考书
本 。
例如, TCC –I c:\tc\include –L c:\tc\lib –B –ml P1 P2.asm
mylib.lib
它表示:在 c:\tc\include目录中找包含文件 ( -I) ;
在 c:\tc\lib目录中找库文件 mylib.lib( -L) ;
用大模式 ( -ml) 编译文件 P1.c,调用 TASM对
P2.asm进行编译, 连接生成可执行文件 P1.exe。
第 12章 C语言综合应用程序举例
上一页 返回
12.5 综合应用程序示例 -- 汉字显示技术
12.5.1 汉字显示的基本原理
1,国标汉字字符集与区位码
区位码:每个汉字在汉字库中有确定的区号和位
号。区号在前,位号在后,合成一个 4位的十进制数字,
这就是所谓的区位码,用两个字节存放,第一个字节
表示区号,第二个字节表示位号。只要知道了区位码,
就可知道该汉字在字库中的地址。
下一页
第 12章 C语言综合应用程序举例
上一页
每个汉字在字库中以点阵字模形式存储,点阵有
16 x 16, 24 x 24及 32 x 32等多种。 16 x 16点阵
字库中,每个点阵字模用 32个字节来描述,其中的
每个点使用一个二进制位。当需要显示时,把某个
汉字的 16 x 16点阵信息直接送到显示器上,值为 1
的点可以在屏上显示一个亮点;值为 0的点则不亮,
这样就可显现出相应的汉字。
国标码,与区位码之间存在着一种简单的换算关系:
国标码的区号 = 区位码的区号 + 32( 或 20H)
国标码的位号 = 区位码的位号 + 32( 或 20H)
例如,, 计, 字的区位码为 2838(或 1C26H),其
国标码为 6070(或 3C46H)。 下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
2,汉字内码
汉字内码是汉字信息处理系统内部标示汉字的
编码,也称机内码。它与国标码也存在一种简单的
对应关系:
机内码区号 = 国标码的区号 + 128( 或 80H)
机内码位号 = 国标码的位号 + 128( 或 80H)
例如,,啊, 字的区位码为 1602( 1002H),国
标码为 3022H,机内码为 B0A2H。
下一页
第 12章 C语言综合应用程序举例
上一页
在西文状态下,对使用汉字的 C语言程序采用如
下方法:读出汉字的内码,将其转换成字库的区位
码,然后直接到字库中去找出汉字字模。再用有关
的位操作和循环语句,对字模各个字节的每一位进
行判断。如果某位是 1,则按设置的颜色在屏幕的相
应位置画点,若该位为 0则不画点。这样就可按预先
设置的颜色在相应的位置显示出该汉字来。
下一页
第 12章 C语言综合应用程序举例
上一页
3,区位码与内码的转化关系及字模显示技术
汉字内码与区位码存在着固定的转换关系:
设某汉字内码的十六进制数表示形式为 0xkkjj,
则相应区位码的区号 qh 和位号 wh 分别为:
qh=0xkk - 0xa0; wh=0xjj - 0xa0;
下一页
第 12章 C语言综合应用程序举例
上一页
若用十进制数表示内码为 c1c2,则
qh=c1-160; wh=c2-160;
即区位码 qw 为,qw=100*(c1-160)+(c2-160);
反之亦可由区位码 qw求得区号和位号:
qh=qw/100; wh=qw-100*qh;
对于国标 2312-80汉字字库, 汉字库分成 94个区,
每个区有 94个位, 每个位存放一个汉字, 当汉字点
阵为 16× 16 时, 每 个 汉 字 的 字 模 大 小 为
(16× 16)/8=32个字节 。 因而该汉字在汉字库中离
起点的偏移位置 ( 以字节为单位 ), 可由如下表达
式计算:
offset=(94*(qh-1)+(wh-1))*32L;
下一页
第 12章 C语言综合应用程序举例
上一页
注意, 偏移量对于不同的汉字库是不相同的 。 下
面给出几种常用汉字库中地址码 offset的计算 公式:
⑴ ucdos中的字库 CCLIB.DAT存放 16x16点阵字模:
offset=((qh-1)*94+(wh-1))*32L;
⑵ CCDOS 2.13中的字库 HZK16存放 16x16点阵字模:
offset=((qh-16)*94+wh-1+15*94)*32L;
⑶ SPDOS5.0的简体字库 CCLIB.DAT存放 16x16点阵
字模:
offset=((qh-7)*94+wh-1)*32L;
⑷ CCDOS 2.13中的字库 hzk24存放 24x24点阵字模:
offset=((qh-16)*94+wh-1)*72L;
下一页
第 12章 C语言综合应用程序举例
上一页
12.5.2 西文 DOS环境下的汉字显示
1,汉字显示方法
在西文 DOS环境下,可以采用画点或画线的方法。
⑴ 利用画点函数 putpixel()显示汉字
根据汉字字模点阵信息的各个字节每位的状态来
判断是否在相应的位置上画点 。 若该位为 1,则在相
应的位置上用函数 putpixel( )画一点;若是 0则跳过 。
这样形成的亮点组合起来就是一个汉字的字形 。
下一页
第 12章 C语言综合应用程序举例
上一页
下一页
第 12章 C语言综合应用程序举例
上一页
⑵ 利用画线函数 lineto()显示汉字
根据汉字字模点阵信息可以确定组成汉字 16线
每条线的线型参数, 用 setlinestyle()设置线型,
再由 lineto()函数画 16点长的线, 重复 16次这样的
过程, 画 16条不同的线型的直线, 就可组成一个汉
字 。
设置线型函数 setlinestyle(linestyle,upattern,thickness);
说明,参数 linestyle 用于指定画线的线型;参数
upattern 仅当线型参数为 USERBIT_LINE时才起作用 。
可用 16位二进制, 4位 16进制或十进制数来表示 。 表示
成 16位二进制数时, 每位代表一个象素点 。 若某位是 1,
则线中的对应像素用当前颜色画出来;否则对应的象素
点用背景色显示;参数 thickness用于指定画线的宽度 。
下一页
第 12章 C语言综合应用程序举例
上一页
汉字的垂直输出是指将汉字逆时针方向旋转 90度,
然后进行输出显示。即将按行输出汉字字模改为按
列输出就可以实现。放大汉字的方法是将字模数据
中的每一位用一个填充长方形或椭圆来表示。
在 C应用程序中使用的汉字量一般都比较少。因此,
可以把在程序中用到的汉字制作成小字库,当程序运
行时,首先把小字库加载到内存,在显示汉字时可直
接从内存中读取汉字字模数据。这样既可提高汉字的
显示速度,又避免了由于加载整个汉字库所造成的内
存浪费或影响程序的运行。
下一页
第 12章 C语言综合应用程序举例
上一页
2,汉字的垂直输出与放大显示
3,小字库技术
举例,编写创建一个名为 USER.LIB小字库的程序。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXNUM 100 /*小字库最多可容纳的汉字数 */
unsigned char *hzstring=‖‖;
main()
{ unsigned char hzmatrix[MAXNUM][32];
int hzcde[MAXNUM];
long p;
int i,j;
int quma,weima;
unsigned char buf[32];
下一页
第 12章 C语言综合应用程序举例
上一页
FILE *fp,*cclibfile;
fp=fopen(user.lib,‖wb‖);
if(fp==NULL)
{printf(―\Can’topen write file! Press any key to halt… ‖);
getch();
exit(1);
}
cclibfile=fopen(―hzk16‖,‖rb‖);
if(cclibfile==NULL)
{printf(―\Can’topen hzk16 file! Press any to halt… ‖);
getch();
exit(1);
}
下一页
第 12章 C语言综合应用程序举例
上一页
i=0;
While(*hzstring)
{ quma=*hzstring-0xa0; /*计算区号 */
weima=*(hzstring+1)-0xa0; /*计算位号 */
p=(quma-1)*94+weima-1;
/*计算汉字字模的记录号 */
p*=32; /*字模首址 */
hzcode[i]=100*quma+weima;
/*保存区位码, 作为汉字索引 */
fseek(cclibfile,(long)p,SEEK_SET);
/*将文件指针指向字模首地址 */
fread(buf,sizeof(unsigned char),32,cclibfile);
/*读取字模数据 */
下一页
第 12章 C语言综合应用程序举例
上一页
for(j=0;j<32;j++)
hzmatrix[i][j]=buf[j];/*将字模数据存入 hzmatrix*/
hzstring+=2;
i++;
}
fwrite(hzcode,sizeof(hzcode),1,fp);
/*记录区位码 */
fwrite(hzmatrix,sizeof(hzmatrix),1,fp);
/* 向字库文件写入字模 */
fclose(fp);
fclose(cclibfile);
}
第 12章 C语言综合应用程序举例
上一页
例题:小字库的使用。
参照教材。
返回