
谈论用C程序C语言调用汇编模块的方法是目前非常流行的编程语言. 除了高级语言,方便灵活的使用,强大的数据处理能力,编程简单等优点外,它还可以实现汇编语言. 大多数功能,例如直接在硬件上运行的能力,生成的目标代码的质量都很高,并且执行速度很快. 因此,当工程中的硬件处理速度不是很高时,可以使用C代替汇编语言来编写用于接口电路的控制软件. 但是,C无法完全替代汇编语言. 例如,在一些需要高速和特殊硬件控制的实时控制系统中,C有时并不完全胜任,需要汇编语言来编写. 由于汇编语言目标代码更加简洁,直接控制硬件的能力更强,执行速度更快,但是汇编语言的编程难度很大,表达能力也很明显. 更好的解决方案是将编程与C和汇编语言混合使用,即使用C编写速度要求较低的软件的调度程序,用户界面和控制部分,并使用汇编语言为速度敏感的用户提供最高速度的处理模块. 用于C传输的零件. 这种方法提供了最佳的软件设计解决方案,并同时实现了速度,效率,灵活性和便利性. 由于我的毕业设计要求使用C程序中的汇编模块的方法来提高ARM定点指令的执行速度,因此我研究了这一方面. 学习经验如下: C语言与汇编语言之间的接口有两个主要问题需要解决.

I. 调用方和被调用方参数传输此数据传输是通过堆栈完成的. 执行调用时,它从调用者参数表中的最后一个参数开始,并自动依次推入堆栈;所有参数都被压入堆栈. 之后,被调用程序执行后的返回地址(断点)会自动压入堆栈,以便被调用程序可以返回到调用程序的正确位置,并在被调用程序结束后继续执行. 例如,调用名为add的汇编器模块的main函数: main(){...... add(dest,op1,op2,flages); ......}. 在此示例中,主函数被分解,并且主函数在调用add函数之前自动组织堆栈. ... lea 0xfffffffe8(%ebp),%eax#标志数组的第一个地址push%eax pushl 0xfffffff8(%ebp)#OP2 push push 0xfffffffc(%ebp)#OP1 push push 0xffffffff0(%ebp)#目标地址在堆栈调用0x80483f0
08a1c5b6cd30745a78fd830cea7e6e
为了使用ESP访问堆栈中的参数,在输入子例程之后,可以制作一个ESP副本,然后使用该副本访问传递的参数是安全的. 通常,EBP可用于保存ESP,例如: push%ebp mov%ebp,%esp2,保留数据空间如果汇编子例程中需要一些本地数据,则可以简单地减小ESP的值以保留节堆栈空间区域中用于存储本地数据的存储空间,子例程结束后必须恢复该区域. 以下语句可以保留本地数据区域: push%ebp mov%ebp,%esp subl space,%esp; set space = 4 movl $ 0x0,%ebp movl $ 0x0,-2(%ebp)如上面的语句,space是本地数据的字节总数. 在将来的应用中,由于更改了ESP并且固定了EBP,因此可以使用负偏移量访问局部变量. 上面的示例使用EBP和offset将两个字的本地数据初始化为0. 3.保留寄存器值如果调用的子例程中使用了其他寄存器,例如ESI和EDI,则应先将它们推入堆栈以保留原始寄存器值. 例如,以下示例将ESI和EDI寄存器的值压入: pushl%ebp movl%ebp,%esp subl $ space,%esp,pushl%esi pushl%edi 4.获取传递的参数并完成步骤1到3. 然后,结合上面的C程序传递参数的示例,堆栈结构如图2所示.
05f02d16980260640c0e9dbc9e15a5df
可以看出,在传递参数并将EBP推入堆栈后,EBP保留了ESP的副本. EBP可用于轻松访问参数. 现在假设每个参数是2字节的整数值,并且在小模式编译中总共使用2个字节. 如果要取出参数op1和op2并将它们分配给ebx和ecx寄存器,则可以通过以下语句完成此功能: movl 0x8(%ebp),%eax movl 0xc(%ebp),%ecx 5 ,子程序返回值当需要返回子程序的执行结果时,C根据返回值的字长,按如下方式接收返回值: AL寄存器中有1个字节; EAX寄存器中有2个字节; 4个字节位于高位部分. EDX的中下部在EAX寄存器中. C可以从这些寄存器中获取返回值. 6.退出汇编程序子例程结束汇编程序的步骤如下: 1)如果ESS,EDS,ESI或EDI已被压入堆栈,则需要以与保存时相反的顺序弹出它们. . 2)如果在过程开始时分配了本地数据空间,则使用mov%esp和%ebp指令恢复%esp. 3)使用指令pop%ebp恢复%ebp. 此步骤是必需的. 或者,您可以使用Leave语句恢复%ebp. 相当于movl%ebp,%esp; popl%ebp 4)最后,汇编程序以ret结尾.
ab31cff8db197ca6a9821ce9b3689838
2. 解释并建立呼叫者和被呼叫者之间的连接. 为了在调用方和被调用模块之间建立连接,被调用汇编程序应用全局表示它可以被外部模块调用;所引用的外部模块的名称应事先说明. 下面通过我的示例进行说明,该示例是C调用add0的汇编子例程. 程序列表如下: / * add.c * / #include
使用文件名add.c保存C源程序,并使用add.s保存汇编语言源程序;编译并与MAKE链接的连接代码如下: all: myadd myadd: adds.o addc.o gcc -o myadd adds.o adc.o adds.o: add.s as --o adds. o add.s addc.o: add.c gcc --g --o addc.o add.c如上所示,在C中调用组装模块非常方便. 因此,在实际的软件开发中,我们可以采用混合编程技术,以便尽可能地利用每种语言的优势. 它不仅可以满足实际问题的需要,而且可以简化设计过程并以较少的努力获得更多的结果.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-148117-1.html
不过也不必反应过度