b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

C语言和汇编语言相互调用

电脑杂谈  发布时间:2020-03-22 08:11:52  来源:网络整理

c语言对应汇编语句_c语言程序设计试题汇编_c语言程序设计试题汇编答案

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

c语言程序设计试题汇编答案_c语言程序设计试题汇编_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 #调用add函数. 执行add call语句后,堆栈上的数据结果如图1所示. 进入汇编子程序后,为了正确获取调用程序并存储在堆栈数据中c语言对应汇编语句,被调用的汇编程序子程序必须执行以下任务: 1.将esp的副本保存到汇编程序子程序中,该子程序是不可避免的. 必须进行推送和弹出操作,因此ESP总是在变化.

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 extern void add(int * dest,int op1,int op2,short int *标志); // *声明调用外部汇编函数* / int main(void){int op1,op2,result; int * dest =&结果;短整数标志[4] = {0,0,0,0}; printf(“请输入两个源运算符: ”); scanf(“%x%x”,&op1,&op2);添加(目标,op1,op2,标志); / *调用add0函数* / printf(“ ADD的结果是: %x \ n标志N(负数)Z(零)C(进位)V(溢出: %d,%d,%d,%d \ n “,* dest,标志[3],标志[2],标志[1],标志[0]);返回0;}#add.s .text .align 2 .global add .type add,函数#Define add作为外部可调用函​​数,添加: push%ebp #ebp将寄存器内容压入堆栈,并保存由add函数的父函数调用的函数的堆栈基地址mov%esp,%ebp #esp值已分配设置为ebp,设置添加功能mov 0x8(%ebp),%edx mov 0x10(%ebp),%eax添加0xc(%ebp),%eax mov%eax,(%edx)mov 0x14(% ebp),%eax jo OF C: jc CF S: js SF jz ZF jmp out of: movw $ 0x1,(%eax)jmp C CF: movw $ 0x1,0x2(%eax)jmp S SF: movw $ 0x1, 0x6(%eax)movw $ 0x0,0x4(%eax)jmp out ZF: movw $ 0x1,0x4(%eax)movw $ 0x0,0x6(%eax)out: 离开#将ebp值分配给esp,弹出基数前一个堆栈中的上层函数堆栈的地址为#eb p,还原原始堆栈基地址ret #add函数返回c语言对应汇编语句,返回上级的调用函数. 其中. text标记代码段的开始,这是AT&T段格式;全局添加; \ n输入add,函数表示add是公共的,可以被其他外部编译的模块调用来更改.

使用文件名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

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      每日福利
      热点图片
      拼命载入中...