C语言编程技巧_第1页
C语言编程技巧_第2页
C语言编程技巧_第3页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、函数包含类别功能_atoldmath.h数学子程序把字符串转换为浮点数beginthreadprocess.h进程控制子程序启动执行一个新线程bios diskbios.h接口子程序输出 BIOS 磁盘驱动器服务bios equiplistbios.h接口子程序检查设备bios keybrdbios.h接口子程序直接使用 BIOS 的键盘接口bios memsizebiosd.h存储子程序返回内存大小bios printerbios.h接口子程序直接调用 BIOS 服务进行打印机 I/Obios timeofdaybios.h时间和日期子程序读取或设置 BIOS 时钟_biosserialco

2、mbios.h接口子程序进行串行 I/O_c_exitprocess.h进程控制子程序不终止程序执行如同 _exit 的清除_cexitprocess.h进程控制子程序不终止程序执行如同 _exit 的清除chdrivedirect.h目录控制子程序设置当前驱动器chian intrdos.h接口子程序chmodeio.h输入输出子程序改变文件的存取权限_clear87float.h数学子程序清除浮点状态字_closeio.h输入输出子程序关闭文件( 3。 1)以下版本control87float.h数学子程序处理浮点控制字creatio.h输入输出子程序创建一个新文件或重写一个已存在的文件d

3、isabledos.h接口子程序屏蔽中断_dos_allocmemdos.h存储子程序_dos_closedos.h输入输出子程序关闭一个文件dos craetedos.h输入输出子程序创建一个新文件或重写一个已存在的文件_dos_createnewdos.h输入输出子程序创建一个新文件dos findfirstdos.h目录控制子程序搜索一个磁盘目录_dos_findnextdos.h目录控制子程序继续 _dos_findfirst 的搜索_dos_freememdos.h存储子程序_dos_getdatedos.h时间和日期子程序取得和设置系统日期dos getdiskfredos.h目录

4、控制子程序取得磁盘空闲空间dos getdrivedos.h目录控制子程序取得和设置当前驱动器号dos getfileattdos.h输入输出子程序取得和设置文件属性dos getftimedos.h输入输出子程序取得和设置文件日期和时间_dos_gettimedos.h时间和日期子程序取得和设置系统时间_dos_getvectdos.h接口子程序取得中断向量_dos_keepdos.h接口子程序dos opendos.h输入输出子程序打开一个文件用于读和写_dos_readdos.h输入输出子程序从文件读_dos_setblockdos.h存储子程序_dos_setdatedos.h时间和日

5、期子程序设置系统日期dos setdrivedos.h目录控制子程序设置当前驱动器号dos setfileattdos.h输入输出子程序设置文件属性_dos_setfitmedos.h_dos_settimedos.h_dos_setvectdos.h_dos_writedos.h_enabledos.h输入输出子程序 设置文件时间 时间和日期子程序 设置系统时间exitfpresent _fsopen _fullpath_getdcwd_graphfreemem _graphgetmem _harderr _hardresumeprocess.h float.h stdio.h stdlib

6、.h direct.h direct.hgraphics.h graphics.h dos.h dos.h_hardretn dos.h _heapaddalloc.h_heapminmalloc.h_hea 视频教程 '>pset 块接口子程序输入输出子程序 接口子程序进程控制子程序 数学子程序输入输出子程序 目录控制子程序目录控制子程序 目录控制子程序图形子程序 图形子程序 接口子程序 接口子程序接口子程序malloc.h设置中断向量写向文件开硬件中断终止程序重新初始化浮点数学包把相对路径名转换为绝对路径名取得指定驱动器的当前目录取得当前驱动器号可修改的图形内存释放函数可修改

7、的图形内存分配函数建立一个硬件错误处理程序硬件错误处理函数硬件错误处理函数添加一个块到堆上释放无用的堆区域 用一个常量值填充堆上的自由_initEasyWin lrotl lrotr_makeepath matherrl matherrl open OvrInitEms OvrInitExt pclose_popen _read rotl rotl rotr searchstr setcursortype setcursortype setcursortype _splitpath _status87 _strdate _strerror _strtimeio.h初始化 Ease window

8、sstdlib.h数学子程序将无符号长整型数向左循环移位stdlib.h数学子程序将无符号长整型数向右循环移位stdlib.h目录控制子程序生成一个路径math.h诊断子程序用户可修改的数学错误处理程序math.h数学子程序用户可修改的数学错误处理程序io.h输入输出子程序打开一个文件进行读和写dos.h初始化复盖治理程序用于交换 EMS 内存dos.h初始化复盖治理程序用于交换 EXT 内存stdio.h等待一个管道命令结束stdio.h创建一个子命令处理程序管道io.h输入输出子程序读文件( 3。1 以下版本)stdlib.h嵌入子程序将一个无符号整数左循环移位stdlib.h数学子程序把

9、一个无符号整数左循环移位stdlib.h嵌入子程序将一个无符号整数向左循环移位stdlib.h为某文件查找某些目录graphics.h图形子程序选择光标类型conio.h输入输出子程序选择光标类型conio.h文本窗口显示子程选择光标类型stdlib.h目录控制子程序将一个全限定的路径名分解各个成份float.h数学子程序取浮点状态stdlib.h转换子程序把当前日期转换成字符串string.h stdio输入输出子程序建立用户定义的错误信息stdlib.h转换子程序转换当前日期为字符串_strtoldstdlib.h转换子程序_strtoldstdlib.h数学子程序tolowerctype

10、.h转换子程序把字符转换成小写字母_writeio.h输入输出子程序写文件abortprocess.h进程控制子程序异常终止一进程absstdlib.h compl数学子程序返回整数的绝对值abslmath.h数学子程序计算复数的模absreaddos.h接口子程序读磁盘的绝对扇区abswritedos.h接口子程序写磁盘的绝对扇区accessio.h输入输出子程序确定文件的存取权限acosmath.h complex数学子程序计算反余弦值acoslmath.h数学子程序计算反余弦值allocamalloc.h存储子程序分配临时堆栈空间allocmdos.h存储子程序分配 DOS 内存arcg

11、raphics.h图形子程序画园弧argcomplex.h数学子程序求复平面中一个复数的弧度asctimetime.h时间和日期子程序 转换日期和时间为对应的asinmath.h complex数学子程序反正弦函数asinlmath.h数学子程序反正弦函数assertassert.h诊断子程序条件终止函数atan2math.h complex数学子程序计算 y/x 的反正切值atan2lmath.h数学子程序计算 y/x 的反正切值atofstdlib.h转换子程序将字符串转换为浮点数at ofmath.h stdlib.数学子程序将字符串转换成浮点数atoistdlib.h转换子程序将字符串

12、转换为整数atoistdlib.h数学子程序把字符串转换成整型数atolstdlib.h转换子程序将字衔串转换成长整型数atolstdlib.h数学子程序抬字符串转换为长整型bargraphics.h图形子程序画二维条形图bar3dgraphics.h图形子程序画一个三维条形图bcdbcd.h数学子程序把一个数转换为相对应的bdosdos.h接口子程序DOS 系统调用bdosptrdos.h接口子程序DOS 系统调用bioscombios.h接口子程序I/O 通讯biosdiskbios.h接口子程序调用 BIOS 磁盘驱动程序bioseqiplistbios.h接口子程序检查设备bioske

13、ybios.h接口子程序调用 BIOS 的键盘接口biosmemorybios.h接口子程序返加内存的大小biosprintfbios.h接口子程序调用 BIOS 的打印 I/O 接口biostimebios.h接口子程序读取或设置 BIOS 时钟brkalloc.h存储子程序改变数据段内存分配cabsmath.h数学子程序计算复数的模callocalloc.h stdlib存储子程序分配内存ceilmath.h数学子程序舍入ASCII 码BCD 码ceillmath.h数学子程序舍入cgetsconio.h输入输出子程序读字符串chdirdir.h目录控制子程序改变当前目录chmodio.h

14、输入输出子程序改变文件存取权限chsizeio.h输入输出子程序修改文件长度circlegraphics.h图形子程序画园cleardevicegraphics.h图形子程序清图形屏幕clearerrio.h输入输出子程序复位错误标志clearviewportgraphics.h图形子程序清除当前图形窗口closeio.h输入输出子程序关闭文件closedirdirect.h目录控制子程序关闭目录流closegraphgraphics.h图形子程序关闭图形系统clreolconio.h文本窗口显示子程清除从当前光标位置到行尾的字符clrscrconio.h文本窗口显示子程清除文本窗口,并把光标

15、放在左上角complexcomplex.h数学子程序创建复数conjcomplex.h数学子程序求复数的共轭复数coreleftalloc.h stdlib存储子程序 返顺未使用的内存大小cosmath.h complex 数学子程序计算余弦值coshmath.h complex 数学子程序计算双曲余弦值coshlmath.h数学子程序计算双曲余弦值coslmath.h数学子程序计算余弦值countrydos.h接口子程序读取与特定国家有关的格式cprintfconio.h输入输出子程序格式化并输出数据到屏幕cputsconio.h输入输出子程序输出一字符串到屏幕creatio.h输入输出子程

16、序创建一个新文件或重写一个已存在的文件creatnewio.h输入输出子程序创建新文件creattempio.h输入输出子程序创建一个文件名唯一的文件cscanfconio.h输入输出子程序从控制台执行格式化输入ctimetime.h时间和日期子程序把日期和时间转化为对应的字符串ctrlbrkdos.h接口子程序设置 CTRL-BREAK 处理程序delaydos.h杂类子程序暂停 DOSdellineconio.h文本窗口显示子程在文本窗口中删去一行detectgraphgraphics.h图形子程序检测硬件并确定使用何种图形驱运程序和图形difftimetime.h时间和日期子程序计算二个

17、时刻的时间差disabledos.h接口子程序屏蔽中断css.shtml' target'_blank' title ='div 视频教程 '>divmath.h 数学子程序将二个整数相除,返回商和余数dosexterrdos.h接口子程序获取扩展错误信息dostounixdos.h时间和日期子程序把日期和时间转换成 UNIX 格式drawpolygraphics.h图形子程序绘制多边形dupio.h输入输出子程序复制文件句柄dup2io.h输入输出子程序将一个文件句柄复制到一个已有的文件句柄ecvtstdlib.h转换子程序把浮点数转换成字符串e

18、cvtstdlib.h数学子程序把浮点数转换为字符串elipsegraphics.h图形子程序绘制椭园enabledos.h接口子程序开硬件中断eofio.h输入输出子程序检测文件是否结束execleprocess.h进程控制子程序装入并运行其它程序execlpprocess.h进程控制子程序装入并运行其它程序execlpeprocess.h进程控制子程序装入并运行其它程序exectprocess.h进程控制子程序execvprocess.h进程控制子程序装入并运行其它程序本文章来自21 视频教程网C 语言编程常见问题解答之常用函数的包含文件(1) _C 语言程序设计教程 原文链接:C 语言编

19、程常见问题解答之杂项 (Miscellaneous) ( 2)请参见:2012 怎样把数据从一个程序传递到另一个程序?2017可以使热启动 (Ctrl+Alt+Delete) 失效吗 ?2110 什么是动态连接 ?20 9 为什么要使用静态变量 静态变量作为一个局部变量是很合适的,它在函数退出后不会失去其本身的值。例如,有一个 要被调用很多次的函数,它的一部分功能就是计算自己被调用的次数。你不能用一个简单的局部变 量来实现这部分功能,因为每次进入该函数时,这个变量都没有被初始化。假如把这个计数变量说 明为静态的,那么它就会象一个全局变量那样保留自己的当前值。那么为什么不直接使用一个全局变量呢?

20、你可以使用一个全局变量, 而且这样做没有错误。 问题是使用了大量全局变量的程序维护起来很麻烦, 尤其是有许多函数都各自访问一个全局变量的程序。 再说一遍,这样做没有错误,这只是一个程序设计和可读性是否好的问题。假如你把这样的变量说 明为静态的, 你就可以提醒自己 (或者其它可能读你的程序的人 )它是局部变量, 但要象全局变量那样 被处理 (保留自己的值 )。假如你把它说明为全局的, 那么读这个程序的人一定会认为有很多地方要引 用它,尽管实际上并不是这样。总而言之,当你需要一个能保持自己的值的局部变量时,使用静态变量是一种好的编程习惯。请参见:2 17 可以头文件中说明 static 变量吗 ?

21、20 10 怎样在一个程序后面运行另一个程序?显然,在一个程序后面运行另一个程序的最简单的办法是把它们依次列入一个批处理文件中, 在执行该批处理文件时,其中所列的程序就会依次运行。然而,这是一种人们已经知道的办法。在 c 或 DOS 中,都没有一种特定的方法来完成“在一个程序结束后运行另一个程序”这样一种 函数调用。然而, c 提供了两组函数,它们答应一个程序随时可以运行另一个程序,而后者的运行 将结束前者的运行。 假如你将这样的一个函数调用放到第一个程序的末尾, 你就能达到上述目的。 C 所提供的这两组函数实际上是由exec()和spawn()所代表的两个函数族,其中的每一个函数都具有一种区

22、别于同族其它函数的功能。exec()函数族包括这样一些成员:execl(), execle(), execlp(), execlpe(),execv(),execve(),execvp()和execvpe()。下面列出了这此函数名中的e, l,p和v等后缀的含义:e明确地把一个指向环境参数的指针数组传递给子进程l把命令参数逐个传递给要执行的程序p通过环境变量 PATH 找到要执行的文件v把命令行参数以一个指针数组的形式传递给要执行的程序在程序中选用哪一个函数完全取决于你以及要执行的程序的需要。下例中的程序调用了其参数 由命令行指定的另一个程序:# include <stdio. h>

23、;# include <process. h> char * envString = "COMM VECTOR=0x63", "PARENT=LAUNCH. EXE", "EXEC=EDIT. COM", NULL ;voidmain(int argc, char *argv)/ * environment for the app * /* communications vector */ * name of this app * / * name of app to exec * / * must be NULL-ter

24、minated * / * Call the one with variable argumets and an enviroffment * /_execvpe (" EDIT. COM", argv, envString ) ;printf("If you can read this sentence, the exec didn't happen!n") ;上面这个短小的例子调用 _execvpe()来执行DOS的文件编辑器 EDIT . COM , EDIT程序的参数 来自该例的命令行。在调用execvpe()函数后,上例中的程序就结束了

25、;当 EDIT程序退出时,你将返回到DOS提示符。假如printf()语句的打印内容显示在屏幕上,则说明_execvpe()函数调用出了问题,因为假如它调用成功,就不会有上述结果。注重,上例所提供的EDIT.COM 的环境变量是没有任何意义的,然而,假如上例要执行一个需要环境变量的程序,那么所提供的环境变量就能供该程 序使用了。用spawn()函数同样可以完成上例所做的工作。spawn()函数族包括这样一些成员:spawnl(), spawnle()。 spawnlp(), spawnlpe(), spawnv(), spawnve(), spawnvp()禾口 spawnvpe()。 这些函

26、数名中的 e, l, p和v等后缀的含义与 exec()族函数名中的相同。实际上,spawn()函数族与exec()函数族基本相同,只不过有一点小小的差别一一spaw n()函数既可以在结束原来的程序后启动另一个程序,也可以启动另一个程序并在该程序结束后返回到原来的程序。spaw n()函数的参数与exec()函数的基本相同,只不过需要增加一个参数一你必须用_P_OVERLAY(结束原来的程序)或_P_WAIT( 结束后返回到原来的程序 面的例子相同的工作:)作为spawn()函数的第一个参数。下例用spawn()函数元成了与前# include <stdio. h># inclu

27、de <process. h>char * envString = "COMM VECTOR = 0x63", "PARENT=LAUNCH. EXE", "EXEC=EDIT. COM" , NULL ;/ * environment for the app * / * communications vector * / * name of this app * / * name of app to exec * / * must be NULL-terminated * /voidmain(int argc, char

28、 *argv)/ * Call the one with variable argumets and an environment * /_spawnvpe (_P_OVERLAY, "EDIT. COM", argv, envString) ;printf("If you can read this sentence, the exec didn't happen!n" );这里唯一的区别是"exec”变为"spawn",并且增加了模式(mode)参数。spawn()函数有覆盖和等 待两种相对立的功能,它使你可以在

29、spawn()运行期间做出是等待还是离开的决定。实现上,P_WAIT参数回答了下一个问题。请参见:2011 怎样在一个程序执行期间运行另一个程序?2011 怎样在一个程序执行期间运行另一个程序?正如你在20. 10的例子中看到的那样,spawn()函数族答应在一个程序中启动另一个程序,并 在后者结束后返回到前者之中。有关spawn()函数的背景知识和例子(你只需把其中的_P_OVERLAY改为 _P_WAIT) 请参见 20. 10。然而,还有另外一种方法可以完成这项工作,即使用system()函数。system()函数与exec()或spawn()函数相似,但也不有同之处。除了挂起(而不是结

30、束)当前程序去执行新程序外,system()还要启动COMMAND . COM 命令翻译程序 (或者其它任何运行在你的计算机上的命令翻译程序)。假如它找不到COMMAND .COM或类似的程序,那么它就不会去执行所要求的程序(这一点与exec()或spaw n()函数不同 )。下例是调用 EDIT COM 打开一个文件的另一个程 序版本,其中的文件名也来自该例 的命令行:# include <stdio. h># include <process. h># inclued <stdlib. h>char argStr255 ;voidmain(int arg

31、c, char *argv)int ret ;/ * Have EDIT open a file called HELLO if no arg given * /sprintf (argStr ,"EDIT %s", (argv1 = NULL?"HELLO" :argyll3) ) ;/ * Call the one with variable arguments and an environment * /ret = sytem (argStr) ;printf("system() returned %dn" ,ret) ;与20

32、. 10中的例子一样(使用_P_WAIT),在system()调用后面的print()语句会被执行,因为原 来的程序只是被挂起而不是被终止。在每一种情况下,system()都会返回一个表示是否成功地运行了所指定的程序的值,而不会返回所指定的程序的返回值。请参见:2010 怎样在一个程序后面运行另一个程序?2012 怎样把数据从一个程序传给另一个程序步骤都相当简洁:首先,定义在何处存放数据,如何获取数据,以及如何通知另一个程序来获取或 设置数据;然后,你就可以获取或设置数据了,尽管使用文件的技术定义和实现起来都比较简单, 但它的速度往往比较慢 (并且轻易引起混乱 )。因此, 这里重点讨论内存数据

33、转移技术。下面将依次具体地分析这一过程的每一个环节:定义在何处存放数据。当你编写要共享数据的两个程序时,你应该让程序知道要访问的数据存 放在何处。这个环节同样有几种实现方法: 你可以在一个 ( 或每个 )程序中建立一个固定的内部缓冲区, 并在两个程序之间传递指向这个缓冲区的指针;你也可以为数据分配动态内存,并在两个程序之间 传递指向该数据的指针;假如要传递的数据很小,你还可以通过 CPU 的通用寄存器来传递数据 (这 种可能性很小,因为 x86 结构的寄存器很少 )。分配动态内存是最灵活和模块性最强的方法。定义获取数据的方法。这个环节非常简洁你可以使用 fmemcpy() 或等价的内存拷贝函数

34、。 显然,在获取和设置数据时都可以使用这个函数。定义通知另一个程序的方法。因为 DOS 并不是一个多任务操作系统,所以其中一个(或两个 )程序的一部分必须已经驻留在内存中,并且可以接受来自另一个程序的调用。同样,这个环节也有几 种方法可供选择:第一个程序可以是一个列入 CONFIG SYS 中的驱动程序,它在系统启动时就被 装入内存;第一个程序也可以是一个 TSR( 终止并驻留 ) 程序,在它退出时会把与第二个程序相互作 用的那部分程序驻留在内存中;此外,你也可以在第一个程序中利用system()或spawn()函数(见20.11)来启动第二个程序。你可以根据需要选择合适的方法。因为有关DOS

35、 驱动程序的数据传递在 DOS文档中已经有详尽的描述,而有关system。和spawn()函数的内容也已经在前文中介绍过,因此下面介绍 TSR 方法。下面的例子给出了两个程序:第一个程序是一个完整的 TSR 程序,但为了突出整个过程中的要 害环节,它写得比较单薄(见20. 15中的解释)。这个TSR程序先是安装了一个中断63H的中断服务程序,然后调用终止并驻留退出函数,在执行这个 TSR 程序后,执行下文给出的另一个程序。这 个程序只是简单地初始化一个对中断63H的调用(类似于使用中断21H调用),并且把“ Hello There ”传送给上述 TSR 程序# include <stdl

36、ib. h># include <dos. h># include <string. h>void SetupPointers (void) ;void OutputString(char * );# define STACKSIZE4096unsigned int near OldStackPtr; unsigned int near OldStackSeg; unsigned int _near MyStackOff ; unsigned int _near MyStackSeg; unsigned char_near MyStackSTACKSIZE; un

37、signed char far * MyStackPtr= (unsigned char_far * )MyStack; unsigned short AX, BX,CX, DX,ES;/ * My interrupt handler * / void_interrupt_far_ 视频教程 '>cdecl NewCommVector ( unsigned short es, unsigned short ds, unsigned short di, unsigned short si, unsigned short bp, unsigned short sp, unsigned

38、 short bx, unsigned short dx, unsigned short cx, unsigned short ax, unsigned short ip, unsigned short cs,unsigned short flags) ;/ * Pointers to the previous interrupt handier * / void(_interrupt_far_cdecl * CommVector)(); union REGS regs;struet SREGS segregs ;# define COMM_VECTOR0x63/ * Software int

39、errupt vector * / * This is where the data gets passed into the TSR * / char_far * eallerBufPtr;char localBuffer255; / * Limit of 255 bytes to transfer * / char_far * localBufPtr=(ehar_far * )loealBuffer;unsigned int ProgSize= 276;/ * Size of the program in paragraphs * /voidmain(int argc,char * * a

40、rgv)int i, idx;/ * Set up all far pointers * /SetupPointers () ;/ * Use a cheap hack to see if the TSR is already loadedtf it is, exit,doing nothing * / comm_veetor =_dos_getvect (COMM_VECTOR) ; if(long)eomm_vector & 0xFFFFL) =(long) NewCommVector & OxFFFFL ) ) OutputString("Error :TSR

41、appears to already be loaded. n"); return ;/ * If everything's set,then chain in the TSR * / _dos_setvect (COMM_VECTOR ,NewCommVector) ;/ * Say we are loaded * /OutputString("TSR is now loaded at 0x63n");/ * Terminate, stay resident * / dos_keep (0, ProgSize ) ;/ * Initializes all

42、 the pointers the program will use * /voidSet upPointers ( )int idx ;/ * Save segment and offset of MyStackPtr for stack switching * / MyStackSeg = FP_SEG (MyStackPtr) ;MyStackOff = FP_OFF (MyStackPtr) ;/ * Initialize my stack to hex 55 so I can see its footprintif I need to do debugging * / for (id

43、x = 0 ;idx<STACKSIZE ; idx + ) MyStack idx = 0x55 ;void _interrupt_ far_cdecl NewCommVector (unsigned short es, unsigned short ds, unsigned short di, unsigned short si, unsigned short bp, unsigned short sp, unsigned short bx, unsigned short dx, unsigned short cx, unsigned short ax, unsigned short

44、 ip, unsign ed short cs, unsigned short flags)AX = ax;BX = bx ;CX = cx;DX = dx ;ES = es ;/ * Switch to our stack so we won't run on somebody else's * / _asm ;set up a local stackeli; stop interruptsmovOldStackSeg,ss; save stack segmentmovOldStackPtr,sp; save stack pointer (offset)movax,ds; r

45、eplace with my stack smovss,ax; dittomovax,MyStackOff; replace with my stack saddax,STACKSIZE-2;add in my stack sizemovsp ,ax; dittosti; OK for interrupts againswitch (AX) case 0x10;/ * print string found in ES:BX */ * Copy data from other application locally * / FP_ SEG (callerBufPtr) = ES ; FP_OFF

46、 (callerBufPtr) = BX ; _fstrcpy (localBufPtr, callerBufPtr ) ;/ * print buffer 'CX'number of times * /for(; CX>0; CX-)OutputString (localBufPtr) ; AX=1; /* show success */ break ;case 0x30:/* Unload stop processing interrupts * /_dos_setvect (COMM_VECTOR ,comm_vector) ; AX=2;/* show succe

47、ss */break ;default :OutputString (" Unknown commandrn" ) ;AX= 0xFFFF; / * unknown command-1 * /break ;/ * Switch back to the caller's stack * / asm climovmovsti;turn off interrupts ss,OldStackSeg;reset old stack segmentsp,OldStackPtr ;reset old stack pointer ;back on againax=AX;/* use

48、 return value from switch() */ * avoids calling DOS to print characters * / voidOutputString(char * str)int i ;regs. h. ah = 0x0E ;regs. x. bx = 0 ; for(i=strlen(str) ; i>0; i-,str+)regs. h. al= * str; int86 (0xl0, ?s, ?s) ;上述程序是这两个程序中的TSR程序。这个程序中有一个NewCommVector()函数,它被安装在中断 63H(63H 通常是一个可用的向量 )处

49、作为中断服务程序。 当它被安装好后, 它就可以接收命令了。 switch 语句用来处理输入的命令,并作出相应的反应。笔者随意选择了0x1O 和 0x30 来代表这样两条命令:“从 ES:BX 处复制数据,并打印到屏幕上, CX 中的数值为打印次数” ;“脱离中断 63H, 并停止接收命令” 。下面是第二个程序向中断 63H 发送命令的程序 (注重它必须在 Large 模式下 编译 )。# include <stdlib. h># include <dos. h># define COMM VECTOR 0x63union REGS regs;struct SREGS s

50、egregs ;char buffer80;char _far * buf=(char_far *)buffer;main (int argc,char * * argv)intcnt;cnt = (argo= =1 ? 1:atoi(argv1) ;strcpy (bur, "Hello Therern" ) ;regs. x. ax= 0x10;regs. x. cx=cnt ;regs. x. bx=FP OFF(buf);segregs, es=FP SEG(buf) ;int86x(COMM_VECTOR ,?s, &segregs) ;printf (&

51、quot;TSR returned %dn" ,regs. x. ax) ;你可能会认为这个短小的程序看上去和那些通过调用int 21或int 10来在DOS中设置或检索信息的程序差不多。假如你真的这么想,那就对了。唯一的区别就是现在你所用的中断号是63H,而不是21H或10H。上述程序只是简单地调用前文中的TSR程序,并要求后者把 es: bX所指向的字符串打印到屏幕上,然后,它把中断处理程序(即那个TSR程序)的返回值打印到屏幕上。当字符串"Hello There ”被打印到屏幕上后,在两个程序之间传递数据的全部必要步骤就都完成 了。这个例子的真正价值在于它能够举一反三

52、。现在你能很轻松地编写一个这样的程序,它将发送 一条类似于“把要求你打印的最后一个字符串传递给我”的命令。你所要做的就是在前述TSR程序的 switch 语句中加入这条命令,然后再写一个程序来发送这条命令。此外,你也可以在第二个程序 中利用20. 11中所介绍的system()或spawn()函数来启动前述 TSR程序。由于TSR程序会检查自己 是否已被装入,因此你只需装入一次 TSR 程序,就可以多次运行第二个程序了。在所有要和前述 TSR 程序通信的程序中,你都可以使用这里所说的方法。在建立前述 TSR 程序时,需要有几个前提条件。其一就是没有其它重要的中断服务程序也在处 理中断63H。例

53、如,笔者原来在程序中使用的是中断67H,结果该程序能正常装入并运行,但此后笔者就无法编译程序了,因为Microsoft用来运行C编译程序的DOS扩展程序也要使用中断 67H。在笔者发送了命令 0x30(让程序卸载自身)后,编译程序又能正常运行了,因为DOS扩展程序的中断处理程序已被该程序恢复了。第二个前提条件与驻留检查在关。 笔者假设永远不会有另一个中断处理程序使用和 NewCommVector() 相同的近程型地址,尽管这种巧合的可能性极小,但读者应该知道该程序并不是 万无一失的。在该程序中,笔者特意让 NewCommVector() 使用自己的栈,以避免它运行在调用它的 程序的栈上,但是,

54、 笔者还是假设调用所需的任何函数都是安全的。注重,该程序没有调用 printf() ,因为它占用较多的内存,并且要调用DOS(int 21)来打印字符。在该程序中,当中断63H发生时,笔者不知道DOS是否可以被调用,因此不能假设可以使用DOS调用。注重,在该程序中,可以调用那些没有用到 DOS int21 服务程序的函数来完成所需的任务,假如必 须使用一个 DOS 服务程序,你可以在中断 63H 发生时检查 DOS 忙标志,以确定当时 DOS 是否可 以被调用。最后,对dos_keep()作一点说明:该函数要求知道在程序退出时要在内存中保留多少段(每段16字节)数据。在本例这个TSR程序中,提供给该函数的段数(276)稍大于整个可执行程序的大小。 当你的程序变大时,提供给该函数的段数也必须增大,否则就会出现一些异常现象。请参见:20. 10 怎样在一个程序后面运行另一个程序 ?20. 1l 怎样在一个程序执行期间运行另一个程序 ?20. 15 本书的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论