02a汇编和C语言的相互调用2012华东师范大学计算机科学技术系2主要内容:•C语言的编译过程–C语言程序→汇编语言程序→目标可执行程序•汇编语言的函数调用过程–参数准备–函数返回–汇编函数间调用•函数调用举例–C语言调用汇编函数–汇编语言调用C语言函数•命令脚本文件和链接脚本文件2012华东师范大学计算机科学技术系3C和汇编语言混合编程•C语言程序→汇编语言程序→目标可执行程序C程序先要转化为汇编程序,意味着C和汇编语言混合编程时,最终可以从汇编语言之间的相互调用过程着眼C程序汇编程序汇编程序目标程序编译转化C程序汇编程序汇编程序如何转化如何调用C程序汇编程序如何调用2012华东师范大学计算机科学技术系4C语言函数→汇编函数inttest_fun(paras...){[处理过程]}test_fun:movip,spstmdbsp!,{fp,ip,lr,pc}subfp,ip,#4;0x4[处理过程]ldmdbfp,{fp,sp,pc}函数名转化为标号栈回溯结构退出fp(r11):FramePointerip(r12):sp(r13):StackPointerlr(r14):LinkRegisterpc(r15):ProgramCounterip→外层函数的栈顶fp→当前函数的栈底2012华东师范大学计算机科学技术系5参数个数≤4时-输入参数•在函数体内使用参数(4个参数见下表)别名寄存器说明a1r0参数1a2r1参数2a3r2参数3a4r3参数42012华东师范大学计算机科学技术系6参数个数≤4时-返回值•函数结束时,应将返回值存放到r0中2012华东师范大学计算机科学技术系7用汇编语言编写函数举例(参数个数≤4)•C语言函数total_fun(intp1,intp2,intp3),返回三数之和,用汇编语言实现total_fun:/*函数名由标号替代*/movip,sp/*栈回溯结构*/stmdbsp!,{fp,ip,lr,pc}subfp,ip,#4adda1,a1,a2/*实现p1+p2,存放在r0中*/adda1,a1,a3/*实现p1+p2+p3,存放在r0中*/ldmdbfp,{fp,sp,pc}/*返回*/2012华东师范大学计算机科学技术系8汇编语言调用函数(参数个数≤4)•如何准备函数参数–将参数依次直接存入R0-R3•如何获得函数返回值–从寄存器R0中读取举例:movr0,#1/*准备参数1*/movr1,#2/*准备参数2*/movr2,#3/*准备参数3*/bltotal_fun/*调用刚编写的求和函数*//*此时,r0中的值应该是6*/2012华东师范大学计算机科学技术系9参数个数4时-输入参数test_fun:movip,spstmdbsp!,{fp,ip,lr,pc}subfp,ip,#4;0x4subsp,sp,#32[处理过程]ldmdbfp,{fp,sp,pc}ip→外层函数体的栈顶fp→当前函数体的栈底sp→当前函数体的栈顶#32→当前函数所用栈容量2012华东师范大学计算机科学技术系10当前函数所用栈容量•临时变量个数+函数参数个数多于4个的部分•例如:–intfoo(intx1,intx2){inta,b,c;/*3个临时变量*/....}•其使用的栈容量=3–intfoo(intx1,intx2,intx3,intx4,intx5){inta,b,c;/*3个临时变量*/...}•其使用的栈容量=3+(5-4)=42012华东师范大学计算机科学技术系11当前函数内存布局外层函数栈顶当前函数栈顶子函数参数5子函数参数6子函数参数:由顶开始依次存放pcfpiplr现场信息函数变量子函数参数函数变量2函数变量1函数中的临时变量:由底开始依次存放ipfpip→外层函数体的栈顶fp→当前函数体的栈底2012华东师范大学计算机科学技术系12当前函数内存布局-思考题•如果当前函数有多个子函数,那么它的内存布局是如何的?•例如:–intfoo(){intx1,x2,x3,x4,x5,x6;foo1(x1,x2);foo2(x1,x2,x3,x4);foo3(x1,x2,x3,x4,x5,x6);}子函数参数5子函数参数6pcfpiplr函数变量子函数参数函数变量2函数变量12012华东师范大学计算机科学技术系13C语言调用汇编函数1externintunsigned2total_fun(intp1,intp2,intp3);3inttest(){4inty;5y=total_fun(1,2,3);6returny;7}1.globaltotal_fun2.text3total_fun:4movip,sp5stmdbsp!,{fp,ip,lr,pc}6subfp,ip,#47adda1,a1,a28adda1,a1,a39ldmdbfp,{fp,sp,pc}10.endtest.ctotal_fun.s2012华东师范大学计算机科学技术系14汇编语言调用C语言函数1.externtotal_fun2.text3test:4movip,sp5stmdbsp!,{fp,ip,lr,pc}6subfp,ip,#47movr0,#18movr1,#29movr2,#310bltotal_fun11ldmdbfp,{fp,sp,pc}12.end1unsignedinttotal_fun(2intp1,intp2,intp3){3returnp1+p2+p3;4}test.stotal_fun.c2012华东师范大学计算机科学技术系15命令脚本文件•命令脚本文件–IDE与目标板连接时–软件调试过程中–复位目标板后•需要集成环境自动完成一些特定的功能:–复位目标板、清除看门狗、屏蔽中断寄存器,等等•这些功能可以由一组命令序列完成,该命令序列保存在文件中。该文件称为命令脚本文件。文件后缀一般为.cs2012华东师范大学计算机科学技术系16命令脚本文件•命令–GO执行程序:从当前PC开始执行程序–MEMWRITE存储区写•向地址0x1000写入值0x5A•memwrite0x10000x5A–REFRESH刷新窗口–REGWRITE寄存器写•向寄存器PC写入值0x3840•regwritepc0x3840–RESET复位目标设备–STOP停止执行程序2012华东师范大学计算机科学技术系17命令脚本文件•命令脚本文件举例(page122):–stop;一般目标板都会处于运行状态regwritesp0x1000;程序刚执行时未初始化堆栈地址•命令脚本文件–类似于Windows操作系统中的autoexec.bat自动执行批处理文件2012华东师范大学计算机科学技术系18命令脚本文件的设置什么也不做,这时,IDE只是和目标板连接而已,但映像文件并不下载到目标板IDE和目标板连接以后,自动把映像文件下载到目标板IDE和目标板连接以后,执行脚本文件,但并不将映像文件下载到目标板2012华东师范大学计算机科学技术系19链接脚本文件•在程序编译时起作用。•该文件描述代码链接定位的有关信息,包括代码段,数据段,地址段等,链接器必须使用该文件对整个系统的代码做正确的定位。•在IDE开发环境中使用扩展名*.ld2012华东师范大学计算机科学技术系20链接脚本文件1SECTIONS2{3.=0X10000;4.text:{*(.text)}5.=0x80000000;6.data:{*(.data)}7.bss:{*(.bss)}8}1SECTIONS2{3.text:{*(.text)}4.data:{*(.data)}5.bss:{*(.bss)}6}目标输入文件1目标输入文件2目标输入文件n目标输出文件链接目标输入文件1:代码段初始化的数据段未初始化的数据段目标输入文件2:代码段初始化的数据段未初始化的数据段目标输出文件:代码段初始化的数据段未初始化的数据段2012华东师范大学计算机科学技术系21链接脚本文件•点.表示当前位置1SECTIONS2{3.=0X10000;4.text:{*(.text)}5.=0x80000000;6.data:{*(.data)}7.bss:{*(.bss)}8}1SECTIONS2{3.text:{*(.text)}4.data:{*(.data)}5.bss:{*(.bss)}6}2012华东师范大学计算机科学技术系22代码的执行过程•起始点:代码段起始处(下载地址)v.s.程序入口地址查找程序入口地址默认为标号:_start从程序入口地址开始执行是否找到入口地址?从代码段起始处开始执行否是从程序入口地址开始?否是2012华东师范大学计算机科学技术系23程序入口地址的设置•默认是global_start标号处•也可以人工指定程序入口地址所在文件程序入口标号名称2012华东师范大学计算机科学技术系24连接后代码段的组织(默认情况下)•单个文件的情况–按源程序编写顺序•多个文件的情况–入口文件放在最前面,其余文件按字母顺序组织1SECTIONS2{3.text:{*(.text)}4.data:{*(.data)}5.bss:{*(.bss)}6}目标输入文件1:代码段初始化的数据段未初始化的数据段目标输入文件2:代码段初始化的数据段未初始化的数据段目标输出文件:代码段初始化的数据段未初始化的数据段2012华东师范大学计算机科学技术系25连接后代码段的组织(默认情况下)•如何查看连接后的代码–编译连接后可使用ToolDisassembleall命令,会在工程的Debug目录下生成一个objdum文件2012华东师范大学计算机科学技术系26作业:完成实验报告•编写一个汇编程序mixop.s–实现函数y=mixop(x1,x2,x3)–y=x1+x2*x3–调用c2.c中的multiply函数•C程序1:c1.c–实现函数voidinit();–作为启动时的起始地址–在该函数内要调用mixop函数完成6+40*50,结果存放在变量y中。•C程序2:c2.c–实现函数y=multiply(x1,x2)–y=x1*x2•提示:init()函数结尾时,设置死循环02b中断2012华东师范大学计算机科学技术系28中断和异常:统称“中断”•外部中断–外部设备有紧急事件处理,向CPU发出中断请求–例:开发板上的interrupt按钮•异常–CPU内部有些事件也要发出中断请求–例:Reset,取指令出错,…2012华东师范大学计算机科学技术系29处理器和中断源•各自平等,双向选择–中断源(发方):有权决定是否发送中断请求–处理器(受方):有权决定是否接收中断请求•有两种中断输入通道处理器中断处理逻辑屏蔽开关可屏蔽中断信号输入端非屏蔽中断信号输入端2012华东师范大学计算机科学技术系30中断管理机构•三类中断–异常(内部中断)请求直接在处理器内部解决–非屏蔽中断由处理器外部直接输入–有屏蔽中断需要经过中断屏蔽开关,并进入排队逻辑处理器处理器内部的中断管理部件异常请求…处理器外部的中断控制器中断优先排队逻辑中断源1中断源2中断源3中断源4中断源n中断屏蔽开关可屏蔽中断非屏蔽中断2012华东师范大学计算机科学技术系31中断嵌套•较低优先级的中断源被较高优先级的中断源中断•实验时要实现中断嵌套较为复杂,有兴趣的同学可作研究–中断发生后转入相应中断模式–占用了相关寄存器,中断嵌套时需要重复占用,并将其覆盖–要想嵌套,需要保存中断相关模式下的寄存器内容主程序低优先级中断服务程序高优先级中断服务程序2012华东师范大学计算机科学技术系32中断服务程序•中断源向处理器发出中断请求,是因为有事情要处理。•每个中断源都有处理该事件的程序,称为中断服务程序。•中断服务程序也可以看成一种子程序,不过非用户调用,而是处理器响应中断请求由硬件调用处理器中断源有事要办——中断请求处理办法——中断服务器程序调用2012华东师范大学计算机科学技术系33中断服务程序与普通子程序•对比普通子程序中断服务程序程序入口(标号/函数名)程序