DSP

TMSC64XX DSP混合汇编1

2019-07-13 17:22发布


      C/C++编译器的函数调用有一套严格的规则。除特定的支持函数外,任何调用或被C/C++函数调用的函数均必须遵守这些规则。不遵循这些规则可能破坏C/C++环境并导致程序错误。   函数如何调用

      当一个函数(父函数)调用另一个函数(子函数)时需执行以下任务:

      (1)按2节的寄存器使用规则把需传递的函数参数放入寄存器或堆栈。
 
      (2)如果A0~A9及B0~B9的值在函数调用后还有用,调用时需将他们压人堆栈保存。

      (3)父函数调用子函数。

      (4)返回时,主函数通过增加堆栈指针地址来释放函数调用开始处参数所站空间。       3.2被调用函数如何响应

      (1)被调用函数(子函数)在堆栈中的局部变量、临时变量及被该函数调用的其他函数的变量分配足够空间。堆栈分配在函数开始处执行,有可能包括帧指针(FP)的分配。帧指针用于从堆栈中读参数及处理寄存器溢出指令。

      (2)如果被调用的函数调用其他函数,返回值需存人堆栈。否则他将保留在返回寄存器(B3)中,并可能被下一个函数调用覆盖。

      (3)如果被调用的函数更新了A10~A15或B10~B15寄存器,必须将他们存储在其他寄存器或堆栈中。被调用的函数可以不保存地更新其他寄存器。

      (4)如果被调用的函数有结构型参数,他接收指向结构的指针。如果要从被调用的函数写结构体,需在堆栈中分配空间,局部变量的结构体需从传递指针拷贝到结构体。

      (5)被调用函数执行函数代码。

      (6)被调用函数返回整型、指针或单精度浮点型,则返回值放人A4寄存器;若返回双精度或长精度,则放入A5:A4寄存器对中,若返回是结构体,主调函数为其分配空间并将返回地址通过A3传给被调函数,被调函数将结构拷贝到该参数指向的存储块。

      (7)恢复(3)中保存的A10~A15或B10~B15寄存器。

      (8)如果A15用做帧指针(FP),A15的旧值从堆栈中恢复。另外,(1)中为函数分配空间在函数结束时通过寄存器B15(SP)加一个常数回收。

      (9)通过跳转到返回寄存器(B3)的值或返回寄存器的保存值实现函数返回。         4 在C/C++程序中插入汇编语言

      在C/C++程序中插入汇编语言,通用有4种方法:

      (1)用独立的汇编代码模块并将他们与已编译的C/C++模块链接。

      (2)用C/C++源内联函数直接调用汇编语言模块。

      (3)在C/C++源程序中内嵌汇编指令。

      (4)在C/C++源程序中使用汇编模块中定义的变量和常量。         4.1使用汇编模块

      只要遵守第2节的寄存器使用规则和第3节的函数调用规则,可直接在C/C++程序中插入汇编语言。C/C++代码可访问在汇编语言中定义的变量,调用汇编语言中定义的函数,汇编代码亦可访问C/C++代码,调用C/C++函数。
   此例中asmfunc外部声明是可选项,因为返回类型为整型。与C/C++函数一样,只有返回非整型值或传递非整型参数时需要声明汇编函数。         4.2 用内联函数访问汇编语言

      C6200的C编译器认可许多内联函数操作,内联函数像普通C函数一样使用但产生C无法表达的汇编语言描述,内联函数以下划线引导,像调用常规C函数一样调用。如:
      4.3使用嵌入汇编语言

      在C程序中嵌入汇编语句是一种C和汇编直接接口的方法,他可以在C中实现C语言无法实现的一些硬件控制功能,比如对寄存器的修改和读取等,但是C编译器在编译时并不检查嵌入的汇编语句,所以这个方法有时候会破坏C运行环境。使用方法是在汇编语句的左右加上双引号,用圆括弧将汇编语句括起来,加上asm标示符,如:
  注意结尾要加上语句结束的分号符。       4.4 从C模块访问汇编语言变量

      C程序有时需要访问汇编语言定义的变量。具体的方法取决于变量定义在.bss段,还是定义于非.bss段或是一个常量。         4.4.1 访问汇编全局变量

      访问定义在.bss部分或在.usect部分方法很直接。

      (1)用.bss或.usect定义一个变量。

      (2)如果用.usect定义一个变量没有被定义在.bss段,因此需声明为far。

      (3)用.def或.global命令行定义为外部变量。

      (4)汇编语言中在变量名前加下划线。

      (5)在C语言中,声明变量为外部变量,并按正常情况访问。  
      4.4.2访问汇编常量       在汇编语言中,可以用.set, .det和.global来定义全局常量,或在连接命令文件里用连接分配语句定义他们。这些长量只有使用特殊操作才可由C访问,对于C或汇编中定义的常规变量符号表包括变量值的地址,对于汇编常量符号表则包括常量值。则编译器不能辨别符号表中哪些项是值,哪些项是地址。如果想通过名字访问汇编常量,则编译器企图从符号表中的地址获取值。要避免不必要的获取,必须使用一(取地址)操作取值。即如果X是汇编常量,他在C中的值是&X。可以使用casts和#define简化程序中这些符号的使用。
     由于仅用到存储在符号表中的符号的值,符号的声明类型不再重要。本例中用的是int型。 需要注意的是,在C语言中,对于局部变量的建立和访问,是通过堆栈实现的,它的寻址是通过堆栈寄存器SP实现的。而在汇编语言中,为了使程序代码变得更为精简,TI在直接寻址方式中,地址的低7位直接包含在指令中,这低7位所能寻址的具体位置可由DP寄存器或SP寄存器决定。具体实现可通过设置ST1寄存器的CPL位实现,CPL=0,DP寻址,CPL=1,SP寻址。在DP寻址的时候,由DP提供高9位地址,与低7位组成16位地址;在SP寻址的时候,16位地址是由SP(16位)与低7位直接相加得来。
由于在C语言的环境下,局部变量的寻址必须通过SP寄存器实现,在混合编程的时候,为了使汇编语言不影响堆栈寄存器SP,通常的方式是在汇编环境中使用DP方式寻址,这样可以使二者互不干扰。编程中只要注意对CPL位正确设置即可。