共2条
1/1 1 跳转至页
sonics c与汇编参数的传递 (转载sonics )
问
C430的汇编语言接口
C430编译器允许汇编语言模块与编译好的C语言模块相连接。这一点特别适用于要求占用空间小、有严格时间限制的子程序设计。这类子程序总是希望用汇编语言来编写,然后由C语言主程序调用。
创建汇编子程序框架
要创建有正确接口的汇编语言子程序,建议用以下方法,即:经过C430编译器创建汇编语言源程序框架。用户可以很容易地在这个源程序框架中加上子程序需要实现的功能主体。下例是创建一个源程序框架,框架中只需要声明所引用的变量,并且执行对它们的简单访问:
int k;
int foo(int i, int j)
{
char c;
i++; // 访问 i
j++; // 访问 j
c++; // 访问 c
k++; // 访问 k
return(i);
}
void f(void)
{
foo(4,5); // 调用foo
}
然后,对此程序编译。
编译时要在Workbench的菜单project中选择Options命令,并在其中的ICC430选项类中,对List页设置:Assembly output file。
这一选项的设置是为了编译后能创建汇编语言源文件(s43)和汇编列表文件(lst)。其中,将包含C源代码行,作为汇编程序的注释。
经过编译,就获得了所需的汇编语言源文件(s43),它包含了变量声明、函数调用、函数返回、变量访问等。用户可以在此程序框架的基础上继续编写程序及修改。
以下详细叙述调用接口。
调用规则
寄存器的使用
C430编译器使用2组MSP430的寄存器:
R12至R15用于参数传递,因此在两次调用之间通常不加保护。
其它寄存器R4至R11主要用于存放寄存器变量和中间结果,因此在两次调用之间必须加以保护。
用-ur选项可以阻止C430编译器使用寄存器R4、R5。
堆栈结构和参数传送
每次函数调用,创建如下的堆栈结构:
除首2个外的全部参数 高地址
返回地址
保护寄存器
自动变量
SPà 暂存存储器 低地址
传递给汇编子程序的参数依照从右至左的次序。最左边的2个参数用寄存器传递,但是如果它们是结构或联合仍用堆栈传递。其余参数总是用堆栈传递。看下例:
f(w,x,y,z)
因为参数按照从右至左的次序处理,结果如下:
首先是z压入堆栈;
接着是y压入堆栈;
x根据类型,放在R14、R15:R14、或者在堆栈中;
w与x相同。
函数结果在R12或R13:R12(32位)中返回。如果返回的是结构或联合,结果在R12所指向的存储区域中返回。
上述内容见表5-3。
表5-3 传递参数
参数 <32位类型 32位类型 结构或联合
第4参数z 堆栈 堆栈 堆栈
第3参数y 堆栈 堆栈 堆栈
第2参数x R14 R15:R14 堆栈
第1参数w R12 R13:R12 堆栈
结果 R12 R13: R12 R12所指区域
INTERRUPT函数
中断函数保护状态寄存器和R4至R15寄存器。
保护状态寄存器是中断调用过程的一部分。而子程序中用到的寄存器要用PUSH Rxx指令保存。程序退出时用POP Rxx指令恢复用PUSH保护的寄存器。由RETI指令重新装载状态寄存器并从中断返回。
MONITOR函数
在使用monitor编译命令的情况下,编译时用PUSH SR保存CPU状态,并用DINT禁止中断。退出时用RTI重新装载状态寄存器,其中包括恢复原先的中断标志,然后返回。
C程序调用汇编子程序
从C程序调用的汇编子程序,必须做到:
l 遵守调用约定;
l 具有PUBLIC入口标号;
l 在被调用前声明为external,以允许类型检查和选择参数升迁。
局部储存分配
如果子程序需要局部储存,可以用下列几种方式分配空间:
l 利用硬件堆栈。
l 如果子程序不要求可重用或可重入,可以利用静态工作空间。
函数在利用寄存器时,对R12至R15不加保存,而对R6至R11在使用前压入堆栈加以保护。为了达到与ROM 监控的代码兼容,不应该使用R4和R5。
如果C程序编译时用了 -ur45选项,而应用程序也不运行ROM监控代码,那么在汇编子程序中也可以使用R4和R5。并且不必对它们作保护,因为C程序从不使用R4和R5。
中断函数
中断函数不能使用上述调用规则,因为中断可能会发生在调用一个前台函数运行期间。因此,对中断函数子程序的要求与一般的函数子程序是不同的:
l 中断子程序必须保护所有引用的寄存器,包括R12至R15。
l 中断子程序必须用RTI来退出。
l 中断子程序必须对所有的标志当作未定义的来处理。
定义中断矢量
中断矢量安排在INTVEC段中。
作为一种替代,用户可以用汇编语言编写中断函数。因此,可以自由地汇编中断子程序,并将它直接安装在中断矢量地址处。 答 1: 顶一下 答 2: 顶两下 答 3: 这个挺复杂,受益匪浅 答 4: 各位都是大虾,以后请多多指教~! 答 5: 顶一下 答 6: 强,我是用AQ430的,有没有AQ430这个的用法,期待啊 答 7: 引用:
C430编译器允许汇编语言模块与编译好的C语言模块相连接。这一点特别适用于要求占用空间小、有严格时间限制的子程序设计。这类子程序总是希望用汇编语言来编写,然后由C语言主程序调用。
创建汇编子程序框架
要创建有正确接口的汇编语言子程序,建议用以下方法,即:经过C430编译器创建汇编语言源程序框架。用户可以很容易地在这个源程序框架中加上子程序需要实现的功能主体。下例是创建一个源程序框架,框架中只需要声明所引用的变量,并且执行对它们的简单访问:
int k;
int foo(int i, int j)
{
char c;
i++; // 访问 i
j++; // 访问 j
c++; // 访问 c
k++; // 访问 k
return(i);
}
void f(void)
{
foo(4,5); // 调用foo
}
然后,对此程序编译。
编译时要在Workbench的菜单project中选择Options命令,并在其中的ICC430选项类中,对List页设置:Assembly output file。
这一选项的设置是为了编译后能创建汇编语言源文件(s43)和汇编列表文件(lst)。其中,将包含C源代码行,作为汇编程序的注释。
经过编译,就获得了所需的汇编语言源文件(s43),它包含了变量声明、函数调用、函数返回、变量访问等。用户可以在此程序框架的基础上继续编写程序及修改。
以下详细叙述调用接口。
调用规则
寄存器的使用
C430编译器使用2组MSP430的寄存器:
R12至R15用于参数传递,因此在两次调用之间通常不加保护。
其它寄存器R4至R11主要用于存放寄存器变量和中间结果,因此在两次调用之间必须加以保护。
用-ur选项可以阻止C430编译器使用寄存器R4、R5。
堆栈结构和参数传送
每次函数调用,创建如下的堆栈结构:
除首2个外的全部参数 高地址
返回地址
保护寄存器
自动变量
SPà 暂存存储器 低地址
传递给汇编子程序的参数依照从右至左的次序。最左边的2个参数用寄存器传递,但是如果它们是结构或联合仍用堆栈传递。其余参数总是用堆栈传递。看下例:
f(w,x,y,z)
因为参数按照从右至左的次序处理,结果如下:
首先是z压入堆栈;
接着是y压入堆栈;
x根据类型,放在R14、R15:R14、或者在堆栈中;
w与x相同。
函数结果在R12或R13:R12(32位)中返回。如果返回的是结构或联合,结果在R12所指向的存储区域中返回。
上述内容见表5-3。
表5-3 传递参数
参数 <32位类型 32位类型 结构或联合
第4参数z 堆栈 堆栈 堆栈
第3参数y 堆栈 堆栈 堆栈
第2参数x R14 R15:R14 堆栈
第1参数w R12 R13:R12 堆栈
结果 R12 R13: R12 R12所指区域
INTERRUPT函数
中断函数保护状态寄存器和R4至R15寄存器。
保护状态寄存器是中断调用过程的一部分。而子程序中用到的寄存器要用PUSH Rxx指令保存。程序退出时用POP Rxx指令恢复用PUSH保护的寄存器。由RETI指令重新装载状态寄存器并从中断返回。
MONITOR函数
在使用monitor编译命令的情况下,编译时用PUSH SR保存CPU状态,并用DINT禁止中断。退出时用RTI重新装载状态寄存器,其中包括恢复原先的中断标志,然后返回。
C程序调用汇编子程序
从C程序调用的汇编子程序,必须做到:
l 遵守调用约定;
l 具有PUBLIC入口标号;
l 在被调用前声明为external,以允许类型检查和选择参数升迁。
局部储存分配
如果子程序需要局部储存,可以用下列几种方式分配空间:
l 利用硬件堆栈。
l 如果子程序不要求可重用或可重入,可以利用静态工作空间。
函数在利用寄存器时,对R12至R15不加保存,而对R6至R11在使用前压入堆栈加以保护。为了达到与ROM 监控的代码兼容,不应该使用R4和R5。
如果C程序编译时用了 -ur45选项,而应用程序也不运行ROM监控代码,那么在汇编子程序中也可以使用R4和R5。并且不必对它们作保护,因为C程序从不使用R4和R5。
中断函数
中断函数不能使用上述调用规则,因为中断可能会发生在调用一个前台函数运行期间。因此,对中断函数子程序的要求与一般的函数子程序是不同的:
l 中断子程序必须保护所有引用的寄存器,包括R12至R15。
l 中断子程序必须用RTI来退出。
l 中断子程序必须对所有的标志当作未定义的来处理。
定义中断矢量
中断矢量安排在INTVEC段中。
作为一种替代,用户可以用汇编语言编写中断函数。因此,可以自由地汇编中断子程序,并将它直接安装在中断矢量地址处。 答 1: 顶一下 答 2: 顶两下 答 3: 这个挺复杂,受益匪浅 答 4: 各位都是大虾,以后请多多指教~! 答 5: 顶一下 答 6: 强,我是用AQ430的,有没有AQ430这个的用法,期待啊 答 7: 引用:
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |