子程序库
库文件对学过C/C 语言程序设计的读者来说应该是不会陌生的,该语言的程序设计环境提供了大量的库文件,也就是说,提供了大量的标准函数或过程。在本节里,介绍读者如何创建自己的库文件。
建立库文件命令LIB
宏汇编MASM系统提供了建立库文件的命令文件LIB.EXE。其通常是在命令行环境(MS-DOS方式)下使用的,当然,也可在Windows 95/98等环境下利用其“开始”菜单下的“运行”功能项来使用。
一、MS-DOS系统
显示命令LIB用法的命令如下:
…>lib /?
该命令的显示结果如图7.9中所示。
二、Windows系统
命令LIB的使用方式和显示结果如图7.8和7.9所示。
三、命令显示内容的解释
1)、各选项的解释
选项 |
含义 |
|
/?、/HELP |
显示LIB命令的用法,描述各命令行参数的含义 |
|
/IGNORECASE |
忽略子程序名中的大小写 |
在实践中,作用不明显 |
/NOIGNORECASE |
不忽略子程序名中的大小写 |
|
/NOEXTDICTIONARY |
不建立扩展的目录 |
|
/NOLOGO |
不显示版本号和版权信息 |
|
/PAGESIZE:n |
设置库文件的每页字节数为n |
2)、命令项的解释:
选项 |
含义 |
name |
向库文件中加一个新的目标文件 |
-name |
从库文件中删除一个指定的目标文件 |
- name |
用新的目标文件替换掉库文件中原有的目标文件 |
*name |
拷贝出指定的目标文件 |
-*name |
从库文件中移出指定的目标文件 |
在弄懂了LIB的各项功能含义后,读者就可根据自己的需要来建立库文件了。
7.6.2建立库文件举例
假设现有目标文件sub1.obj、sub2.obj和sub3.obj,要用它们建立库文件mylib.lib。可用下列方法来建立该库文件:
方法1:所有目标文件都准备好了,可一次性把它们加入到库文件中
…>lib mylib sub1 sub2 sub3
方法2:随着目标文件的逐个生成,而依次把它们加入到库文件中
…>lib mylib sub1
…>lib mylib sub2
…>lib mylib sub3
假如源文件sub3.asm已修改,并也生成了新的目标文件sub3.obj,这时,就需要把库文件mylib.lib中的sub3.obj替换成新的目标文件。于是,可用下面命令来实现替换:
…>lib mylib - sub3
当提示输入目标库文件名(Output library)时,可按“回车”用默认的原库文件名。
如果想查看库文件mylib.lib中各文件的大小和存放的先后次序,可用下列命令:
…>lib mylib, list ;把库文件mylib.lib中的文件结构生成到文件list中
…>type list
7.6.3 库文件的应用
在开发一个功能较 弱的应用程序时,其执行文件通常可由一个目标文件连接而成,当开发一个功能较强、关系较复杂的应用程序时,其执行文件很难由一个目标文件连接而成,常常是 由多个目标文件(模块)连接而成的。各模块之间无疑会存在着相互调用、相互访问数据单元等内在联系,各模块之间的相互联系就产生了这样的问题:程序员如何 在源程序中来表达这种联系?
为了解决描述各模块之间的联系,汇编语言提供了二条伪指令PUBLIC和EXTRN,它们的作用有点象C/C 语言说明变量、过程和函数是“全局的”或“外部的”。
这二条伪指令的具体用法和含义如下:
1、伪指令PUBLIC
伪指令PUBLIC是用来说明:当前模块中哪些标识符是能被其它模块引用的公共标识符。其说明的一般格式如下:
PUBLIC 标识符1, 标识符2, ……
其中:“标识符”可以是变量名、过程名和程序标号,各标识符之间要用逗号分开。
上面说明语句说明了标识符1、标识符2等是公共标识符,可以被其它模块引用。在一个模块中,可用多条PUBLIC伪指令来说明公共标识符。
2、伪指令EXTRN
伪指令EXTRN是用来说明:在当前模块所使用的标识符中,哪些标识符是已在其它模块中被定义为指定类型的标识符。如果当前模块使用了其它模块的标识符,而对它又不加以说明的话,那么,在汇编时,汇编程序将会给出下列出错信息:
error nnnnn: undefined symbol : XXXXXX
其中:“nnnnn”是错误号,“XXXXXX”是当前模块中没有定义的标识符。
伪指令EXTRN的一般说明格式如下:
EXTRN 标识符1:类型1, 标识符2:类型2, ……
其中:“标识符”和“类型”之间要用冒号“:”连接。
上面语句说明了标识符1、标识符2等是外部标识符,它们在其它模块中已被分别定义为类型1、类型2等,该类型说明符可以是:NEAR、FAR、BYTE、WORD、DWORD等之一。如果在一条说明伪指令中说明了多个标识符,那么,各标识符之间要用逗号分开。
在一个模块中,可用多条EXTRN伪指令来说明本模块所引用的外部标识符。
注意:伪指令EXTRN中所说明的标识符必须在其定义的模块中被PUBLIC伪指令说明为公共标识符,并且其说明的标识符类型要与该标识符在定义是的类型相一致,否则,要么不能生成其可执行文件,要么其执行文件不能正确运行。
例7.7 把例7.3、7.4和7.5合并在一起生成一个可执行文件,假设它们所对应的源程序名分别为Count.ASM、DispBX.ASM和Main.ASM。
解:由于在源文件Count.ASM中调用了子程序UPPER,所以,例7.1的程序也必须加入到本题中。假设其源文件名为Upper.ASM。
由于生成本题的执行文件需要四个模块,模块之间存在着调用关系,所以,在有关源文件中需要说明某些标识符为外部属性,或说明其为公共属性。
为了把前面例子中的子程序改写成可汇编的程序,需要添加一些简单的说明语句或进行简单修改,其添加或改写的部分已在下面用“下划线”表示出来。
|
;源文件Upper.ASM |
|||
;子程序说明信息:…… |
||||
PUBLIC |
UPPER |
|||
SegUpr |
SEGMENT 'code' |
|||
UPPER |
PROC FAR |
|||
…… |
;例7.1中的程序段,在此从略 |
|||
UPPER |
ENDP |
|||
SegUpr |
ENDS |
|||
END |
||||
;源文件DispBX.ASM ;子程序说明信息:…… |
||||
PUBLIC |
DISPBX |
|||
SubData |
SEGMENT |
|||
DB |
5 DUP('0'), 0ah, 0dh, '$' |
|||
SubData |
ENDS |
|||
SegDisp |
SEGMENT 'code' |
|||
DISPBX |
PROC FAR |
|||
…… |
;例7.3中的程序段,在此从略 |
|||
DISPBX |
ENDP |
|||
SegDisp |
ENDS |
|||
END |
||||
;源文件Count.ASM ;子程序说明信息:…… |
||||
PUBLIC |
COUNT |
|||
EXTRN |
UPPER:FAR |
|||
SegCount |
SEGMENT 'code' |
|||
COUNT |
PROC FAR |
|||
…… |
;例7.4中的程序段,在此从略 |
|||
COUNT |
ENDP |
|||
SegCount |
ENDS |
|||
END |
||||
;源文件Main.ASM |
||||
EXTRN |
COUNT:FAR, DISPBX:FAR |
|||
.MODEL |
SMALL |
|||
.DATA |
||||
|
STR |
DB 'KSDJ L0984/[]3oiu OIU OIU (*&(5341', 0 |
||
.CODE |
||||
|
.STARTUP |
|||
LEA |
DX, STR |
|||
CALL |
COUNT |
;调用子程序统计出各类字符的个数 |
||
CALL |
DISPBX |
;调用子程序显示数字字符的个数 |
||
MOV |
BX, CX |
|||
CALL |
DISPBX |
;调用子程序显示字母的个数 |
||
MOV |
BX, DI |
|||
CALL |
DISPBX |
;调用子程序显示其它字符的个数 |
||
.EXIT |
0 |
|||
END |
经过以上改写后,可用下列命令把它们分别汇编成目标文件(假设已安装了MASM编程环境):
…>MASM upper
…>MASM dispbx
…>MASM count
…>MASM main
有了这些目标文件后,可用以下二种方法来生成可执行文件。
方法1:把所有的目标文件连接在一起
…>link main upper count dispbx
方法2:把目标文件upper.obj、count.obj和dispbx.obj加到自己开发的库文件中,然后在连接时,与该库文件连接。
…>lib mylib upper count dispbx
…>link main
Microsoft (R) Segmented Executable Linker Version 5.31.009 Jul 13 1992
Copyright (C) Microsoft Corp 1984-1992. All rights reserved.
Run File [main.exe]:
List File [nul.map]:
Libraries [.lib]: mylib ;输入要连接的库文件,可用加号“ ”连接多个库文件
Definitions File [nul.def]:
LINK : warning L4021: no stack segment
…>main ;运行生成的文件
以上各步骤也可由集成开发环境PWB来完成,具体介绍请见附录1。另外,当模块的指令条数较少时,也可以把几个子模块合在一个源文件中。