《嵌入式系统实践实验报告--汇编和C 语言的相互调用.docx》由会员分享,可在线阅读,更多相关《嵌入式系统实践实验报告--汇编和C 语言的相互调用.docx(9页珍藏版)》请在第一文库网上搜索。
1、计算机科学技术系上机实践报告课程名称:嵌入式系统实践年级:上机实践成绩:指导教师:姓名:创新实践成绩:上机实践名称:汇编和C语言的相学号:上机实践日期:互调用上机实践编号:No.3组号:上机实践时间:V实验目的1. 阅读EmbCStEduKit-III启动代码,观察处理器启动过程;2. 学会使用En1beStIDE辅助信息窗口来分析判断调试过程和结果;3. 学会在EmbeStIDE环境中编写、编译与调试汇编和C语言相互调用的程序。二、实验设备1. 硬件:EmbestEDUKIT-111(实验平台)PC机2. 软件:EmbestIDEProARM集成开发环境,Windows98/2000/NT/
2、XP。三、实验内容使用汇编完成一个随机数产生函数,通过C语言调用该函数,产生一系列随机数,存放到数组里面。1 .C语言的编译过程C语言程序一汇编语言程序f目标可执行程序2 .汇编语言的函数调用过程参数准备函数返回汇编函数间调用3 .函数调用举例C语言调用汇编函数汇编语言调用C语言函数4 .命令脚本文件和链接脚本文件四、实验原理1. ARM过程调用ATPCS(ARM)ATPCS是一系列用于规定应用程序之间相互调用的基本规则,这此规则包括:支持数据栈限制检查;支持只读段位置无关(ROPI);支持可读/写段位置无关(RVVPI);支持ARM程序和ThUmb程序的混合使用;处理浮点运算。使用以上规定的
3、ATPCS规则时,应用程序必须遵守如下:程序编写遵守ATPCS;变量传递以中间寄存器和数据栈完成;汇编器使用-apes开关选项。关于其他ATPCS规则,用户可以参考ARM处理器相关书籍或登录ARM公司网站。程序只要遵守ATPCS相应规则,就可以使用不同的源代码编写程序。程序间的相互调用最主要的是解决参数传递问题。应用程序之间使用中间寄存器及数据栈来传递参数,其中,第一个到第四个参数使用R0R3,多于四个参数的使用数据栈进行传递。这样,接收参数的应用程序必须知道参数的个数。但是,在应用程序被调用时,一般无从知道所传递参数的个数。不同语言编写的应用程序在调用时可以自定义参数传递的约定,使用具有一定
4、意义的形式来传递,可以很好地解决参数个数的问题。常用的方法是把第一个或最后一个参数作为参数个数(包括个数本身)传递给应用程序。ATPCS中寄存器的对应关系如表35所列:表35ATPCS规则中寄存器列表ARM寄存器ATPCS别名ATPCS寄存器说明RO-R3a1-a4参数/结果/scratch寄存器1-4R4v1局部变量寄存器1R5v2局部变量寄存器2R6v3局部变量寄存器3R7V4、wr局部变量寄存器4ThUmb状态工作寄存器R8v5ARM状态局部变量寄存器5R9V6、sbARM状态局部变显寄存器6RWPI的静态基址寄存器R1OV7、siARM状态局部变星寄存器7数据栈限制指针寄存器R11v8
5、ARM状态局部变量寄存器8R12P子程序内部调用的临时(SCmtCh)寄存器R13sp数据栈指针寄存器R14Ir链接寄存器R15PC程序计数器2.main()函数与gccmain()当应用程序中包含了main。函数,将会引起对C运行时库的初始化。该初始化是通过函数gccmain()实现的,即在main。函数入口处,编译器会首先调用gccmain()函数,然后才是执行编写的代码。_gccmain()函数在gcc的标准库里面实现。当应用程序中没有包含main。函数,将不会引起对C运行时库的初始化。这时,C运行时库的很多功能在应用程序中是不能使用的。在基础实验的课程里面,我们没有涉及到函数库的内容,
6、因此,我们不打算在这里加入函数库的使用。因此,如果我们使用main函数作为应用程序的主函数,可以在源代码中加入一个空的五、实验步骤1 .考本章其他实验,创建新的工程,工程名为:exp1asm:2 .按照参考程序,重新编写源代码文件并分别保存为randtest.c,init.s,random.s和IdSCript,并把它们加入工程里面;3 .参照其他基础实验操作,按照编译一汇编器配置一链接器配置一调试器配置设置新工程,并编译、链接工程,如图3-14所示;4 .下载调试文件,打开memoryregisterWatCh/variab1e/CaI1StaCk窗口,单步执行程序。通过以上窗口,跟踪程序运
7、行,观察分析运行结果,通过实验学会使用EmbeSt1DE进行应用程序的开发与调试;5 .理解和掌握实验后,完成实验练习题。6 .习题:- 编写一个汇编程序mixop.s- 实现函数y=mixop(x1,x2,x3)- y=x1+x2*x3- 调用c2.c中的mu1tip1y函数- C程序1:c1.c- 实现函数voidinit();- 作为启动时的起始地址- 在该函数内要调用mixop函数完成6+40*50,结果存放在变量y中。- C程序2:c2.c- 实现函数y=mu1tip1y(x1,x2)- y=x1*x2提示:init()函数结尾时,设置死循环调试过程、结果和分析编写三个函数八、JBu
8、i1dingproject:exparm-e1f-gcc-gdwarf-cC:EmbestIDEExamp1esexpc2.c-o.debugc2.oarn-e1f-as-gdarF2C:EmbestIDEExamp1esexpmixop.s-o.debugioarn-e1F-1d-Ttext00-o.debugexp.e1F.debugd.o.debugc2.o.cygdriuecEnbestIDEBui1dxgcc-arm-e1Fbinaru-e1F-1d:Warning:caComnand(S)successfu11yexecuted.运仃c1.cR10:0X00000000。R10:0
9、00000000。R11:0X00000000。R11:0FffFfffcqR12:0x00000000。R12:000O0OOOOqR13:OFfFfffF0NR13:OxFFFFffec0R14:000000O0O。R14:0X00000000。R15:OOO090008。R15:O0O0OOO1OqSP:0xfFFFFFF0/SP:GXffffffeCG1R:00000000W1R:0X00000000*PC:00000008。PC:000000109CPSR:O0000OOd3。CPSR:00O0000d3qSPSR:0x00000000jSPSR:OOOOOOO0将常数赋值给r,r1
10、,r2012RRRO0000000060X000000280X00000032R3:0O0000000R4:O00O00000R5:00000O00OR6:OO00O0OO0R7:000000000R8:0O0OOOO00DQ-AvAAAAAAAmixop.s俣存当前地址R11:GXFFFFFffCR12:0O00000O0R13:OxFFFFFFecR14:0OOOO002OR15:0O00OOO58SP:OxFFFFFFec1R:0000000200PC:00OO0OO58。CPSR:000OOO0d3。SPSR:0X00000000将r3的值放入rRO:0x00000032R1:0OOO
11、OO028R2:O0OO00O32R3:0X0O0000O0R4:0x00000006R5:OxO0O0OOOOR6:0X0O000000R7:0x00000000R8:0O00O00O0R9:OxOOOOOOOr*r1的值放入rqR0:00O0O07dO。R1:0X00000028。R2:x00000032PR3:000O0O7dO。R4:0x00000006。R5:0X00000000。R6:0x00000000。R7:OO00000OO。R8:0X00000000&R9:0X00000000R0+r4的结果存入rR:0000007d6R1:0x00000028R2:0x00090032R
12、3:000OOO7dORU:OO0OOOO6R5:O0000OO00R6:000000000R7:0x00000000R8:0x00000000R9:0x00000000七、总结本次实验主要是将两个C函数与一个汇编函数连接,从而实现相互调用。编译之后调试过程中遇到了一些错误,后来发现是程序入口的地址应该和连接脚本写得一样,之后调试成功。八、附件c1.cexternintunsignedmixop(intx1,intx2,intx3);voidinit()(inty;y=mixop(6,40,50);whi1e(1)()Mixop.s.g1oba1mixop.externmu1tipy.textmixop:movip,spstmdbsp!,fp,ip,Ir,pcsubfp,ip,#4movr4,rmovr,r2b1mu1tip1yaddr,r,r4Idmdbfp,fp,sp,pc).endC2.cunsignedintmu1tip1y(x1,x2)inty;y=x1*x2;returny;