第8章 高级汇编技术_第1页
第8章 高级汇编技术_第2页
第8章 高级汇编技术_第3页
第8章 高级汇编技术_第4页
第8章 高级汇编技术_第5页
已阅读5页,还剩86页未读 继续免费阅读

下载本文档

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

文档简介

依第『章富」汇编技术

第3章布被汇编技木

8.1宏汇编

8.2重复汇编和条件汇编

8.3汇编语言与高级语言的混合编程

8.1宏汇编w

8.1.1宏指令的定义、调用和展开

1.宏定义伪指令

宏的概念与过程很相似,也是用一个宏名字来代替源程序中

经常需要用到的一个程序模块(代码段),宏定义语句格式与过程

定义语句格式也相似。

格式:

宏名MACRO[形式参数表]

;;宏体

ENDM;宏定义结束

功能:定义一个宏。

依第』章卷级汇编技术图£

说明:

①宏名必须是惟一的,它代表着所定义的宏体的内容,在

其后面的源程序中,可通过该名字来调用宏。

②形式参数表是用逗号(或空格,或制表符)分隔的一个或

多个形式参数。它是可选项。选用了形式参数时,所定义的宏

称为带参数的宏。当调用宏时,需用对应的实际参数去取代,

以实现向宏中传递信息。

③宏体可以是汇编语言所允许的任意指令和伪指令语句序

列,它决定了宏的功能。在宏体中还可以定义或调用另一个宏,

这就是宏嵌套。

④宏一经定义,就像为指令系统增加了新的指令一样,在

程序中就可像指令一样通过宏名对它进行任意次的调用,故又称

为宏指令或宏调用。要注意的是,宏定义必须放在第一条调用它

的指令之前,一般都将它放在程序的开头。

2.宏的调用与展开

(1)在汇编语言源程序中,为了使在源程序中不重复书写需

要多次使用的程序段,可以用一条宏指令来代替,由汇编程序

在汇编时产生所需要的代码。

例如,为了实现ASCII码与BCD码之间的相互转换,往往需

要把AL中的内容左移4位或右移4位,可以用80x86的指令来实现。

若要左移4位,可用:

MOVCL,4

SALAL,CL

若要多次使用,就可以用一条宏指令来代替,宏定义是:

SHIFTMACRO

MOVCL,4

SALAL,CL

ENDM

这样,以后凡要使AL中的内容左移4位,就可以用这条宏

指令SHIFT来代替。

―二FF-

宏定义中,SHTFT是宏指令名,MACRO是宏定义的定义

符,ENDM是宏定义的结束符,这两者必须成对出现。

宏汇编一般由可执行的指令语句和管理语句(即由伪指令构

成的语句)所构成。经宏定义后,就可以引用宏指令,这称作宏

调用。宏汇编程序遇到这样的调用时,就用对应的宏体来代替

这条宏指令,以产生目的代码,这称作宏展开。

(2)宏定义不但能使源程序的书写简洁,而且由于宏指令具

有接收参量的能力,所以功能就更灵活。

例如,上述的宏指令只能使AL中的内容左移4位。若每次使

用时,要移位的次数不同,或要使不同的寄存器移位,就不方便

了。但是,若在宏定义中引入参量,就可以满足上述要求。

例8・1定义满足不同移位次数要求的宏。

SHIFTMACROX

MOVCL,X

SALCL,CL

ENDM

其中,X是一个形式参量(此处用来代表移位次数)。在调用时可

把实际要求的移位次数作为实在参量代入。如

SHIFT4

就可以用实在参量4代替在宏定义体中出现的形式参量X,从而

实现左移4位的功能。

依第『章富」汇编技术

又如:

SHIFT6

就可以左移6次。这样,就可以由调用时的实在参数来规定任意

的移位次数。

-Jc

£人第8章富像汇编技术血

例8-2定义满足使用不同寄存器实现移位要求的宏,可

入一个形式参量Y。

SHIFTMACROX,Y

MOVCL,X

SALY,CL

ENDM

用形式参量Y来代替需要移位的寄存器。只要在调用时,把要移

位的寄存器作为实在参量代入,就可以对任一个寄存器实现指

定的左移次数。

SHIFT4,AL

SHIFT4,BX

£三第9章富像汇编技术

在汇编这些宏指令时,分别产生以下指令语句,宏汇编

序在每一条由宏展开产生的指令前冠以加号“+”:

+MOVCL,4

+SALAL,CL

+MOVCL,4

+SALBX,CL

+MOVCL,6

+SALDLCL

第一条宏指令使AL左移4位;第二条宏指令使16位寄存器

BX左移4位;第三条宏指令使DI左移6位。

Ml

(3)形式参量不仅可以出现在操作数部分,也可以出现在操

作码部分。

例8-3用宏指令定义操作码。

SHIFTMACROX,Y,Z

MOVCL,X

S&ZY,CL

ENDM

其中第三个形式参量Z代替操作码中的一部分。若在宏定义

体中的形式参量没有适当的分隔符,则不被看作为形式参量,

调用时也不被实在参量所代替。

例如,上例中的操作码部分S&Z中,若Z与S之间没有分隔,

则此处的Z就不被看作形式参量。要定义它为形式参量,必须在

其前面加上符号所以S&Z中Z就被看作是形式参量。若有以

下调用:

SHIFT4,AL,AL

SHIFT6,BX,AR

SHIFT8,SLHR

在汇编这些宏指令时,分别产生以下指令语句。

+MOVCL,4

+SALAL,CL

+MOVCL,6

+SARBX,CL

+MOVCL,8

+SHRSLCL

这里的SHIFT宏指令可以对任一个寄存器进行任意的移位

操作(算术左移、算术右移、逻辑右移、可移任意指定的位数)。

・一一“一JUh一

依第『章富」汇编技术

8.1.2宏操作符

主要的宏操作伪指令有:

1)MACRO

格式:

宏指令名MACRO〈形式参量表>

;宏体

ENDM

心孚章富像汇编技术衣£

宏指令名是-个宏定义调用的依据,也是不同宏定义方

分的标志,是必须要有的。对于宏指令名的规定与对标识符的规

定是一致的。宏定义中的形式参量表是任选的,可以没有形式参

量,也可以有若干形式参量。若有一个以上的形式参量时,它们

之间必须用逗号分隔。对形式参量的规定与对标识符的规定是一

致的。形式参量的个数没有限制,只要一行限制在152个字符以

内就行。在调用时的实在参量多于1个时,也要用逗号分隔,它

们与形式参量在顺序上相对应。但IBM宏汇编并不要求它们在数

量上必须一致。若调用时的实在参量多于形式参量,则多余的部

分被忽略;若实在参量少于形式参量,则多余的形式参量变为

2)PURGE

一个宏指令名,可以用伪指令PURGE来取消,然后就可以重新定义

格式:

PURGE宏指令名

功能:取消多个宏定义。

金晨第『章存秋汇编於术瓶

3)REPT

格式:

REPT〈表达式〉

;指令体

ENDM

功能:重复执行在它的指令体部分所包含的语句。重复执

行的次数,由表达式的值所决定。

依第『章富」汇编技术

例8.4

X=0

REPT10

X=X+1

DBX

ENDM

实现的功能是把1到10分配给10个连续的内存单元。

.;..i^ggsfef

-Jc

4)IRP

格式:

IRP形式参量,〈参数表〉

■:;指令体

ENDM

功能:重复执行指令体部分所包含的语句,重复的次数由

参数表中的参数的个数决定(参数表中的参数必须用两个尖括号

括起来,参数间用逗号分隔),且每重复一次,依次用参数表中

的参数来代替形式参量。

例8£

IRPX,<1,2,3,4,5,6,7,8,9,10>

DBX

ENDM

因为参数表中的参数个数为10,故指令体部分重复执行10

次。例8-4中的指令体部分只有一条伪指令DBX,其中X为形式

参量。在第一次执行时用参数表中的第一个参数1代替形式参量,

就为DB1;第二次执行时,用参数表中的第二个参数2代替形式

参量,就为DB2;……所以例8-4也是把1到10分配给10个连续

的内存单元。

5)IRPC

格式:

IRPC形式参量,字符串(或〈字符串〉)

:;指令体

ENDM

功能:重复执行指令体部分所包含的语句。重复执行的次

数,取决于字符串中的字符个数,每次重复时,依次用字符串

的字符代替形式参量。

IRPC伪指令与IRP伪指令很类似,只是用字符串(此字符串

可以包括在两个三角括号中,也可以不包括)代替了IRP指令中的

参数表。

例8-6

IRPCX,<ABCDEF>

DBX

ENDM

实现的功能是:把字符A到F分配给内存中的6个连续单元。

以上MACRO、REPT、IRP和IRPC4个宏定义的伪指令都

必须以伪指令ENDM作为它的结束符。

有两点需要特别指出:

①宏定义也可以像程序设计语言中的标准函数一样,构成

一个标准函数库,供其他源程序使用。以文件的形式组织若干个

宏定义即形成宏程序库。程序设计中使用了宏程序库中的宏定义

时,在源程序中应使用INCLUDE伪指令。宏汇编程序在汇编源

程序时,当遇到该伪指令,就把INCLUDE伪指令所包含的宏程

序库中的文件扫描一遍,如同在程序中使用自己定义的宏一样,

在后面的程序中就可以对宏库中的宏定义直接进行宏调用了。

②与子程序一样,宏定义也可以嵌套。宏定义的嵌套有两

种方式:宏定义嵌套和宏定义内嵌套宏调用。在一个宏定义中

包含了另一个宏定义,则称为宏定义嵌套;在一个宏定义的宏

体内有宏调用,则称为宏定义内嵌套宏调用。在宏定义内嵌套

宏调用中,被调用的宏指令必须是已定义的。宏定义嵌套常用

于产生一些新的宏定义,而宏定义内嵌套宏调用则可以使宏定

义简化,功能单一,便于通过组合的方法实现一个功能较为复

杂的宏定义。

8.1.3LOCAL伪指令

如果宏定义中含有变量名或标号,且在同一源程序中又多

次被宏调用,那么宏汇编程序在宏展开时,产生多个相同的变

量名或标号,这就不能满足变量名和标号在同一程序中必须惟

一的要求,从而产生汇编出错,即产生uERRORA2005:

SYMBOLISMULTIDEFINED”的错误。为达到在宏定义中使用

变量名和标号,又能避免这个错误的目的,可在宏定义中使用

局部符号伪指令LOCAL对变量名或标号进行说明。

c第『章富」汇编技术

格式:

LOCAL〈符号表〉

功能:对在符号表中的每个符号,在汇编时每扩展一次便

建立一个“??xxxx”惟一的符号,保证汇编时生成名字的惟一

性。

说明:

(1)符号表是在宏定义中定义的变量名和标号,多个符号之

间用逗号分隔。

(2)LOCAL伪指令指定的变量名和标号自动生成格式为

8.1.4宏和过程的比较

宏和过程都可用来简化源程序,并可使程序多次对它们进行

调用,从而使程序结构简洁清晰,符合结构化程序设计风格。

因此,对于那些需重复使用的程序模块,既可用过程也可用宏

来实现。

宏和过程的主要区别在于:

(1)宏操作可以直接传递和接收参数,它不需通过栈等其他

媒介来进行,因此编程比较容易。而过程不能直接带有参数,

当过程之间需要传递参数时,必须通过栈、寄存器或存储器来

进行,所以相对于宏而言,它的编程要复杂一些。

(2)宏调用只能简化源程序的书写,缩短源程序长度,它并

没有缩短目标代码的长度,汇编程序处理宏指令时,是把宏体

插入到宏调用处,所以目标程序占用内存空间并不因宏操作而

减少。而过程(子程序)调用却能缩短目标程序的长度,因为过程

在源程序的目标代码中只有一段,无论主程序调用多少次,除

了增加CALL和RET指令的代码外,并不增加子程序段代码。

(3)引入宏操作并不会在执行目标代码时增加额外的时间开

销。相反,过程调用由于需要保护和恢复现场及断点,因而有

额外的时间开销,会延长目标程序的执行时间。

若在一个源程序中多次调用一段程序,则可用子程序,也

可以用宏指令来简化源程序。用子程序的方法,汇编后产生的

目标代码少,即目标程序占用的内存空间少,节约内存空间。

但是,子程序在执行时,每调用一次都要先保护断点,通常在

程序中还要保护现场。同样,在返回时,先要恢复现场,然后

恢复断点(返回)。这些操作都额外增加了时间,因而执行时间

长,速度慢。而宏指令恰好相反,它的目标程序长,占用的内

存单元多,但在执行时不需要保护断点、现场以及恢复、返回

等这些额外操作,因而执行时间短,速度快。

c第『章富」汇编技术衣£■

所以,当要代替的程序段较短,速度是主要矛盾时,通常

用宏指令。而当要代替的程序段较长,额外操作所附加的时间

不明显,节省存储空间是主要矛盾时,通常用子程序。宏指令

是机器的指令系统中没有的,但又可以作为一条指令使用。所

以,从形式上看,宏指令扩充了机器的指令系统。

8.2重复汇编和条件汇编

8.2.1重复汇编

在汇编程序设计中,经常要连续地重复相同的或几乎完全

相同的代码序列,这时可以使用重复伪指令。

1.重复伪指令

宏汇编语言提供的重复伪指令包括REPT、IRP、IRPC,其

格式、功能及使用说明在8.1.2节中已讲述,这里不再赘述。

2.重复伪指令应用举例

例8・7使用不同重复伪指令定义10个数据,使其内容分别

为0,1,…,9o

第一种方法,使用REPT伪指令:

COUNT=0

REPT10

DBCOUNT

COUNT=COUNT+1

ENDM

第二种方法,使用IRP伪指令:

IRPX,<0,1,2,3,4,5,6,7,8,9>

DBX

ENDM

第三种方法,使用IRPC伪指令:

IRPCX0123456789

DBX

ENDM

依第『章富」汇编技术

以上三种方法具有同样的功能,汇编后产生的代码如下

+DB0

+DB1

+DB2

+DB3

+DB4

+DB5

+DB6

+DB7

+DB8

+DB-9

-Jx

依第『章富」汇编技术

例8-8下面两条重复伪指令具有相同的功能。

(1)IRP指令:

IRPREG,<AX,BX,CX,DX>

POPREG

ENDM

-Jx

依第『章富」汇编技术

(2)IRPC指令:

IRPCRABCD

POPR&X

ENDM

汇编后它们产生的代码如下:

+POPAX

+POPBX

+POPCX

+POPDX

-Jc

8.2.2条件汇编

条件汇编伪指令可使汇编程序根据某种条件对某部分源程

序有选择地进行汇编,在形式上和高级语言中的条件语句类似,

但实质不同。条件汇编语句是一种说明性语句,其功能由汇编

系统实现;而一般高级语言的条件语句是执行性语句,其功能

由目标程序实现。

条件汇编语句通常在宏定义中使用,使得宏定义的适用范

围更广。一般情况下,使用条件汇编语句可使一个源文件产生

几个不同的源程序,它们可有不同的功能。

依第『章富」汇编技术

格式:IF条件

语句序列1

[ELSE

语句序列2]

ENDIF

功能:当条件为真(满足)时执行汇编语句序列1,否则执行

汇编语句序列2。

-Jx

说明:“条件”为IF伪指令说明符的一部分,ELSE伪指令

及其后面的语句序列2是可选择部分,表示条件为假(不满足)时

的情况。如果属于非完全分支的判断,就不用这部分。整个条

件汇编最后必须用ENDIF伪指令来结束。语句序列1和语句序列

2中的语句是任意的,也可为条件汇编语句。

以下5组条件汇编开始语句均可选用ELSE语句,以便汇编条

件为假时执行语句序列2,但一个IF语句只能有一个ELSE与之对

应。

1)是0否条件语句

语句有:IF和IFE。

①IF语句。

格式:IF表达式

功能:表达式值非0,则条件为真,执行汇编语句序列1。

②IFE语句。

格式:IFE表达式

功能:表达式值为0,则条件为真,执行汇编语句序列1。

依第『章富」汇编技术

2)扫描1否条件语句

语句有:IF1和IF2。

①IF1语句。

格式:IF1

功能:汇编处于第一次扫描时条件为真。

②IF2语句。

格式:IF2

功能:汇编处于第二次扫描时条件为真。

.;..i^ggsfef

-Jc

3)符号有定义否条件语句

语句有:IFDEF和IFNDEF。

①IFDEF语句。

格式:IFDEF符号

功能:符号已被定义或已由EXTRN伪指令说明,则条件为真。

②IFNDEF语句。

格式:IFNDEF符号

功能:符号未被定义或未由EXTRN伪指令说明,则条件为真。

4)空否条件语句

语句有:IFB和IFNB。

①IFB语句。

格式:IFBv参数〉

功能:参数为空格,则条件为真。尖括号不能省略。

②IFNB语句

格式:IFNBv参数〉

功能:参数不为空格,则条件为真。尖括号不能省略。

5)字符串比较条件语句

语句有:IFIDN和IFDEF。

①IFIDN语句。

格式:IFIDNv字符串1>,v字符串2>

功能:字符串1与字符串2相同,则条件为真。

②IFDIF语句

格式:IFDIFv字符串1>,〈字符串2>

功能:字符串1与字符串2不相同,则条件为真。

说明:这两条语句只能在宏定义中使用,检查传送给两个

参数的实参是否相同。

例8-9将输入及输出字符的DOS功能调用放在一个宏定义

中,通过判断参数为0还是非0值来选择是执行汇编输入还是输

出的DOS功能。

所编制的程序描述如下,其中含有条件汇编的语句。

INOUTMACROX

IFX

MOVAH,2

INT21H;输出DL中的字符

ELSE

MOVAH,1

INT21H;输入一个字符到AL

ENDIF

ENDM

注:二

当宏调用为INOUTO时,表明传递给参数X的值为0,此时IFX

的条件为假,因此汇编程序只汇编ELSE与ENDIF之间的语句,

这样,对该宏调用来说,实际上是执行下面的两条指令:

MOVAH,1

INT21H

而当宏调用为INOUT1时,实际上是执行这样两条指令:

MOVAH,2

INT21H

8.3汇编语言与高级语言的混合编程

8.3.1调用协议

汇编程序和汇编语言常常以在线汇编语言代码的形式,通过

过程同高级语言,如C/C++、BACIC、PASCAL及FORTRAN一

起使用。需要指出的是,这里尽管讲的是使用Microsoft汇编语言

过程,但只要提供兼容的调用协议,大多数其他语言也能够使用。

在与高级语言接口时,汇编程序使用两种调用协议:一是用

于C/C++语言的C语言调用协议,二是用于BASIC、PASCAL和

FORTRAN语言的PASCAL语言调用协议。调用协议语言在

MODEL语句中或与PROC语句相联系的OPTION指示符中指定。

除用这以外还可以用矣全以短岁旨定O

I.c语言调用协议

C语言调用协议从右到左压入参数,像它们在参数表里放的

那样,带着放在栈上的参数从汇编语言过程返回,返回结果或

者放在AX中或者放在DX:AX中。在BP、DI、SLDS、SS和

方向标志位被改动之前应使用汇编语言过程保存起来。这些寄

存器是高级语言能用到的。图8-1给出了C语言调用协议下近调

用和远调用的栈。

(SP)

(SP)

图8-1使用C语言调用协议时的栈内容

(a)近程调用;(b)远程调用

对栈内参数的访问由C语言调用协议提供,如例8-10所示。

带*号的语句是汇编程序加上的,以保持与C语言调用协议的一

致。注意搞清楚BP的内容如何被压入栈中,以及BP是如何被

装入SP值以访问由C语言程序放在栈中的参数这两个问题。

C第『章富」汇编技术

例8-10

.LISTALL

.MODELSMALL,C

SSSPROTOC,A:SWORD,A:SWORD

.CODE

SSSPROCC,A:SWORD,B:SWORD

PUSHBP;保存BP

MOVBP,SP;栈地址存入BP

MOVAX,A;使用参数A

ADDAX,B;使用参数B

POPBP;恢复BP

RET00000H

SSSENDP

■■•----»♦

一Y带7•提

根据C语言调用协议编写的汇编语言过程通过指令INVOKE

而被调用。INVOKE用来替代标准的CALL指令。INVOKE遵循

C语言调用协议,允许汇编语言程序访问C语言程序和函数。

INVOKE指令被用来访问例8-10中的过程,例如,INVOKESSS,

20,30实现把30加上20后,结果放入AX中并返回。INVOKE与

CALL的不同之处,按照调用协议的要求,INVOKE指令必须将

参数从栈中全部移出。INVOKE指令的语法要求过程名后必须跟

着全部的参数,参数间用逗号隔开。

2.INVOKE指令的使用

用PUSH把参数压入堆栈,如果不小心把参数个数搞错了,

就会使堆栈不平衡,从而使程序从堆栈中取出错误的返回地址,

引起不可预料的后果。所以有必要用一条语句来完成自动检验

的任务。INVOKE语句是能自动将所有的参数压入栈中,并检测

参数个数、类型是否正确,使用CALL来调用的一个宏指令。

INVOKE在汇编程序中调用子程序时,其参数的传递是通过

堆栈来进行的。例如,MessageBox。函数在USER32.INC文件中

是这样声明的:

MESSAGEBOX(HWNDHWND,LPCTSTRLPTEXT,

LPCTSTRLPCAPTION,UINTUTYPE),

在汇编程序中可这样调用它:

PUSHUTYPE

PUSHLPCAPTION

PUSHLPTEXT

PUSHHWND

CALLMessageBox

PUSH为汇编语言中的进栈指令。上面语句的原理是先将函

数所需要的参数,压入到堆栈中去,然后再用CALL指令来调用

该函数。

需要注意的是,在上述的参数进栈过程中,是从左到右依

次压入的,即最右面的参数是最后一个进堆栈,采用的是

PASCAL规则。引入INVOKE语句后,就可自动的将所调用子程

序中的参数压入堆栈中,而无须编程者用手工压入。所以上面

的代码就可以变为

INVOKEMessageBox,NULL,addrszText,addrszCaption,

MBOKo

addr是用来把变量参数的地址传递给被调用的函数(注意,是所

指变量在内存中的地址,而不是变量中的值),它只能在

INVOKE语句中使用。

3.PASCAL语言调用协议

PASCAL语言调用协议用于BASIC、PASCAL和FORTRAN

语言,在WINDOWS中,它也被用于访问WINDOWS库文件

(WINH.LIB)中的函数。PASCAL语言调用协议与C语言调用协议

的差异在于:参数是自左至右压入栈中。如果用在汇编语言过程

中时,PASCAL语言调用协议也需要保存寄存器SI、DLDS和SS

的内容。方向标志位在登录时要被清零,并以清除状态被返回。

和在C语言调用协议中一样,INVOKE语句也用于由汇编语言进

出高级语言过程。

这一点在汇编语言同WINDOWS一起使用时格外重要,以

INVOKEMessageBeep,-1为例,如果WINH.LIB库文件已被程

序装载,则该指令使扬声器发出“嘀”的一声。其他参数也可

与MessageBeep一起使用,从而由WINDOWS发出各种失败提示

音。在C语言程序中,通过在C语言程序的开头使用指令

#INCLUDE<WINDOWS.H>,就可以访问WINDOWS应用程序

接口(API)。

―二FF-

依第『章富」汇编技术

存储器

参数1

参数2

CS(返回地址)

IP(返回地址)

BP(BP)

图8-2使用PASCAL语言调用协议时栈内容

-Jx

图8-2给出了从PASCAL中调用函数时的栈,注意:所有这

些语言调用的函数都被认为是远程调用,BP给出了存储参数的

栈的地址。最右边的参数的地址为BP+6,这一点与C语言调用

协议正好相反。同C语言调用协议一样,隐蔽的指令将BP压入

栈,并将SP写入BP。

第7章富您汇编技术布更

4.数据类型

表8・1各种数据类型的比较

MASM数据类型C语言数据类型PASCAL数据类型

BYTEunsignedchar—

SBYTEchar—

WORDunsignedshortSTRING*1

SWORDshortintINTEGER

DWORDunsignedlong—

SDWORDlongLONG(&)

REAL4floatSINGLE(!)

REAL8doubleDOUBLE(#)

REAL10longdouble

8.3.2与C语言的接口

例8-H本例给出了一个被C语言程序调用的过程,该过程

使用MODEL语句指示内存模型(本例为小模型)和相应的调用协

议语言(C语言)。PROTO语句把本过程作为外部函数声明,并指

定了全部与本过程相关的参数的大小和名称。本过程被作为一

个近程调用

.MODELSMALL,C

XIPROTOC,1:SWORD,F:SWORD

.CODE

C第『章富」汇编技术

XIPROCC,1:SWORD,LSWORD

FILDPI;取出

FADDST,ST(0);计算2Xpi

MOVAX,1;取1

MOVTEMP,AX

FILDTEMP;取1

FMUL;计算2XpiXl

MOVAX,F;取F

MOVTEMP,AX

FILDTEMP;取F

FMUL计算2XpiXlXf

FISTPTEMP保存结黑

依第『章富」汇编技术

MOVAX,TEMP;取结果用以返回C

RET

XIENDP

TEMPDW?;暂存区

END

-Jx

本过程使用数值协处理器计算电抗值,使用公式Xl=2兀1F。

其中,参数F和1从C语言程序中传送到汇编语言过程中,返回值

(XI)作为一个字长的整型变量由AX传回C语言程序。通过BP+4

和BP+6给出的地址,可以从栈中取出1和F的数据。本例中的

MOVAX,1指令,若转换为代码应为MOVAX,[BP+4],通过

该指令可从栈中取出1值。

例8-12本例给出了主模块的C语言调用顺序,该程序喉力

打印出电感系数为4H,频率为1000Hz的电抗值。注意:本程序

中的计算结果被变换为整型。

#include<stdio.h>

externintxl(int1,intf);

voidmainQ

printf(nTheinductivereactanceof4Hat1000Hzis%d\n”,

xl(4,1000));

8.3.3与PASCAL语言的接口

1.有关的PASCAL语句和调用约定

PASCAL语言没有提供CALL调用语句。PASCAL主程序对

汇编语言子程序的调用是通过外部过程和外部函数调用的形式

来实现的。为了保证调用的正确实施,PASCAL主程序和被调

用的汇编语言子程序都要遵从一定的调用约定。PASCAL语言

中的过程和函数有所不同。

1)过程方式

在PASCAL程序中,对要调用的汇编语言过程必须预先采用

PROCEDURE说明语句加以定义说明。PROCEDURE语句的格式

为:

PROCEDURE过程名(参数表):过程属性;

这样,PROCEDURE语句将向PASCAL编译程序提供如下信息:

(1)被调用的过程名;

(2)此过程是内部过程还是外部过程;

(3)过程的参数名和类型;

(4)是“数值参数”还是“引用参数”。

由于汇编语言子程序是单独编写和汇编的,它相对PASE

主程序而言总是外部的。所以,其“过程属性”为EXTERN。

并且,过程名必须在汇编语言程序中用PUBLIC伪指令加以说明。

第(3)项的过程参数名和类型是符合PASCAL要求的变量标识符

和数据类型。在进行PASCAL过程调用时,过程参数也是通过栈

来进行传递的。第(4)项的“数值参数”和“引用参数”涉及到

是传递参数变量值,还是传递参数变量地址的问题。当一个变

量是数值参数时,主程序把此变量的值入栈,即传递给被调用

过程;否则,主程序把此变量的地址入栈。作为引用参数的变

量,在PROCEDURE语句中须用VAR或VARS来加以说明。两者

的区别在于:对由VAR说明的参数,主程序须将其变量地址的

偏移量入栈;而对由VARS说明的参数,除变量地址的偏移量外,

主程序还要将此变量地址的段地址入栈。语句:

PROCEDUREADDP(A,B:INTEGER;VARC:INTEGER):EXTERN;

定义了一个有3个参数的外部过程ADDP。其中,变量A和B是整

型数值参数,而变量C是整型引用参数;一旦汇编语言过程在

PASCAL主程序中经由PROCEDURE语句定义说明后,PASCAL

主程序就可以采用相应的过程调用语句来调用此汇编语言过程了,

过程调用语句的格式为

过程名(参数表)

对上面的ADDP过程,其相应的过程调用语句为

ADDP(A,B,C)

其中,A,B,C是PASCAL主程序中的整型变量。

在被调用的汇编语言子程序中,PASCAL对过程的要求基;

(1)由于寄存器SP不能用于一般的寻址方式,通常用BP来存

取传递的调用参数。所以,在过程程序开始时要先把BP的原有

内容入栈保存,并在返回PASCAL主程序之前恢复内容。另外,

若要在子程序中改变DS和SS等寄存器的内容,也须加以保存和

恢复。

(2)由于是外部过程,在返回PASCAL主程序时应采用长返

回指令,即进行段间返回。

(3)在返回时,应取消栈参数,即主程序传递给此过程的所

有调用参数。

依第『章富」汇编技术

下面是用汇编语言编写的ADDP过程程序,在程序中,

PUBLIC指令将过程名ADDP存放。

CODESEGMENT

ASSUMECS:CODE

ADDPPROCFAR

PUBLICADDP

PUSHBP

MOVBP,SP

PUSHAX

《泉第『章富像汇编技术

PUSHBX

MOVAX,[BP+10]

ADDAX,[BP+8]

MOVBX[BP+6]

MOV[BX],AX

POPBX

POPAX

POPBP

RET6

ADDPENDP

过程的FAR属性使得后面的RET指令成为长返回指令。RET

指令中的整数用于消去栈参数,它在返回后将自动加入到SP寄

存器中。程序的“RET6”指令执行前后栈内容的变化如图8-3所

Zj\O

当ADDP过程的C变量为VARS引用参数时,相应的汇编语

言程序有所不同。由于C的段地址,A和B的地址由[BP+10]和

[BP+8]变为[BP+12]和[BP+10]。同时,“RET6”变为“RET8”。

除此之外,由于C变量不是当前DS寄存器所指数据段中的变量,

对它的存取方式也与前不同,如图8-4所示。

依第『章富」汇编技术

.

r

YVVVYfQD\______—

—A的内容—八八人入入(>JL)xxxxx

Y-B的内容—

6

执行“RET6”

-C的偏移量一_______________________>

I

-返回段地址CS-

(SP)-►—返1可偏移量IP—

图8-3栈变化

-Jxr^S

依第『章富」汇编技术

图8-4C变量为VARS引用参数时的堆栈结构

C第『章富」汇编技术

CODESEGMENT

ASSUMECS:CODE

ADDPPROCFAR

PUBLICADDP

PUSHBP

MOVBP,SP

PUSHAX

PUSHBX

PUSHES

MOVAX,[BP+12]

《泉第『章富像汇编技术

ADDAX,[BP+10]

LESBX,[BP+6]

MOVES:[BX],AX

POPES

POPBX

POPAX

POPBP

RET8

ADDPENDP

CODEENDS

2)函数方式

函数方式同过程方式很相似。在PASCAL程序中,对要调用

的汇编函数也必须预先加以说明。不过,此时采用的是

FUNCTION说明语句,而不是PROCEDURE说明语句。

FUNCTION语句的格式为

FUNCTION函数名(参数表):函数类型;函数属性;

在FUNCTION语句中,除增加了一个“函数类型”外,其余同

PROCEDURE语句一样。“函数类型”符合PASCAL要求的数据

类型的语句。如:

FUNCTIONADDF(A,B:INTEGER):

温馨提示

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

评论

0/150

提交评论