ARM汇编子程序参数传递
2016-01-02 00:54
316 查看
ATPCS规则体现了一种模块化设计的思想,其基本内容是C模块(函数)
和汇编模块(函数)相互调用的一套规则(C51中也有类似的一套规则)。
我感觉比在线汇编功能强大(不用有很多忌讳),条理更清楚(很简单的几条
规则)。
规则内容
一.被调用模块的寄存器使用
1.调用模块和被调用模块通过R0-R3传递参数,因此参数少于四个时可以随意
使用剩余的而不必保存和恢复
2.使用R4-R11之前一定要先在堆栈中保存起来,退出时再恢复
3.可以使用堆栈,但一定要保证堆栈指针(R13)在进入时和退出时相等
4.R14用于保存返回地址,使用前一定要备份
二.被调用模块的堆栈使用
ATPCS规则规定堆栈是满递减(fD)型的,因此使用STMFD/LDMFD指令操作,
注意保证进入和退出时堆栈指针相等
三.参数传递
当少于四个时,按从左到右的顺序依次放在r0,r1,r2,r3中;
当多于四个时,前四个放在r0,r1,r2,r3中,剩余的放在堆栈中,最后一个
参数先入栈,第五个参数最后入栈,即从右到左入栈
四.返回值
结果为32位时,通过R0返回
结果为64位时,r0放低32位,r1放高32位
如果不涉及Thumb指令集,全部规则就这几条,
比较有条理,很清楚,我举两个例子:
1.C主程序调用汇编子程序
C主程序:
#define UINT unsigned int
extern UINT add_six(UINT a,UINT b,UINT c,UINT d,UINT e,UINT f);
int main(void)
{
add(1,2,3,4,5,6);
return
0;
}
汇编子程序:
area
cdo,code,readonly ;段名cdo,代码段
code32 ;ARM指令
add_six
global
add_six ;add_six是全局标号
stmfd
r13,{r4,r5} ;将r4,r5压入堆栈,但R13不变
ldr
r4,[r13] ;将第五个参数从堆栈中提出
ldr
r5,[r13,#4] ;将第六个参数从堆栈中提出
add
r0,r0,r1
add
r0,r0,r2
add
r0,r0,r3
add
r0,r0,r4
add
r0,r0,r5 ;32位结果保存在R0中
sub
r3,r13,#8
ldmfd
r3,{r4,r5} ;从堆栈中恢复r4,r5
mov
r15,r14 ;返回主程序
end
2.汇编主程序调用C子程序
汇编主程序
area
main,code,readonly ;代码段
entry ;声明程序入口
code32 ;32位ARM指令
extern
add_six ;声明标号add_six
start
mov
r13,#0xa000 ;初始化堆栈指针
mov
r0,#1
mov
r1,#2
mov
r2,#3
mov
r3,#4 ;前四个参数通过寄存器传递
mov
r4,$5
mov
r5,#6
stmfd
r13!,[r4,r5] ;后两个参数通过堆栈传递
bl
add_six
mov
r1,r0 ;调用后结果将放在r0中
end
C子程序:
#define UINT unsigned int
UINT add_six(UINT a,UINT
b,UINT c,UINT d,UINT e,UINT f)
{
return
a+b+c+d+e+f;
}
以上代码均在ARM ADS 1.2中调试通过。
总结一下,在线汇编比较简洁,但功能有限,而且规则有点零碎;
ATPCS功能强大而且条理清楚,但需要单独在开一个模块;
写代码时可以根据需要自由选择.
from: http://blog.sina.com.cn/s/blog_4b61ebcd010005rd.html
和汇编模块(函数)相互调用的一套规则(C51中也有类似的一套规则)。
我感觉比在线汇编功能强大(不用有很多忌讳),条理更清楚(很简单的几条
规则)。
规则内容
一.被调用模块的寄存器使用
1.调用模块和被调用模块通过R0-R3传递参数,因此参数少于四个时可以随意
使用剩余的而不必保存和恢复
2.使用R4-R11之前一定要先在堆栈中保存起来,退出时再恢复
3.可以使用堆栈,但一定要保证堆栈指针(R13)在进入时和退出时相等
4.R14用于保存返回地址,使用前一定要备份
二.被调用模块的堆栈使用
ATPCS规则规定堆栈是满递减(fD)型的,因此使用STMFD/LDMFD指令操作,
注意保证进入和退出时堆栈指针相等
三.参数传递
当少于四个时,按从左到右的顺序依次放在r0,r1,r2,r3中;
当多于四个时,前四个放在r0,r1,r2,r3中,剩余的放在堆栈中,最后一个
参数先入栈,第五个参数最后入栈,即从右到左入栈
四.返回值
结果为32位时,通过R0返回
结果为64位时,r0放低32位,r1放高32位
如果不涉及Thumb指令集,全部规则就这几条,
比较有条理,很清楚,我举两个例子:
1.C主程序调用汇编子程序
C主程序:
#define UINT unsigned int
extern UINT add_six(UINT a,UINT b,UINT c,UINT d,UINT e,UINT f);
int main(void)
{
add(1,2,3,4,5,6);
return
0;
}
汇编子程序:
area
cdo,code,readonly ;段名cdo,代码段
code32 ;ARM指令
add_six
global
add_six ;add_six是全局标号
stmfd
r13,{r4,r5} ;将r4,r5压入堆栈,但R13不变
ldr
r4,[r13] ;将第五个参数从堆栈中提出
ldr
r5,[r13,#4] ;将第六个参数从堆栈中提出
add
r0,r0,r1
add
r0,r0,r2
add
r0,r0,r3
add
r0,r0,r4
add
r0,r0,r5 ;32位结果保存在R0中
sub
r3,r13,#8
ldmfd
r3,{r4,r5} ;从堆栈中恢复r4,r5
mov
r15,r14 ;返回主程序
end
2.汇编主程序调用C子程序
汇编主程序
area
main,code,readonly ;代码段
entry ;声明程序入口
code32 ;32位ARM指令
extern
add_six ;声明标号add_six
start
mov
r13,#0xa000 ;初始化堆栈指针
mov
r0,#1
mov
r1,#2
mov
r2,#3
mov
r3,#4 ;前四个参数通过寄存器传递
mov
r4,$5
mov
r5,#6
stmfd
r13!,[r4,r5] ;后两个参数通过堆栈传递
bl
add_six
mov
r1,r0 ;调用后结果将放在r0中
end
C子程序:
#define UINT unsigned int
UINT add_six(UINT a,UINT
b,UINT c,UINT d,UINT e,UINT f)
{
return
a+b+c+d+e+f;
}
以上代码均在ARM ADS 1.2中调试通过。
总结一下,在线汇编比较简洁,但功能有限,而且规则有点零碎;
ATPCS功能强大而且条理清楚,但需要单独在开一个模块;
写代码时可以根据需要自由选择.
from: http://blog.sina.com.cn/s/blog_4b61ebcd010005rd.html
相关文章推荐
- 数字信号处理笔记
- 数字信号处理笔记
- 了解 Maven
- 方法与思想高于平台与语言
- nginx_lua vs nginx+php 应用场景
- 设计模式系列7---金点子多多的策略模式
- 第六届福建省大学生程序设计竞赛 Super Mobile Charger
- sublime2使用过程中遇到的一些问题总结
- 重新出发:我的2015总结和2016计划
- 代理设计模式在 UIScrollView 中的应用
- github比sourceforge好在哪?
- java温习笔记01:环境配置及编辑器设置
- 资源文件assets和 res下面raw文件的使用不同点
- UITableView
- RecyclerView的嵌套使用
- centos 6.7(final)jdk 安装
- ngx_lua应用最佳实践
- 【前端】JS
- 每日记录
- https提供安全的web通讯