1、CompanyLOGO第七章第七章第七章第七章 汇编语言与汇编语言与汇编语言与汇编语言与C/C+C/C+混合编程混合编程混合编程混合编程电子工业出版社第七章第七章第七章第七章 汇编语言与汇编语言与汇编语言与汇编语言与C/C+C/C+混合编程混合编程混合编程混合编程7.1混合编程17.2C/C+的嵌入式汇编27.3C/C+调用汇编模块37.1 7.1 混合编程混合编程混合编程混合编程 混合编程即由高级语言来调用或嵌入汇编语言子程序,或用汇编语言调用或嵌入高级语言子程序。有两种方法可以实现汇编语言与C/C+语言的混合程序设计。(1)在CC+语言中直接嵌入汇编语言语句,即嵌人式汇编。这种方法比较简洁
2、直观,但功能较弱,此外,由于在其CC+程序中嵌入一段汇编语言程序段,会降低该程序的可移植性。(2)另一种方法是,两种语言分别编写独立的程序模块,分别产生目标代码OBJ文件,然后进行连接,形成一个完整的程序,这种方法使用灵活、功能强。7.1 7.1 混合编程混合编程混合编程混合编程高级语言与汇编语言的接口必须解决两个关键问题:(1)是调用者和被调用者之间的程序控制权问题。(2)参数传递问题,利用寄存器、存储器和堆栈传递参数。7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编 1嵌入方式在C/C+中,嵌入汇编语言指令是在汇编语句前加一个_asm关键字(asm前面是两个
3、下划线),格式如下:格式1:_asm操作码操作数格式2:_asm汇编指令1汇编指令2汇编指令n7.2.1 在在C/C+程序嵌入汇编语句程序嵌入汇编语句 7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编例:要嵌入movax,01h和int10h两条汇编语句,可以有如下三种方式:方式1:_asm/成组嵌入movax,01hint10h方式2:_asmmovax,01h/逐条嵌入_asmint10h方式3:_asmmovax,01h_asmint10h/在一行中嵌入多条7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编因此,在嵌入多条汇编
4、指令时,通常采用格式2。如若要嵌入一组汇编语句,通常采用如下方式:_asm/实现整型变量x和y之值的交换movax,xxchgax,ymovx,ax7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-1】在C语言程序中嵌入汇编语句,实现赋值SUM=A+B+C。其中:A、B、C及SUM均为16位整型变量。#include#includemain()shorta,b,c,sum;/变量A、B、C及SUM均为16位整型变量a=10;b=20;c=30;7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编_asm/实现16位整型变量相加S
5、UM=A+B+Cmovax,aaddax,baddax,cmovsum,axprintf(“SUM=%d”,sum);7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-2】在C语言程序中嵌入汇编语句,实现赋值SUM=A+B+C。其中:A、B、C及SUM均为32位整型变量。#include#includemain()inta,b,c,sum;/变量A、B、C及SUM均为32位整型变量a=10;b=20;c=30;7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编_asm/实现32位整型变量相加SUM=A+B+Cmoveax,aa
6、ddeax,baddeax,cmovsum,eaxprintf(“SUM=%d”,sum);7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编2约定和限制嵌入式汇编代码可以使用汇编表达式,这个表达式是操作数和操作符的组合,产生一个数值或地址。嵌入式汇编语言语句中,可以使用汇编语言格式表示整数常量(如378h),也可以采用C+的格式(如0 x378)。嵌入式汇编语言语句中,注释可以使用C注释风格(如/*/和/),也可以使用汇编语言的注释风格。嵌入式汇编语句不能使用C的专用操作符,如、+、-等。对两种语言都有的操作符,在汇编语句中作为汇编语言操作符,如*,等。在C语言
7、中,表示数组的某个元素,而在汇编语言中,表示字节偏移量,其意义是不一样的。7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编例:intarray6;/下面两条意义不同array6=0;/将0存储在array+24_asmmovarray6,ebx/将ebx的值存储在array+6/下面两条意义相同array6=0;/将0存储在array+24_asmmovarray6*TYPEint,ebx/将ebx的值存储在array+247.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编嵌人式汇编代码不支持汇编伪指令定义的数据(如DB、DW、DD
8、、DT、DF、DUP、THIS等定义的操作数)。在嵌人式汇编代码中,不能使用汇编的结构和记录(如STRUCT、RECORD、WIDTH及MASK等),也不能使用宏伪指令(如MACRO,ENDM,REPEATFORFORC等)和宏操作符(如!,&,等)。虽然嵌入式汇编不支持大部分汇编伪指令,但它支持EVEN和ALIGN。这些指令将NOP指令放在汇编代码中以便对齐边界。对有些处理器来说,这样可以更有效地读取指令。7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编嵌入式汇编引用段时只能通过寄存器而不能通过段名,段超越时,必须明确地用段寄存器来说明。例如:MOVAX,ES
9、:EBX在用汇编语言编写的函数中,不必保存EAX,EBX,ECX,EDX,ESl和EDI寄存器;但必须保存函数中使用的其他寄存器(如DS,SS,ESP,EBP和整数标志寄存器),例如用STD和CLD改变方向标志位,就必须保存标志寄存器的值。嵌入式汇编支持80X86的全部指令系统。对于还不能支持的指令,VC提供了_emit伪指令用于机器指令(以字节为单位)的扩展。格式:_asm_emit7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编1使用C程序的变量在嵌入式汇编语句中,可以使用C程序中的变量或常量。【例7-3】获取C变量和类型的大小#include#includ
10、emain()intarray8;inta,b,c;_asmmoveax,LENGTHarraymovebx,TYPEarray0movecx,SIZEarray7.2.2 在嵌入式汇编中访问在嵌入式汇编中访问C/C+的数据的数据 7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编mova,eaxmovb,ebxmovc,ecxprintf(LENGTH=%dTYPE=%dSIZE=%d,a,b,c);getchar();7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编程序运行显示的结果为:LENGTH=8TYPE=4SIZE=32
11、从上面例子可以看出,对于一个C语言中的整型数组intarray8来说,数组共有8个int元素,由于int类型是32位,占4个字节,则有:LENGTHarray返回值为8(相当于C的sizeof(array)sizeof(array0);TYPEarray返回值为4(相当于C的sizeof(array0);SIZEarray返回值为32(相当于C的sizeof(array);7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-4】实现对array数组元素自动求和main()intarray=1,13,5,10,-1,9,4,2,-21,32;intsum;_a
12、sm/实现对array数组元素求和movecx,LENGTHarray/用LENGTH操作符获取数组元素的个数moveax,0movesi,0next:7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编addeax,arrayesiaddesi,4loopnextmovsum,eaxprintf(sum=%d,sum);/打印汇编代码的求和结果getchar();7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编2标号的使用标号在两种语言中都用来标识程序语句的位置,汇编语句可以转到C程序的标号位置,C程序也能转到汇编程序的标号位置。需
13、要特别注意的是:C程序是大小写敏感的,而汇编则对大小写不加区分。例:voidfunc(void)gotoC_Dest;/正确gotoc_dest;/错误gotoA_Dest;/正确gotoa_dest;/正确7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编_asmjmpC_Dest;正确jmpc_dest;错误jmpA_Dest;正确jmpa_dest;正确a_dest:;汇编标号C_Dest:/C标号return;7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编3结构成员的引用嵌入式汇编语句可以方便地访问C语言结构中的某个成员,
14、通常有两种引用方法。(1)通过变量名引用,即采用结构变量名加成员名的方法:结构变量名.成员名(2)通过变量地址引用,即把结构变量的首地址送往某一地址寄存器,然后用该寄存器名(加方括号)再加成员名,中间用圆点隔开。地址寄存器.成员名7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编例:structscoreinta;intb;intc;)s1,s2;example()asmmoveax,s1.a/取结构变量s1的成员a7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编asmmoveax,s2.c/取结构变量s2的成员casmmovebx
15、,offsetsl/取结构变量s1的主存地址asmmovecx,ebx.b/取结构变量s1的成员b如果类、结构、联合的成员名字惟一,可不说明变量或类型名就可以引用成员名,否者必须说明。7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编4使用C语言的宏指令用C/C+宏可以方便地将一段汇编代码插入到源程序中。书写具有嵌入汇编的C/C+宏时,应遵循下列规则:将汇编程序段放在括号中,每一个汇编语言指令前必须有_asm标志,应该使用C的注释风格(/*/),不要使用单行注释(/)和汇编语言的分号注释方式。例:#definePORTIO_asm/*端口输出*/_asmmovdx
16、,0 xD007_asmoutal,dx宏展开为:_asm/*端口输出*/_asmmovdx,0 xD007_asmoutal,dx7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编利用嵌入式汇编可以方便地编写C程序中的函数,函数的定义和函数调用与C程序相同,只是在函数体内嵌入汇编语言程序段。【例7-5】用嵌入式汇编编写C函数#includeintpower2(intnum,intpower);voidmain(void)printf(2的5次方乘以3等于:%dn,power2(3,5);/显示函数返回值getchar();7.2.3 用汇编程序段编写用汇编程序段
17、编写C函数函数 7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编intpower2(intnum,intpower)_asmmoveax,num;第一个参数3送eaxmovecx,power;第二个参数5送ecxshleax,cl;eax左移5次,EAX=3*25/*寄存器EAX的内容作为函数的默认返回值*/该程序运行后显示结果如下:2的5次方乘以3等于:967.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-6】用嵌入汇编方式实现取两数较小值的函数MIN。#includeintMIN(intVAR1,intVAR2)/嵌人汇
18、编实现求较小值intmin;_asmmoveax,VAR1/第一个参数VAR1送eaxcmpeax,VAR2/比较第一个参数VAR1与第二个参数VAR2jgemaxexitmoveax,ymovmin,eax7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编minexit:movmin,eax/将寄存器eax的内容赋值给变量minreturn(min);/将变量min的内容作为函数的返回值voidmain()printf(max=%dn,MIN(100,200);/显示比较结果getchar();7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编
19、的嵌入式汇编1参数传递汇编程序向C函数传递参数的方法是通过堆栈。由于被调用的C函数是从栈顶访问参数,所以在汇编程序中参数的压栈顺序要与C函数的参数顺序相反。比如汇编程序希望把参数a、b、c依次传送给C函数的三个形式参数x、y、z。则汇编程序的压栈顺序应为c、b、a。在汇编语言程序调用C函数完成后,应该立即平衡堆栈,即清除堆栈里的参数,恢复堆栈到调用前的情形,通常我们可以利用一组POP指令来完成堆栈的平衡。7.2.4 在嵌入式汇编中调用在嵌入式汇编中调用C/C+函数函数 7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-7】汇编代码传递参数给C函数的压栈次序
20、c_func(intx,inty,intz)/C函数c_func的参数次序为x、y、z_asm/调用C函数c_func(a,b,c)moveax,c/按c、b、a的次序压栈,将a、b、c依次传送给参数x、y、zpusheaxmoveax,bpusheax7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编moveax,apusheaxcallc_func/调用C函数c_funcpopebx/平衡堆栈,恢复堆栈到调用前的情形popebxpopebx7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-8】汇编代码按值和按址传递参数给C
21、函数#include#includeintx;charst180;voiddisplay(intx,char*s)/显示整数和字符串printf(%dn,x);printf(%sn,s);getchar();7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编voidmain()x=3;strcpy(st1,hello,cprogram);_asmmoveax,offsetst1/传送变量的地址pusheaxmoveax,x/传送变量的值pusheaxcalldisplay/调用C函数displaypopebxpopebx7.2 7.2 C/C+C/C+的嵌入式汇编
22、的嵌入式汇编的嵌入式汇编的嵌入式汇编2使用C语言函数的返回值若C函数需要向汇编语言程序送返回值,则C语言函数体必须用RETURN返回。返回值的传递约定同前所述,即:对于小于等于32位的数据扩展为32位,存放在EAX寄存器中返回,58字节的返回值存放在EDX:EAX中返回;更大字节数据则将它们的地址指针存放在EAX中返回。7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编【例7-9】调用带返回值的函数#include#includeintgetmax(intx,inty)/比较两个整数的大小,返回较大的整数intmax;if(x=y)max=x;elsemax=y;
23、returnmax;7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编voidmain()intx,y,m;x=20;y=50;_asmmoveax,y/传递参数pusheaxmoveax,xpusheaxcallgetmax/调用C函数getmax,返回值默认保存在EAX寄存器中7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编movm,eaxpopebxpopebxprintf(max=%d,m);getchar();7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编3调用C的库函数因为C的所有的标准
24、头文件都采用extern“C”说明库函数,并且已经通过头包含文件“include”加入到C/C+的源程序中,所以C/C+程序中的嵌入式汇编也可以调用C的库函数。【例7-10】调用C的库函数printf,实现printf(%s%sn,Hello,World)的功能程序如下:#includecharformat=%s%sn;charhello=Hello;charworld=World;voidmain()7.2 7.2 C/C+C/C+的嵌入式汇编的嵌入式汇编的嵌入式汇编的嵌入式汇编_asmmoveax,offsetchina/利用堆栈为printf函数传递参数pusheaxmoveax,off
25、sethellopusheaxmoveax,offsetformatpusheaxcallprintf/调用C的库函数printf(format,hello,world)popebx/清除压入的参数,恢复调用前的堆栈内容popebxpopebx7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块 采用模块调用方法进行混合编程一般执行的步骤是,首先建立C+源程序(.cpp)和汇编源程序并把汇编程序编译成.obj文件;然后将编译后的汇编文件和C+源程序放入建立号的C+工程项目中;最后对工程文件进行编译、连接,生成可执行文件。1名字约定C语言是大小写敏感的,它的外部名可大
26、小写混合使用,每个外部名隐含的使用1个下划线做前缀,因而外部名在汇编语言程序中要用下划线做前缀。例如,C语言可用下列调用语句:MyProc(inta,intb)相应汇编过程的名字则为_MyProc。7.3.1 接口接口 7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块2调用规范C/C+与汇编语言混合编程的参数传递通常利用堆栈,调用规范决定利用堆栈的方法和命名约定。VC提供了三种调用规范:_cdecl,_stdcall和_fastcall。其中_cdecl是VC采用的默认调用规范。它在名字前自动加一个下划线,从右到左将实参压人堆栈,由调用程序进行堆栈的平衡。7.3
27、 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块3声明函数和变量汇编程序中供外部调用的标识符应具有PUBLIC属性,例如:PUBLICasmproc;说明汇编过程asmproc可供外部调用.codeasmprocproc;定义asmproc过程ret;返回,结果在EAX中asmprocendp7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块为了使C/C+函数对汇编语言程序可见,汇编语言程序需要对所调用的C函数、变量用关键字EXFERN进行说明,形式如下:EXTERN被调用函数名EXTERN变量名:变量属性VC数据类型MASM数据类型VC
28、数据类型MASM数据类型字节数unsigned charbytecharsbyte1unsigned shortwordshortsword2unsigned long intdwordlong intsdword4floatreal44doublereal88long doublereal1010表7-1VC与MASM数据类型对应关系7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块在C/C+语言程序中,采用extern“C”对所要调用的外部过程、函数、变量予以说明,说明形式如下:extern“C”返回值类型,调用规范,函数名(参数类型表);extern“C”变
29、量类型变量名;例:shorti,array10;charch;intresult;在汇编语言程序中,应说明为:EXTERNi:word,arrray:word,ch:sbyte,result:dword7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块4参数的传递原则C/C+程序调用汇编程序时,参数是通过堆栈传给汇编程序的。例:如在C/C+程序中说明了一个函数(用汇编程序写成):voidabc(char*p1,intp2)。假设是在小内存模式下进行编译的,当在C/C+程序中调用它时,如写成abc(&ch,num),则首先将num压入堆栈,接着将&ch压入堆栈,当汇
30、编语言子程序要取得C/C+程序中传递来的参数时,便用BP寄存器作为基址寄存器,用它加上不同的偏移量来对栈所存数据进行存取操作,由于一般C/C+程序和调用的子程序共用一个堆栈,因此在汇编语言子程序中开始必须执行两条指令,即:pushbpmovbp,sp7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块C/C+程序传送参数到堆栈中是以和其它语言相反的顺序进行的。例:ADDS(NUM1,NUM2);该语句先使NUM2,后使NUM1进栈,就按次序并调用ADDS。在从被调用模块返回时,C/C+模块(不是汇编模块)使SP增量去丢弃传送的参数。在被调用的汇编模块中,用于访问两个
31、传送参数的典型过程如下:pushbpmovbp,spmovdh,bp+4movdl,bp+6popbpret7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块在push bp指令之后,堆栈的情况如图7-1所示:调用程序返回地址原来的bp值NUM1NUM2bp+0bp+2bp+4bp+6图7-1 堆栈情况7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块5参数及返回值约定参数传递分传递值及传递指针两种情况。(1)参数值直接入栈(2)参数的地址压入栈。在C/C+浯言中,不论采用何种调用规范,除了数组变量传递指针外,其它都是“传值”,参数“
32、传址”应利用指针数据类型。当然还可用“&变量”表示变量的地址,用“*指针变量”表示值。7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块调用步骤如下:将汇编语言过程汇编为符合COFF的obj文件;在VC编译环境下创建一个项目将汇编过程的obj文件插入到VC的项目中编译连接该项目,生成可执行文件7.3.2 调用汇编模块调用汇编模块 7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块【例7-11】VC下调用汇编过程示例;汇编源程序文件名:hbgc.asm;模块名:fun;入口参数:num:dword,power:dword;模块功能:计算
33、num/(2power),返回值放在EAX寄存器中.386P.modelflat,cpublicfun.codefunprocnum:dword,power:dword;定义过程funmoveax,num;第一个参数num送eax7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块movecx,power;第二个参数power送ecxshreax,cl;eax左移5次,EAX=;num/(2power)ret;寄存器EAX的内容作为返;回值funendpend用以下命令对hbgc.asm进行汇编:ML/c/coffhbgc.asm得到名为hbgc.obj的目标文件。
34、7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块VC环境下具体调用步骤如下:在VC编译环境下创建一个项目cgc,并插入cgc.cpp源文件将汇编过程的hbgc.obj目标文件插入到VC的项目中对该项目编译连接,生成可执行文件cgc.exe执行cgc.exe该程序运行后显示的结果如下:16/(23)=27.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块【例7-12】假设有C+主程序MSORT.CPP实现从键盘输入任意多个4位十进制整数(先输入整数的个数),然后调用汇编过程对这些整数进行升序排列后返回主程序,最后再由主程序输出排序后的整
35、数。定义1个数组b100及1个整型变量a,它们都作为参数传递给汇编过程,本利的参数传递通过堆栈来实现。MSORT.CPP的程序如下:/C+源程序文件名:msort.cpp/使用外部过程cprotc,汇编目标文件名为:sort.obj#includeexternCintcprotc(int*,int);voidmain()7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块inta,i,b100;printf(pleaseinputa=n);scanf(%d,&a);for(i=0;i=a-1;i+)scanf(%d,&bi);cprotc(b,a);for(i=0;
36、i=a-1;i+)printf(%d,bi);getchar();7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块汇编源程序如下:;汇编源程序文件名:sort.asm;模块名:cprotc;入口参数:a:dword(值参),b:dword(地址参数);模块功能:对以b为始址,数组元素个数为a的整型数组按升序排序.386P.modelflat,cPUBLICcprotc.codecprotcprocla0:pushebpmovebp,espsubesp,4pushesi7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块movebx,e
37、bp+8;取参数b,得数组b的始址movecx,ebp+12;取参数asorta:movesi,0movdwordptrebp-4,0;局部参数”0”dececx;元素个数减”1”为循环次数jcxzfinishcomp:moveax,ebx+esicmpeax,ebx+esi+4;比较jleincs;小于等于,转incsxchgeax,ebx+esi+4;否则交换movebx+esi,eaxmovdwordptrebp-4,1;局部参数置”1”7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块incs:addesi,4loopcomptestdwordptrebp
38、-4,1;测试局部参数是否为”0”jzfinish;是”0”,转结束shresi,1;除以4为下次元素个数shresi,1movecx,esijmpsortafinish:popesimovesp,ebppopebpretcprotcendpend7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块/C+源程序文件名:cgc.cpp/使用外部过程fun,汇编目标文件名为:hbgc.obj#includeextern”C”intfun(int,int);voidmain()intnum,power;num=16;power=3;printf(%d/(2%d)=%dn,
39、num,power,fun(num,power);/显示结果7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块汇编过程的源文件为SORT.ASM,采用冒包排序法,并使用1个局部变量BP-4作为交换标志,控制是否继续外层循环。运行的结果放在主程序提供的数组中,数组b的始址作为指针参数传到堆栈中,数组的元素个数a为值参,也传到堆栈中。VC在调用外部过程时,将参数按自右至左的次序压入堆栈,最后再压入指令指针EIP,即先压入a再压入参数b,最后是EIP,C程序调用汇编过程后的堆栈情况如图7-2(a)所示。7.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块
40、调用汇编模块aEIPb a.C调用汇编模块后ESPaEIPEBP交换标志ESIb b.进入汇编模块ESPEBPc.汇编模块返回后ESP图7-2 C调用汇编模块cprotc(b,a)的堆栈情况EBP+8EBP+127.3 7.3 C/C+C/C+调用汇编模块调用汇编模块调用汇编模块调用汇编模块进入汇编过程后,汇编过程将EBP和EIP寄存器的内容压栈保存,并为交换标志预留4个字节,堆栈变化情况如图7-2(b)所示。显然,参数a的地址为EBP+12,占4个字节,数组b的始址的存放地址为EBP+8,占4个字节。交换标志的地址为EBP+8。汇编过程返回后,堆栈必须恢复,其中EBP和EIP寄存器通过POP指令恢复,而参数a、b及EIP则是通过RET指令自动恢复并返回C程序,此时堆栈恢复为调用前的情况,如图7-2(c)所示。
版权声明:以上文章中所选用的图片及文字来源于网络以及用户投稿,由于未联系到知识产权人或未发现有关知识产权的登记,如有知识产权人并不愿意我们使用,如有侵权请立即联系:2622162128@qq.com ,我们立即下架或删除。
Copyright© 2022-2024 www.wodocx.com ,All Rights Reserved |陕ICP备19002583号-1
陕公网安备 61072602000132号 违法和不良信息举报:0916-4228922