ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:23.50KB ,
资源ID:8430581      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8430581.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(ch11汇编语言与高级语言溷合程序设计.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

ch11汇编语言与高级语言溷合程序设计.docx

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

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

3、C+与汇编语言的混合编程问题。 7.2. 为什么要混合编程?有时为了提高关键代码的执行效率,可以采用汇编语言来实现低层关键代码的功能,如数据采集、定时、调度等,而用C/C+等高级语言来实现高层如数据处理等功能。通过C/C+与汇编语言之间的相互调用,实现汇编语言和高级语言的混合编程,发挥各自语言的优势。这种混合编程的方法优点是提高了关键程序段的执行效率,而其缺点是程序移植性变差。在操作系统软件中,如linux,、uC/OS II等就采用了C/C+与汇编语言的混合编程。操作系统中,一般是低层的硬件相关的代码(任务切换调度、硬件中断、定时中断等)都采用汇编语言实现,这部分与具体硬件相关,也叫平台相关

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

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

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

7、2 函数调用约定要想实现高级语言与汇编语言的混合编程,必须知道这两种语言之间的调用约定。当高级语言函数被编译成机器码时,有一个问题就必须解决:因为CPU没有办法知道一个函数调用需要多少个、什么样的参数。即计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用与者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本身修改堆栈,使堆栈恢复原装。在参数传递中,必须明确说明以下三个方面: 1) 当参数个数多于一个时,按照什么顺序把参数压入

8、堆栈; 2) 函数调用后,由谁来把堆栈恢复原样; 3)调用函数返回值放在什么地方。在高级语言中,通过函数调用约定来说明这个问题。如果定义的约定和使用的约定不一致,则将导致堆栈被破坏,导致严重问题。常见的调用约定有如下5种:1) stdcall -pascal调用约定;2)cdecl -C调用约定;3)fastcall -与stdcall类似,速度更快;4)thiscall -C+类成员函数缺省的调用约定;5)naked call -很少见的调用约定,不建议使用。1. stdcall调用约定stdcall很多时候被称为pascal调用约定,因为pascal是早期很常见的一种教学用计算机程序设计语

9、言,其语法严谨,使用的函数调用约定是stdcall。在Microsoft C+系列的C/C+编译器中,常常用PASCAL宏来声明这个调用约定,类似的宏还有WINAPI和CALLBACK。stdcall是Win32 API函数的调用约定。stdcall调用约定声明的语法为:int _ _stdcall function(int a, int b) /*pascal调用约定*/stdcall的调用约定: 1)参数从右向左压入堆栈; 2)被调用函数自动清理堆栈; 3)函数名自动加前导的下划线,后面紧跟一个符号,其后紧跟着参数的尺寸。以上述这个函数为例,参数b首先被压栈,然后是参数a,函数调用func

10、tion(1,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指向a add eax,ebp + 0CH ;堆栈中ebp + 0CH处保存了b,实现加法功能 mov esp,ebp ;恢复esp pop e

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

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

13、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指向a add eax,ebp + 0CH ;堆栈中ebp + 12处保存了b mov esp,ebp

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

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

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

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

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

19、st,char *src) asm mov si,src /* dest和src是地址指针 */ asm mov di,dest asm cldloop: asm lodsb /* C语言定义的标号 */ asm cmp al,a asm jb copy /* 转移到copy标号 */ asm cmp al,z asm ja copy /* 不是a到z之间的字符原样复制 */ asm sub al,20h /* 是小写字母转换成大写字母 */ copy: asm stosb asm and al,al /* C语言中,字符串用NULL(0)结尾 */ asm jnz loopmain() /*

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

21、!Uppercase String:THIS STARTED OUT AS LOWERCASE!7.5. 独立汇编模块格式模块划分:有的模块用C语言实现,有的模块用汇编语言实现。每个模块源程序(C源程序或汇编源程序)独立编译为.obj目标文件,之后用链接工具把所有的obj整合到一个exe可执行文件。模块之间的调用有两种情况,一种是C调用汇编;另一种是汇编调用C。对于C语言模块调用汇编语言模块中函数(或使用变量)的情况,声明如下:1)在C语言模块中,用extern说明要调用汇编模块中的函数(或使用变量)。其格式如下: extern返回值类型 函数名(参数类型表);extern变量类型 变量名;2

22、)在汇编语言模块中,用PUBLIC声明被C语言模块调用的函数(或使用变量)。其格式如下: PUBLIC _程序标识符(函数名或变量名)对于汇编语言模块调用C语言模块中函数(或使用变量)的情况,声明如下:1)在汇编语言模块中,用extern说明要调用C语言模块中的函数(或使用的变量)。其格式如下: EXTRN _函数名:类型(NEAR ,FAR)EXTRN _变量名:类型(BYTE, WORD,DWORD)2)在C语言模块中,用PUBLIC声明被汇编语言模块调用的函数(或使用的变量)。其格式如下: 函数名 /*在C语言模块中,要求全局可见*/变量名 /*在C语言模块中,要求全局可见*/ 例2:C

23、语言程序模块调用汇编语言子程序模块,显示一段信息/* C语言程序:main.c */extern void display(void); /* 说明display是外部函数 */main() display();汇编语言子程序模块:display.asm .model small,c ;存储模式,采用小型存储模式和C语言类型 .data ;数据段msg db Hello, C and Assembly !,$ .code ;代码段 PUBLIC _display ;外部C模块可以使用本过程_display proc ;采用了一致的命名约定 mov ah,9 ;小型模式只有一个数据段,所以不必设

24、置DS mov dx,offset msg ;寄存器AX和DX无须保护 int 21h ret_display endp end例3:uC/OS II中汇编语言部分。注意本例中函数和变量的定义格式及程序中的使用。;1.全局和外部引用定义部分;1.1本汇编模块中实现的4个函数(C模块会调用下边四个汇编实现的函数) PUBLIC _OSTickISR ;定时中断汇编函数 PUBLIC _OSStartHighRdy ;开始执行最高级任务汇编函数 PUBLIC _OSCtxSw ;任务切换汇编函数 PUBLIC _OSIntCtxSw ;中断中任务切换汇编函数; 1.2 C模块中声明和实现的函数和变

25、量(本汇编模块中要引用它们) EXTRN _OSIntExit:FAR ;函数3个 EXTRN _OSTimeTick:FAR EXTRN _OSTaskSwHook:FAR EXTRN _OSIntNesting:BYTE ;变量7个 EXTRN _OSTickDOSCtr:BYTE EXTRN _OSPrioHighRdy:BYTE EXTRN _OSPrioCur:BYTE EXTRN _OSRunning:BYTE EXTRN _OSTCBCur:DWORD EXTRN _OSTCBHighRdy:DWORD .MODEL LARGE ;存储模式.CODE ;代码开始;2.1开始执行最

26、高级任务汇编函数实现部分_OSStartHighRdy PROC FAR_OSStartHighRdy ENDP;2.2 多任务切换汇编函数实现部分_OSCtxSw PROC FAR PUSHA ;保存当前旧任务环境到堆栈中 PUSH ES PUSH DS MOV AX, SEG _OSTCBCur ; 引用C中声明的变量 MOV DS, AX ; LES BX, DWORD PTR DS:_OSTCBCur ;保存当前旧任务的SS:SP到当前任务的TCB中, OSTCBCur-OSTCBStkPtr = SS:SP MOV ES:BX+2, SS MOV ES:BX+0, SP CALL F

27、AR PTR _OSTaskSwHook ;调用C中函数 MOV AX, WORD PTR DS:_OSTCBHighRdy+2; _OSTCBCur = _OSTCBHighRdy MOV DX, WORD PTR DS:_OSTCBHighRdy MOV WORD PTR DS:_OSTCBCur+2, AX MOV WORD PTR DS:_OSTCBCur, DX MOV AL, BYTE PTR DS:_OSPrioHighRdy MOV BYTE PTR DS:_OSPrioCur, AL LES BX, DWORD PTR DS:_OSTCBHighRdy; 取出新任务的堆栈指针

28、,SS:SP = OSTCBHighRdy-OSTCBStkPtr MOV SS, ES:BX+2 MOV SP, ES:BX POP DS ;弹出新任务的环境 POP ES POPA IRET ;跳到新任务执行_OSCtxSw ENDP其它汇编函数实现略,参考uC/OS II源程序中OS_CPU_A.ASM文件。例4. C模块与汇编模块混合调用 /*main.c模块*/#include extern int maxx(int ,int ); /*引用汇编实现的函数*/int main(int argc, char *argv) int x; _asm mov ah,1 /*嵌入汇编指令,等待

29、键盘输入*/ _asm int 21h x= maxx(8,9); /*调用汇编函数maxx( ) */ printf(%d,x); /*显示返回值*/ return 1;*sub.asm模块*;.MODEL LARGE ;存储模式为large.CODEpublic _maxx ;外部可见函数_maxx_maxx proc far ;_maxx函数实现 push bp mov bp,sp mov ax,bp+6 cmp ax,bp+8 jge exit mov ax,bp+8 exit: pop bp ret_maxx endpEnd7.6. 编译、汇编和连接的方法 步骤一,用MASM汇编ASM语言源程序,生成汇编语言目标文件(.OBJ)。 步骤二,在TURBO C集成环境下建立一个工程文件,该文件包括需要编译连接的C语言源程序和汇编语言目标文件名(.OBJ)。 步骤三,在TURBO C集成环境下,按F9功能键,制作出工程,生成可执行文件(.EXE)。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1