arm汇编编程(示例)
包括:
子程序调用过程中寄存器的使用规则、数据栈的使用规则和参数的传递规则。
1.寄存器使用规则
寄存器:R4-R11用来保存局部变量
R0-R3(a1-a4)用于保存参数/返回结果/scratch(临时寄存器)
R4-R11(v1-v8)用于保存ARM状态局部变量
R12(IP)子程序内部调用的scratch
R13(SP)数据栈指针
R14(LR)连接寄存器
R15(PC)程序计数器
R7又可称为wr用于Thumb状态工作寄存器
R9又可称为sb在支持RWPI的ATPCS中为静态基址寄存器
R10又可称为sl在支持PWPI的ATPCS中为数据栈限制指针
R11又可称为fp用于帧指针
2.数据栈使用规则
ATPCS标准规定,数据栈为FD(满递减类型),并且对数据栈的操作是8字节对齐。在进行出栈和入栈操作,则
必须使用ldmfd和strnfd指令(或ldmia和stmdb)
3.参数的传递规则
参数:参数小于等于4,用R0-R3保存参数,参数多于4,剩余的传入堆栈
函数返回:结果为32位整数,通过R0返回
结果为64位整数,通过R0,R1返回
对于位数更多的结果,通过内存传递
例:参数传递及结果返回(r0-r3做参数,r0做返回值)
AREAExample,CODE,READONLY;声明代码段Example
ENTRY;程序入口
Start
MOVR3,#4;设置实参,将参数写入R0-R3
MOVR2,#3
MOVR1,#2
MOVR0,#1
BLfunc1;调用子程序ADD_SUM
BOVER;跳转到OVER标号处,进入结尾
func1
ADDR0,R0,R1;实现两数相加
ADDR0,R0,R2
ADDR0,R0,R3
MOVPC,LR;子程序返回,R0内为返回的结果
OVER
END
相当于如下C语言
intfunc1(inta,intb,intc,intd){
returna+b+c+d;
}
intmain(){
func1(1,2,3,4);
}
例:多于4个参数,前4个通过寄存器R0-R3传递,其它参数通过数据栈传递
AREAExample,CODE,READONLY;声明代码段Example
ENTRY;程序入口
Start
STMFDSP!,{R1-R4,LR};先将R1-R4,及LR内原有数据压入栈,需要使用这五个寄存器
MOVR0,#1;准备好7个寄存嚣存入7个数据LR,IP,R4作临时寄存器使用
MOVIP,#2
MOVLR,#3
MOVR4,#4
MOVR1,#5
MOVR2,#6
MOVR3,#7
STMFDSP!,{R1-R3};先将R1-R3数据从前向后入栈,然后将IP,LR,R4内的数据装入R1-R3
MOVR3,R4;其中IP,LR,R4是临时使用的寄存器
MOVR2,LR
MOVR1,IP
BLfunc1;调用子程序funclR0是返回结果
LDMFDSP!,{R1-R4,PC};从栈中取出最初的数据,恢复原始值
BOVER;跳转到OVER标号处,进入结尾
func1
STMFDSP!,{R4,LR};当调用函数时,LR和R4都已发生了变化,其中LR是指令地址所以也压入栈
LDRR4,[SP,#0x10];目前共压入5个数据,每一个数据占两个字节,当前栈顶偏移10为前5个数据7
ADDLR,SP,#8;将前第4个数据的地址(栈项+偏移)赋给LR
LDMIALR,{IP,LR};连续将LR地址处的两个数据取出写入IP和LR内,从右向左写,LDMIA即出栈指令
ADDR0,R0,R1;从此行开始相当于returna+b+c+d+e+f+g;
ADDR0,R0,R2
ADDR0,R0,R3
ADDR0,R0,IP
ADDR0,R0,LR
ADDR0,R0,R4
LDMFDSP!,{R4,PC};从栈内取数据加载入R4和PC,PC跳转回主函数
OVER
END
下面是栈顶
相当于如下C语言
intfunc1(inta,intb,intc,intd,inte,intf,intg){
returna+b+c+d+e+f+g;
}
intmain(){
inta=1,b=2,c=3,d=4,e=5,f=6,g=7;
func1(a,b,c,d,e,f,g);
}
(二)、C和ARM汇编程序间的相互调用
1.汇编程序调用C子程序
为保证程序调用时参数正确传递,必须遵守ATPCS。
在C程序中函数不能定义为static函数。在汇编程序中需要在汇编语言中使用IMPORT伪操作来声明C子函数
//C代码
intsum5(inta,intb,intc,intd)
{
return(a+b+c+d);
}
//汇编代码
AREAExample,CODE,READONLY;声明代码段Example
IMPORTsum5;
ENTRY;程序入口
Start
MOVR3,#4;设置实参,将参数写入R0-R3
MOVR2,#3
MOVR1,#2
MOVR0,#1
BLsum5;调用子程序sum5
BOVER;跳转到OVER标号处,进入结尾
OVER
END
2.汇编程序访问全局C变量
汇编程序中可以通过C全局变量的地址来间接访问C语言中定义的全局变量
在编编程序中用IMPORT引入C全局变量,该C全局变量的名称在汇编程序中被认为是一个标号。通过ldr和str指令访问该编号所代表的地址
//C代码
inti=3;
intsum5(inta,intb,intc,intd)
{
return(a+b+c+d+i);
}
//汇编代码
AREAExample,CODE,READONLY;声明代码段Example
IMPORTsum5
IMPORTi
ENTRY;程序入口
Start
LDRR1,i;将i读入R1内
MOVR0,#2
ADDR0,R0,R1
STRR0,i;将寄存器值写入i内
MOVR3,#4;设置实参,将参数写入R0-R3
MOVR2,#3
MOVR1,#2
MOVR0,#1
BLsum5;调用子程序ADD_SUM
BOVER;跳转到OVER标号处,进入结尾
OVER
END
3.在C语言中调用汇编子程序
为保证程序调用时参数的正确传递,在汇编程序中需要使用EXPORT伪操作来声明汇编子程序,同时在C语言中使用extern扩展声明汇编子程序。
//汇编代码
EXPORTfunc1;func1为子函数名
AREAExample,CODE,READONLY;声明代码段Example
func1
ADDR0,R0,R
arm汇编编 相关文章:
- ARM汇编编程基础之四-ARM汇编伪操作(11-27)
- ARM汇编编程基础之三-基本寻址方式与基本指令(11-27)
- ARM汇编编程基础之一-寄存器(11-27)
- ARM汇编编程基础之五-ADS开发环境的使用(11-27)
- ARM汇编编程基础之二-流水线对PC值的影响(11-27)
- ARM汇编编程基础之六-其它寻址模式与其它指令(11-27)