您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > 第12章--汇编语言与高级-语言的连接
第12章汇编语言与高级语言的连接第12章汇编语言与高级语言的连接12.1BASIC程序对汇编语言子程序的调用12.2C语言和汇编语言的相互调用12.3FORTRAN和PASCAL等对汇编的调用第12章汇编语言与高级语言的连接12.1BASIC程序对汇编语言子程序的调用PC机各种版本的BASIC语言对汇编语言子程序的调用方法是相同的。它们都有实现调用的语句和函数,即CALL语句和USR函数。12.1.1CALL语句这个语句的功能是调用一个机器语言子程序。格式为:CALLnumvar[(Variable[,Variable]···)]第12章汇编语言与高级语言的连接其中numvar是数字变量的名字,这个变量值指明被调用的汇编语言子程序在内存中的入口地址的偏移量,而入口地址的段地址则由语句DEFSEG进行定义。Variable是变量的名字,它是由BASIC语言传送给汇编语言子程序的参数。例如:250DEFSEG=&H5000260LETX=0270CALLX(A,B$,C)第12章汇编语言与高级语言的连接其中250行的DEFSEG语句把子程序装入的段地址设置为5000H;260行中的LET语句,将子程序装入当前段的偏移量赋给X,此处偏移量为o。因此,这个被调用的机器语言:子程序,是从绝对地址50000H单元开始执行的。变量A,B$,C作为传送给这个汇编语言子程序的参数。这个参数是BASIC语言通过堆栈向汇编语言传送的。BASIC语言要调用汇编语言子程序,要做两件事,首先给汇编语言确定在内存中的装入地址的段地址值和段内偏移量值。此外还要向汇编语言子程序通过堆栈传送参数。第12章汇编语言与高级语言的连接利用CALL指令调用汇编语言子程序,有两种方法。1.以数据形式装入汇编语言子程序以BASIC语言的数据形式装入汇编语言子程序的机器代码,它是通过READ和DA-TA语句装入的,然后再使用CALL语句实现调用。第12章汇编语言与高级语言的连接例12.1把指令代码作为BACIC数据读入的程序:10DEFINTA~Z20DEFSEG=&H170030FORI=0TO2140READJ50POKEI,J60NEXT70SUBRT=080A=2:B=3:C=090CALLSUBRT(A,B,C)100PRINTC第12章汇编语言与高级语言的连接110END120DATA&H55,&H8B,SLHEC,81H8B,&H76130DATA&HOA,SLH8B,&H04,&H8B,&H76140DATA&H08,&H03,SIH04,&H8B,&H7E150DATA&H06,&H89,&H05,&HSD,&HCA160DATASLH06,SLH00OKRUN5OK第12章汇编语言与高级语言的连接从120行至160行提供了一个完成两个数相加的子程序,从这个例子中,可以看出这种调用方式的步骤有四点:①逐条地把要调用的汇编语言子程序的指令代码,以十六进制数的形式表示。②将指令代码放在BASIC程序的DATA语句中作为数据。十六进制数前加‘&H’符号。⑧执行一个循环体,用READ语句从DATA数据区中读出数据,用POKE语句将它存放到由DEFSEG语句指定的段地址的单元中。第12章汇编语言与高级语言的连接④定义段内偏移量SUBRT=0,对传送给汇编语子程序的参数赋值,然后用CALL语句进行调用。利用DATA语句和READ语句读入汇编语言子程序的代码和调用该子程序时,受到汇编语言子程序代码长度的限制,当代码很长时,这种方法的程序书写和输入都比较麻烦,且容易出错,指令代码也不便于阅读和记忆。第12章汇编语言与高级语言的连接2.用BLOAD语句读入内存和用CALL语句调用第二种方法是先将汇编语言子程序的机器代码以二进制文件的形式存放在磁盘上,然后用BLOAD语句读入内存,再以CALL语句进行调用。装入内存的段地址由DEFSEG语句指定,而段内偏移量的开始位置则由BLOAD语句给出。其形式为:BLOAD’SUBRT.EXE,,0其中。为段内偏移量的开始值。第12章汇编语言与高级语言的连接例12.2用BLOAD语句装入磁盘文件的方式调用汇编语言子程序。10A%=2:B%=3:C%=020DEFSEG=&H27E030BLOAD,SUBRT.EXE,,040SUBRT=050CALLSUBRT(A%,B%,C%)60PRINTC%70END其中A%,B%,C%为整型变量的表示形式。第12章汇编语言与高级语言的连接例12.3汇编子程序如下:NAMEEX—12—3CSEGSEGMENTASSUMECS:CSEGSUBRTPROCFARPUSHBPMOVBP,SPMOVSI,[BP+10]MOVAX,[SI]MOVSI,[BP+8]第12章汇编语言与高级语言的连接ADDAX,[SI]MOVDI,[BP+6]MOV[DI],AXPOPBPRET6SUBRTENDPCSEGENDSEND第12章汇编语言与高级语言的连接以上程序是实现两个数相加的汇编语言子程序。它是以文件名SUBRT.EXE存放在磁盘上的。这种调用方法的特点是:①BAS℃解释程序将CALL语句解释为以远调用的方式调用汇编语言子程序。②BASIC解释程序在CALLSUBRT(A%,B%,·C%)语句执行时,按A%、B%、C%的次序分别将它们压入堆栈,因此在CALL语句执行完毕时,SP指针向低地址方向移动了10个字节。第12章汇编语言与高级语言的连接③汇编语言子程序的入口处有一条指令PUSHBP,其作用是把BP的值保护起来,以便用指令MOVBP,SP将堆栈指针送至BP中,以BP作为堆栈的基址指针从堆栈中取出参数。例如本例中,变量A%在[BP+10]中;变量B%在[BP+8]中;结果C%应存于[BP+6]单元中,实际上A%、B%、C%在此处是参数的地址。第12章汇编语言与高级语言的连接④在汇编子程序结束前,应用指令POP:BP,恢复BP现场,用RET6(一般情况下为RETn)使BASIC存入堆栈中的参数作废,同时把栈指针调整到调用开始时的位置上。此处的n为参数的个数乘2,例如本例中有3个参数,故n应为6。BASIC堆栈如图12.1所示。第12章汇编语言与高级语言的连接图12.1第12章汇编语言与高级语言的连接12.1.2USR函数这是PC机为BASIC语言调用汇编语言子程序设置的一个函数.它提供了CALI+语句之外的调用汇编语言子程序的一种方法。函数的功能是用自变量调用指定的汇编语言子程序。函数的格式:V=USR[n](arg)第12章汇编语言与高级语言的连接其中n是一位十进制数.它的范围在0~9之间。这个数字是由相应的DEFUSR语句指定的。如果n被缺省掉.就认为是USR0。圆括号中的arg是任意数字表达式或字符串变量.它是汇编语言子程序的变量。例如:20DEFUSR0=&HF00030A=USR0(C/2)40B=USR0(C/3)第12章汇编语言与高级语言的连接例中30行用自变量C/2调用函数USR0。40行用自变量C/3再次调用USR0函数.每调用一次函数USR0.则相应地由USR0函数调用——个汇编语言子程序。20行指定的USR0的值为F000H.它是子程序的入口地址的段内偏移量.段的基地址仍由DEFSEG语句指定。第12章汇编语言与高级语言的连接12.2C语言和汇编语言的相互调用若用C语言来编写程序.不但编程比较容易.而且效率也比较高;而汇编语言不易编写.但它的效率更高.也最适用于直接对计算机硬件进行控制。如果把这两种语言混合起来编程.能够得到最优的程序质量。第12章汇编语言与高级语言的连接从C语言中调用汇编语言子程序的具体方法应该随着C编译程序的不同而有所不同。本节在理论上的阐述是适合于所有的C编译程序的.但所举的例子是使用Microsoft—C编译程序3.0版或4.0版及MASMV5.0宏汇编.它们是PC机上最为流行的C编译和宏汇编。12.2.1汇编语言子程序调用方法1.一个实例C语言主程序名为addl—to—2.汇编语言子程序名为add.asm.主程序调用子程序是为了求l加2的和.并用printf()函数将结果打印出来。第12章汇编语言与高级语言的连接由于C编译程序总是自动地在所定义的函数和变量名前再加一个下划线,例如C语言程序中定义了一个变量abc,则编译完成后这个变量的名字变成了—abc。在汇编语言中如果想引用这个名字时,则也使用名字—ABC。反过来,如果在汇编语言中定义了一个变量名为—XY,则在C语言中引用这个变量时,应该使用变量XY。由于C语言在调用函数名add(1,2)时,汇编语言子程序的名字应为—add,所以过程名在汇编语言中应写成—add。第12章汇编语言与高级语言的连接2.C语言调用汇编语言子程序的规则(1)编写汇编过程的步骤①建立过程;②进入过程;⑧分配局部数据(任选的);④保存寄存器值;⑤存取参数;⑥返回值(任选的);⑦退出过程。第12章汇编语言与高级语言的连接(2)建立过程建立一般的汇编过程用PROC/ENDP伪指令便可以了。在这里,则应将过程名—add用PUBLIC指示符说明为公用的符号。此外,为了使其中的数据为其它模块公用,也应说明为PUBLIC。如果要存取全程的数据,则必须用EXTRN说明。第12章汇编语言与高级语言的连接对于段名的设置有一些专门的规定,这与C语言的内存模式有关,这些模式有小模式、中模式、紧凑模式、大模式和巨模式5种。对于小模式,只产生代码段和数据段两个段,这两个段都被限制在64KB以内。在小模式中,所有的调用都为近(NEAR)调用,所有的指针都是16位指针,对于个别不在代码段的函数,可用关键字FAR来调用。对于个别不在数据段内的数据可以用FAR或HUGE关键字来修正指针。上例是一个小模式下的过程例子。在小模式中,代码段指定用—TEXT段名,且用PUBLIC,CODE,说明,这也是C编译产生的段名,如表12.1所示。第12章汇编语言与高级语言的连接表12.1C编译产生的段名第12章汇编语言与高级语言的连接表12.1中的—DATA、CONST、—BSS、STACK几个段被组合成一个名为DGROUP的组,在正常操作时,DS和SS都指向这个组的起点。此外,这个组的开头还有一个名为NULL的段,这个段用于存放编译程序拷贝数和检测无效指针。如果在程序运行之前和程序运行之后检查NULL段,发现内容已经改变,则说明出现了严重的错误。最常见的错误是程序间接地往0指针写了什么东西。这时会显示“NULLPointerAssignment”信息。显然这个DGROUP组的总字节不能超过64KB。图12.2给出了MicrosohC编译产生的段的存放示意图。第12章汇编语言与高级语言的连接图12.2第12章汇编语言与高级语言的连接(3)进入过程C程序在调用汇编语言子程序前,把要传给被调用函数的参数入栈,且按参数表中的逆顺序把参数压入堆栈。这样,参数表中的第一个参数总是最后一个被压入,因而也就被存在堆栈的顶部。有时,参数表中的第一个参数就是为了说明实际参数的个数有多少,这时就必须把这个数放在堆栈的栈顶处。因为只有这个位置是固定的,取得了这个数以后,也就知道随后有多少个参数。第12章汇编语言与高级语言的连接有些类型的变量是先转换成另一类型后才压入堆栈的。将C中的字符型(char)转换成整型(int);无符号数的字符型(unsignedchar)转换成无符号整型(unsignedint);浮点型的(float)转换成双精度型(double)。结构即structure类型,它是按逆顺序整个压入堆栈的。对于数组,压入堆栈的是指向数组的指针。近指针是16位,远指针是32位,先压入段寄存器值,后压入偏移量。下面的表12.2列出了压入参数时各个参数所占的字节数。第12章汇编语言与高级语言的连接表12.2C程序参数压栈时参数类型及字节数第12章汇编语言与高级语言的连接有了表12.2所给的各类参数在堆栈中所占的字节数,汇编语言子程序就能很方便地取得有关参数。这只要在进入过程后,编写下列两条指令
本文标题:第12章--汇编语言与高级-语言的连接
链接地址:https://www.777doc.com/doc-7598424 .html