微型计算机技术与汇编语言程序设计:ch11-汇编语言与高级语言混合程序设计.docx

上传人:太** 文档编号:35052952 上传时间:2022-08-20 格式:DOCX 页数:12 大小:26.26KB
返回 下载 相关 举报
微型计算机技术与汇编语言程序设计:ch11-汇编语言与高级语言混合程序设计.docx_第1页
第1页 / 共12页
微型计算机技术与汇编语言程序设计:ch11-汇编语言与高级语言混合程序设计.docx_第2页
第2页 / 共12页
点击查看更多>>
资源描述

《微型计算机技术与汇编语言程序设计:ch11-汇编语言与高级语言混合程序设计.docx》由会员分享,可在线阅读,更多相关《微型计算机技术与汇编语言程序设计:ch11-汇编语言与高级语言混合程序设计.docx(12页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、汇编语言与高级语言混合程序设计本章对汇编语言与C语言混合程序进行设计。主要介绍汇编语言和C语言 的混合编程和调用方法。7.1.汇编语言和高级语言程序设计语言按照功能的不同可以分为3种:机器语言、汇编语言和高级语 言。把机器语言指令以助记符来表示,就成汇编语言指令,汇编语言指令必须用 工具软件翻译(汇编过程)成机器语言指令才能执行,其它高级语言也必须翻译(编 译或解释)为机器语言才能执行。高级语言是独立于机器的通用语言,不依赖于 特定计算机的硬件结构和指令系统。用高级语言写的源程序,可以在不同的计算 机上重新编译(或解释)后运行,而得到相同运行结果。高级语言包括C/C+. Basic Pasca

2、l Java 等。C/C+语言是一种应用广泛,并且实现灵活的一种计算机编程语言,用 C/C+语言编出来的程序,可以在很多平台上运行,可移植性强。C/C+不仅具 有良好的高级语言特征,而且还具有一些低级语言的特点,如:寄存器变量、位 操作等。所以,C/C+语言的程序与汇编语言程序之间能很平滑地衔接。另外, 目前主要的C/C+语言程序开发环境,如:Turbo C/C+ Borland C/C+等,也 都提供了很好的混合编程手段。计算机操作系统等大型软件,一般都采用C/C+语言和汇编语言混合编程来 完成。虽然除了 C/C+以外的其它高级也可以与汇编语言进行混合编程,但下面 我们重点讲述C/C+与汇编

3、语言的混合编程问题。7. 2.为什么要混合编程?有时为了提高关键代码的执行效率,可以采用汇编语言来实现低层关键代 码的功能,如数据采集、定时、调度等,而用C/C+等高级语言来实现高层如数 据处理等功能。通过C/C+与汇编语言之间的相互调用,实现汇编语言和高级语 言的混合编程,发挥各自语言的优势。这种混合编程的方法优点是提高了关键程7. 5,独立汇编模块格式模块划分:有的模块用c语言实现,有的模块用汇编语言实现。每个模块 源程序(C源程序或汇编源程序)独立编译为Qbj目标文件,之后用链接工具把所 有的。用整合到一个exe可执行文件。模块之间的调用有两种情况,一种是C调 用汇编;另一种是汇编调用C

4、o对于C语言模块调用汇编语言模块中函数(或使用变量)的情况,声明如下:1)在C语言模块中,用extern说明要调用汇编模块中的函数(或使用变量)。 其格式如下:extern返回值类型 函数名(参数类型表);extern变量类型变量名;2)在汇编语言模块中,用PUBLIC声明被C语言模块调用的函数(或使用变 量)。其格式如下:PUBLIC 程序标识符(函数名或变量名)对于汇编语言模块调用C语言模块中函数(或使用变量)的情况,声明如下:1)在汇编语言模块中,用extern说明要调用C语言模块中的函数(或使用的变 量)。其格式如下:EXTRN 函数名:类型(NEAR,FAR)EXTRN 变量名:类型

5、(BYTE, WORD,DWORD)2)在C语言模块中,用PUBLIC声明被汇编语言模块调用的函数(或使用的变 量)。其格式如下:函数名/*在C语言模块中,要求全局可见*/变量名/*在C语言模块中,要求全局可见*/例2: C语言程序模块调用汇编语言子程序模块,显示一段信息/* C语言程序:main, c */extern void display (void) ; /* 说明 display 是外部函数 */main () display (););汇编语言子程序模块:display. asm.model small, c ;存储模式,采用小型存储模式和C 语言类型.data ;数据段msg

6、db Hello, C and Assembly,code ;代码段PUBLIC _display ;外部C模块可以使用本过程 _display proc ;采用了一致的命名约定mov ah, 9 ;小型模式只有一个数据段,所以不必设置DS mov dx, offset msg ;寄存器AX和DX无须保护 int 21hret_display endpend例3: uc/osn中汇编语言部分。注意本例中函数和变量的定义格式及程序中的 使用。;1.全局和外部引用定义部分;1.1本汇编模块中实现的4个函数(C模块会调用下边四个汇编实现的函数)PUBLIC _OSTickISR定时中断汇编函数PUB

7、LIC _OSStartHighRdy ;开始执行最高级任务汇编函数PUBLIC _OSCtxSw;任务切换汇编函数PUBLIC _OSIntCtxSw ;中断中任务切换汇编函数;1.2C模块中声明和实现的函数和变量(本汇编模块中要引用它们)EXTRN _OSIntExit:FAR ;函数 3 个EXTRN _OSTimeTick:FAREXTRN _OSTaskSwHook:FAREXTRN _OSIntNesting:BYTE ;变量 7 个EXTRN _OSTickDOSCtr:BYTE EXTRN _OSPrioHighRdy:BYTE EXTRN _OSPrioCur:BYTE EX

8、TRN _OSRunning:BYTE EXTRN _OSTCBCur:DWORD EXTRN _OSTCBHighRdy:DWORD.MODELLARGE ;存储模式,CODE ;代码开始;2.1开始执行最高级任务汇编函数实现部分_OSStartHighRdy PROC FAR _OSStartHighRdy ENDP;2.2多任务切换汇编函数实现部分_OSCtxSw PROC FARPUSHA;保存当前旧任务环境到堆栈中PUSH ESPUSH DSMOV AX, SEG JDSTCBCur ;引用C中声明的变量MOV DS, AX ;LES BX, DWORD PTR DS:_OSTCBC

9、ur ;保存当前旧任务 的 SS: SP 到当前任务的 TCB 中,OSTCBCur-OSTCBStkPtr 二 SS:SPMOV ES:BX+2,SSMOV ES:BX+09SPCALL FAR PTR _OSTaskSwHook ;调用 C 中函数MOV AX, WORD PTR DS:_OSTCBHighRdy+2; _OSTCBCur =_OSTCBHighRdyMOVDX, WORD PTR DS :_OSTCBHighRdyMOVWORD PTR DS:_OSTCBCur+2, AXMOVWORD PTR DS: OSTCBCur, DXMOVAL, BYTE PTR DS:_OS

10、PrioHighRdyMOVBYTE PTR DS:_OSPrioCur, ALLES BX, DWORD PTR DS:_OSTCBHighRdy;取出新任务 的堆栈指针,SS:SP = OSTCBHighRdy-OSTCBStkPtrMOVSS, ES:BX+2MOVSP, ES:BXPOP DS;弹出新任务的环境POP ESPOPAIRET ;跳到新任务执行_OSCtxSw ENDP其它汇编函数实现略,参考uC/OS II源程序中OS_CPU_A.ASM文件。例4. C模块与汇编模块混合调用/*main.c 模块*/#include extern int maxx(int ,int);

11、/*引用汇编实现的函数*/int main(int argc, char *argv)int x; _asm mov ah, 1 /*嵌入汇编指令,等待键盘输入*/_asm int 21hx= maxx(8,9);/*调用汇编函数 maxx() */printf(n%dM,x); /* 显示返回值*/return 1;);*sub.asm 模块*;.MODEL LARGE ;存储模式为 large.CODEpublic _maxx;外部可见函数maxx_maxx proc far ;_maxx 函数实现push bpmov bp,spmov ax,bp+6cmp ax,bp+8jge exit

12、mov ax,bp+8exit: pop bp ret_maxx endpEnd6.编译、汇编和连接的方法步骤一,用MASM汇编ASM语言源程序,生成汇编语言目标文件(.OBJ) 0步骤二,在TURBO C集成环境下建立一个工程文件,该文件包括需要编译连 接的C语言源程序和汇编语言目标文件名(.OBJ) o步骤三,在TURBO C集成环境下,按F9功能键,制作出工程,生成可执行文件(.EXE) o 序段的执行效率,而其缺点是程序移植性变差。在操作系统软件中,如linux,、uC/OS II等就采用了 C/C+与汇编语言的混 合编程。操作系统中,一般是低层的硬件相关的代码(任务切换调度、硬件中断

13、、 定时中断等)都采用汇编语言实现,这部分与具体硬件相关,也叫平台相关的代 码;而高层的服务功能采用C/C+语言来实现,这部分与具体硬件无关,也叫平 台无关的代码。平台相关的汇编语言代码部分是操作系统移植到不同处理器时需 要修改的部分。7. 3.如何混合编程?为了实现一个任务,我们把一个任务按功能划分为很多模块,每个模块以 函数或子程序的形式存在,根据每个模块的特点选用汇编语言或C/C+语言,我 们把它们叫做汇编语言模块或C/C+语言模块。这两种不同语言编写的模块,都 会编译成目标文件(.Obj),最后将多个目标文件连接在一起,形成一个完整的可 执行文件(.exe)。为了完成一个特定任务的多个

14、模块,模块之间不是孤立的。一种情况是, 模块中函数之间可能存在着调用关系,也就是,可能存在着汇编语言模块中的函 数调用另一个C/C+模块中的函数的情况;也可能存在着C/C+模块中的函数调 用汇编语言编写的模块函数的可能。另一种情况是,也可能存在着一个模块引用 另一个模块公共变量的情况。为了不同模块之间调用和引用的正确,要对模块之间的调用和引用进行约 定。汇编语言与C/C+语言混合编程,需要考虑四个方面的约定(规范):(1)存储模式的约定一如何为模块分配内存的约定;(2)函数名称的约定一如何声明函数名称约定;(3)函数调用约定一汇编语言与C语言之间的参数如何传递的约定;(4)编译方法。有两种混合

15、编程方式,一种是嵌入汇编指令的格式;另一种是独立汇编模块格式。7.3.1 存储模式的约定存储模式用于处理程序、数据、堆栈在主存中的分配和存取,决定代码和 数据的默认指针类型,例如段寄存器CS、DS、SS、ES的设置就与所采用的存 储模式有关。存储模式在C语言中也称为编译模式或主存模式。Turbo C提供了六种存储模式,分别是:微型模式(tiny)、小型模式(small)、 紧凑模式(compact)中型模式(medium)、大型模式(large)和巨型模式(huge)。混合编程时必须保持汇编语言和C语言的存储模式一致。在汇编语言中使 用伪指令.model *,表示在汇编语言中采用的存储模式,其

16、中*表示上述6 种模式中的一种。若C采用小模式,则在汇编语言中要使用.model small。7.3.2 函数调用约定要想实现高级语言与汇编语言的混合编程,必须知道这两种语言之间的调 用约定。当高级语言函数被编译成机器码时,有一个问题就必须解决:因为CPU没 有办法知道一个函数调用需要多少个、什么样的参数。即计算机不知道怎么给这 个函数传递参数,传递参数的工作必须由函数调用与者和函数本身来协调。为此, 计算机提供了一种被称为栈的数据结构来支持参数传递。函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后, 在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本 身修改

17、堆栈,使堆栈恢复原装。在参数传递中,必须明确说明以下三个方面:1)当参数个数多于一个时,按照什么顺序把参数压入堆栈;2)函数调用后,由谁来把堆栈恢复原样;3)调用函数返回值放在什么地方。在高级语言中,通过函数调用约定来说明这个问题。如果定义的约定和使 用的约定不一致,则将导致堆栈被破坏,导致严重问题。常见的调用约定有如下5种:1) stdcall-pascal 调用约定;2)cdecl-C调用约定;3)fastcall一与stdcall类似,速度更快;4)thiscallC+类成员函数缺省的调用约定;5)naked call -很少见的调用约定,不建议使用。1. stdcall调用约定stdc

18、all很多时候被称为pascal调用约定,因为pascal是早期很常见的一种教 学用计算机程序设计语言,其语法严谨,使用的函数调用约定是stdcallo在 Microsoft C+系列的C/C+编译器中,常常用PASCAL宏来声明这个调用约定, 类似的宏还有WIN API和CALLBACK o stdcall是Win32 API函数的调用约定。stdcall调用约定声明的语法为:intstdcall function(int a, int b) /*pascal 调用约定*/stdcall的调用约定:1)参数从右向左压入堆栈;2)被调用函数自动清理堆栈;3)函数名自动加前导的下划线,后面紧跟一

19、个符号,其后紧跟着参数的 尺寸。以上述这个函数为例,参数b首先被压栈,然后是参数a,函数调用 function。,2)调用处翻译成汇编语言将变成:push 2;第二个参数入栈push 1;第一个参数入栈call function ;调用函数,自动把cs:eip入栈而对于函数自身开始处,则翻译为:push ebp ;保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针,可以在函数退出时恢复mov ebp,esp;保存堆栈指针mov eax, ebp + 8H;堆栈中ebp指向位置之前依次保存有ebp,cs:eip,a,b, ebp +8指向aaddeax,ebp + OCH;堆栈中ebp + OC

20、H处保存了 b,实现加法功能mov esp,ebp;恢复 esppop ebpret 8;自动恢复堆栈,返回值在eax中。在编译时,函数名被翻译成_function8。注意不同编译器会插入自己的汇编代码以提供编译的通用性,但是大体代 码如此。其中在函数开始处保留esp到ebp中,在函数结束恢复是编译器常用的 方法。从函数调用看,2和1依次被push进堆栈,而在函数中又通过相对于ebp(即 刚进函数时的堆栈指针)的偏移量存取参数。函数结束后,ret 8表示清理8个字 节的堆栈,函数自己恢复了堆栈。_stdcall是在windows程序设计中出现的最多的调用规则,所有的不可变 参数的API调用都使

21、用这个规则。2. cdecl调用约定cdecl调用约定又称为C调用约定,是C语言缺省的调用约定,它的定义语 法是:int function (int a ,int b)/*不加修饰就是C调用约定*/int cdecl function(int a,int b)/* 明确指出 C 调用约定*/cdecl调用约定:1)参数从右向左压入堆栈;2)函数本身不清理堆栈,调用者负责清理堆栈;3)函数名自动加前导的下划线.function。cdecl调用约定的参数压栈顺序是和stdcall是一样的,参数首先由右向左 压入堆栈。所不同的是,函数本身不清理堆栈,调用者负责清理堆栈。由于这种 变化,C调用约定允许

22、函数的参数的个数是不固定的,这也是C语言的一大特色。对于前面的function函数,使用cdecl后的汇编码变成:调用处push 2;第二个参数入栈push 1;第一个参数入栈call function ;调用函数,自动把cs:eip入栈add esp,8;注意:由调用者恢复堆栈被调用函数function处push ebp;保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针mov ebp,esp;保存堆栈指针mov eax, ebp + 8H滩栈中ebp指向位置之前依次保存有ebp,cs:eip,a,b, ebp +8指向aadd eax,ebp + OCH;堆栈中 ebp + 12 处保存了

23、 bmov esp,ebp;恢复 esppop ebpret;注意,这里没有完全恢复堆栈,返回值在eax中。由于参数按照从右向左顺序压栈,因此最开始的参数在最接近栈顶的位置, 因此当采用不定个数参数时,第一个参数在栈中的位置肯定能知道,只要不定的 参数个数能够根据第一个后者后续的明确的参数确定下来,就可以使用不定参 数。cdecl调用约定最大好处在于由于是调用者清理栈,它可以处理可变参数, 缺点则在于它增加了程序的大小,因为在每个调用返回的时候,需要多执行一条 清理栈的指令。3. fastcall调用约定fastcall调用约定和stdcall类似,fastcall调用约定:1)函数的第一个和

24、第二个DWORD参数(或者尺寸更小的)通过ECX和 EDX传递,其他参数通过从右向左的顺序压栈;2)被调用函数自动清理堆栈;3)函数名修改规则同stdcall。其声明语法为:intfastcall function(int a,int b)_fastcall在windows内核设计中被广泛的使用,由于两个参数由寄存器直 接传递,采用这种规则的函数效率要比以上两种规则高。4. thiscall调用约定thiscall是C+成员函数的默认调用约定,编译期间,这种调用会根据函数 是否支持可变参数表来决定采用什么方式清理堆栈。如果成员函数不支持可变 参数,那么它就是用参数入栈,ECX保存this指针的

25、方式进行调用,如果成员 函数支持可变参数,那么它的调用和_/(10小类似,唯一不同的是将this指针最 后压入栈中进行传递。5. 调用函数返回值以上4种调用约定中,返回值保存方式是一样的。被调用函数的返回值, 按下列规则传递给调用者:1)如果返回值小于或等于16位,则将其存放在AX寄存器中;2)如果返回值是32位,则存放在DX, AX寄存器对中,其中DX存储高 16位,AX存储低存位;3)如果返回值大于32位,则存放在静态变量存储区;AX寄存器存放指向这 个存储区的偏移地址;对于32位far指针,则还利用DX存放段地址。由此可见,汇编语言子程序向C程序返回处理结果时,是通过AX和DX 完成的;

26、但对于不同长度的返回数据,使用寄存器的情况也不同。当返回值为 char short、int类型,仅需要使用寄存器AX;当返回值类型为long时,低16位 在AX中,高16位在DX中;而当返回值类型为float、double时,AX传送存储 地址的偏移量;如果是far指针,DX传送段地址,偏移地址仍然在AX中。7. 4.嵌入汇编指令格式嵌入汇编方式把插入的汇编语言语句作为C语言的组成部分,不使用完全独 立的汇编模块,所以比调用汇编子程序更方便、快捷,并且在大存储模式、小存 储模式下都能正常编译通过。C语言程序中含有嵌入式汇编语言语句时,C编译器首先将C代码的源程序 (.c)编译成汇编语言源文件(

27、.asm),然后激活汇编程序Turbo Assembler将产 生的汇编语言源文件编译成目标文件(.obj),最后激活Tlink将目标文件链接成 可执行文件(.exe)0若要在C语言源程序中嵌入一条汇编语句,则用保留了 asm声明,格式如 下:asm mov ax, bx若要在C语言源程序中嵌入一组汇编语句,则需要用括号和下把它们括起 来。asm mov ax, datalmov bx, data2mov data 1, bxmov data2, ax/*实现整型变量datal和data2之值的交换*/)例1:将字符串中的小写字母转变为大写字母显示/*upcase.c */#include v

28、oid upper(char *dest,char *src)asm mov si,src /* dest 和 src 是地址指针 */asm mov di,destasm cldloop: asm lodsb /*C语言定义的标号*/asm cmp al,aasm jb copy /* 转移到 copy 标号 */asm cmp al/z1asmja copy /*不是a至z之间的字符原样复制*/asm sub al920h /*是小写字母转换成大写字母*/copy: asm stosbasm and al,al /*C语言中,字符串用NULL (0)结尾*/asm jnz loop)mai

29、n() /* 主程序 */(char str=nThis Started Out As Lowercase!n;char chr100;upper(chr,str); /* 调用汇编函数*/printf(nOrigin string:n%snH,str);printf(HUppercase String:n%snn,chr);编辑完成后,在命令行输入如下编译命令,选项-I和-L分别指定头文件和库 函数的所在目录:TCC -B -linclude -Llib upcase.c生成可执行文件upcase.exe,程序运行后输出的结果将是:Origin string:This Started Out As Lowercase!Uppercase String:THIS STARTED OUTAS LOWERCASE!

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > 解决方案

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁