chuxuezhe 当前离线
金牌会员
对于有假定值(为0或为1)的状态寄存器单元,在进行函数调用和函数返回时必须保证其值为假定值。
13.2.6 函数结构与调用规则
TMS320C2x/C2xx/C5x运行环境对函数调用有严格的要求,要调用C函数或要被C程序调用的汇编语言程序必须遵守这些规则,否则可能破坏C运行环境,造成程序失败。
当进行函数调用时,调用者要将传递参数压入系统堆栈传给被调用的函数,并将函数返回地址压栈。
被调用的函数要在函数运行结束时将返回值放在累加器里返回给调用者函数。
TOP
可见函数参数及返回地址等都是通过堆栈传递的,要
编写汇编函数,必须明确函数调用的过程中堆栈的
变化和应该进行的处理
调用函数的工作:
将参数反向压入堆栈(最右端的参数最先压栈,最左端的参数最后压栈),这样,当函数被调用时,最左端的参数会在堆栈的最顶部。调用被调用函数。
当被调用函数返回时,调用者函数假定ARP已被设置为AR1。
当被调用函数运行结束时,调用者函数要将压入堆栈的参数弹出以恢复堆栈状态。
注:如果用C程序调用汇编语言程序,C编译器会自动产生代码完成这 些工作。
被调用函数的工作:
进入函数时,函数假定ARP已经被设定为AR1。
将返回地址从硬件堆栈弹出,压入软件堆栈。
将FP(SP)压入软件堆栈。 分配局部帧。 如果函数中要修改AR6、AR7,将它们压入堆栈,其它寄存器不用进行保护就可以进行修改。 实现函数功能。如果函数返回标量数据,将它放入累加器。 将ARP设定为AR1。如果保护了AR6、AR7,恢复这两个寄存器。删除局部帧。
恢复FP(SP)。将返回地址从软件堆栈中弹出,压入硬件堆栈。返回。 一些特殊的情况:
返回一个结构:当函数的返回值为一个结构时,调用者函数负责分配存储空间,并将存储空间地址作为最后一个输入参数传递给被调 用函数。被调用函数将要返回的结构拷贝到这个参数所指向的内存空间。 将返回地址移动到软件堆栈:当被调用函数不再调用其它函数, 或者确定调用深度不会超过8级,可以不用将返回地址移动到软件堆栈。 不分配局部帧:如果函数没有输入参数,不使用局部变量,就不需要修改AR0(FP),因此也不需要对其进行保护。
13.2.7 C程序调用汇编函数
C程序调用汇编函数必须要满足前面介绍的调用规则和寄存 器规则,C程序可以访问汇编语言定义的变量或调用汇编语言函数,同样汇编语言也可以访问C程序定义的变量或调用C函数。 用C程序调用汇编函数有以下注意事项:
所有的函数(不论用C编写还是用汇编语言编写)都必须满足前面介绍的寄存器规则。对于一些寄存器,如果函数要修改其内容,则必须事先对其进行保护。这些寄存器包括:
AR0(FP) AR1(SP) AR6 AR7
其它的寄存器可以不用保护自由使用。 如果函数改变了状态寄存器某些有假定值的位,则必须在函数结束前恢复其原有值。尤其要注意ARP必须为AR1。
中断服务程序必须保护所有其用到的寄存器。 long型和float型变量在存储器中的存储方式为低有效位在低端地址。 函数返回值要通过累加器进行传递。 编译器会在所有对象的名称前面加下横线“_”,因此汇编 语言模块定义对象名称时也要以下横线为前缀,才能使定义的对象可以被C代码访问。例如C语言对象x在汇编语言中就是_x。汇编语言可以使用任何不带下横线前缀的变量而不会和C语言对象冲突。 任何汇编语言定义的对象,如果要被C程序访问,则必须用.global修饰。同样任何C语言定义的对象,如果要被汇编语言访问,也必须以.global修饰。
C程序调用汇编语言函数实例
13.2.8 使用内嵌asm语句
在C程序中可以用asm语句插入单行汇编语句,用来实现用C 语言很难实现的功能。但是如果使用这种语句,一定不要破坏C运行环境,因为C编译器不会对这种插入的汇编 语句进行检查或分析。
不要插入跳转或标签,否则会破坏编译器的堆栈处理算法,造成无法预期的后果。
不要修改C变量,但可以任意读取C变量当前值。
不要在内嵌汇编语句中书写修饰性汇编代码(如.text、 .data等),否则会破坏汇编环境。内嵌汇编语句可以用来在编译输出结果中添加注释。 asm(“ ***** this is an assembly language comment”);
13.2.9 C程序访问汇编语言变量 有时候需要在C程序中访问汇编语言变量,这通常有两种方式:
访问.bss块中的变量: 将要访问的变量定义在.bss块中。 用.golbal修饰要访问的变量。 在汇编语言中以下横线“_”为前缀声明要访问的变量。 在C语言中将变量声明为外部变量(extern),就可以进行正常访问。
访问非.bss块中的变量:
要访问非.bss块中的变量,通常的办法是在汇编语言中定义 一个查找表,然后在C语言中通过指针来访问。
首先定义变量,而且最好放在独立的初始化块中。 定义一个全局的标识指向对象的起始点,这样对象可以分配在存储器空间的任何位置。在C程序中将这个对象定义为外部对象(extern),并且对象名称不带下横线“_”前缀,就可以对其进行正常访问。
13.2.10 修改编译器输出结果
程序设计者可以检查和修改C编译器输出的汇编语言程序,然后
再对其进行汇编编译和连接。
在C语言可以使用内嵌汇编语句在编译输出结果中添加
注释,以改善编译器输出汇编程序的可读性。
/***************************************************/
asm(“ ***** this is an assembly language comment”);
13.2.11 系统初始化
C程序开始运行时,必须首先初始化C运行环境,这是通过c_int0函数完成的,这个函数在运行支持库(rts, runtime-support library)中。连接器会将这个函数的入口地址放置在复位中断向量处,使其可以在初始化时被调用。
c_int0函数进行以下工作以建立C运行环境: 为系统堆栈产生.stack块,并初始化堆栈指针。从.cinit块将初始化数据拷贝到.bss块中相应的变量。调用main函数,开始运行C程序。 用户可以对c_int0函数进行修改,但修改后的函数必须完成以上任务。
13.3 DSP程序烧写
DSP程序编写完成,调试无误后,就可以将程序烧写到DSP的
FLASH(EEPROM)中,使DSP可以脱离仿真器独立运行。
烧写DSP程序也要通过仿真器来进行,仿真器制造者会提供相
应的烧写程序。要注意不同型号的DSP往往使用不同的烧写程
序,不同类型的仿真器对烧写环境也会有不同的要求,使用
前要详细阅读相应说明(readme)。
MP/MC*模式置为0(微计算机模式)
仿真RAM不被PS*信号选中
DSP烧写步骤:
清除flash内容 (bc0.bat, bc1.bat)
将FLASH(EEPROM)中的所有位清零(set to 0)。
擦除flash内容 (be0.bat, be1.bat)
将FLASH(EEPROM)中的所有位置位(set to 1)。
把目标程序写进flash中 (bp16k.bat, bp32k.bat)
将FLASH(EEPROM)中的所有选中的位清零(set to
0)。
ggppjiao 当前离线
新手上路