蚂蚁的窝 2013-04-22
一.实验目的:
理解汇编的编程结构,有助于学习ARM汇编与C语言的调用关系,熟悉堆栈的调用关系.
二.实验环境:
TX2440平台
三.实验工具:
ADS1.2 + AXD + JLINK调试
四.实验步骤:
1.在ads 上建立新工程,增加两个源文件call_C_func.s 和 func.c
1)call_C_func.s源码
;我的assembler程序,EastonWoo procedure
area init,code,readonly
import add_8
import main
export assembler_add_4
export assembler_add_5
export assembler_add_8
entry ;一个进程中至少有一个.
start
ldr sp,=0x33ff8000 ;程序有效开始指令地址:0x30000000,,堆栈设在内存里面,也就是大于0x30000000,注意不要跟代码区冲突;
;如果设成0x1000,是写不进栈的,读出来是0xFFFFFFFF.
;********************一:汇编中调用C语言函数:***************************
stmfd sp!,{r0-r3};start看作子程序,保护好r0-r3 压栈
;5个实参:优先使用ip,即r0-r3,其中ip.ip作为第5个实参
;6个实参:优先使用ip,lr,即r0-r3,ip,lr.其中ip,lr分别作为第5,6个实参.
;其中lr会在子程序压栈,出栈.
;7个实参:优先使用ip,lr,和一个保存局部变量的寄存器v1,即r0-r3,ip,lr,v1.其中ip,lr,v1分别作为第5,6,7个实参.
;其中lr,v1会在子程序压栈,出栈
;8个实参:优先使用ip,lr,和二个保存局部变量的寄存器v1,v2,即r0-r3,ip,lr,v1,v2.其中ip,lr,v1,v2分别作为第5,6,7,8个实参.
;其中lr,v1,v2会在子程序压栈,出栈
;如此类推...
;15个参数开始就更复杂了.因为所有的局部变量寄存器全用了.4+2+8=14.以后有时间再来研究.
;8个参数例子,调用C函数例子.
mov v2,#8
mov v1,#7
mov lr,#6
mov ip,#5
stmfd sp!,{v1-v2} ;压栈,先压8,7,也就释放了v1,v2寄存器.add_8里会用到这些寄存器.
stmfd sp!,{ip,lr} ;压栈,再压6,5,也就释放了ip,lr寄存器.add_8里会用到这些寄存器.
mov r3,#4
mov r2,#3
mov r1,#2
mov r0,#1
bl add_8 ;返回值为r0
add sp,sp,#16 ;出栈.
;********************二:C语言中调用汇编函数:***************************
mov v2,#8 ;8个实参进栈.这里就不重复叙述了.
mov v1,#7
mov lr,#6
stmfd sp!,{v1-v2} ;压栈,先压8,7,也就释放了v1,v2寄存器.add_8里会用到这些寄存器.
stmfd sp!,{ip,lr} ;压栈,再压6,5,也就释放了ip,lr寄存器.add_8里会用到这些寄存器.
mov r3,#4
mov r2,#3
mov r1,#2
mov r0,#1
bl main ;bl已经保存了b over 这个地址到lr.
add sp,sp,#16 ;出栈.
ldmfd sp!,{r0-r3}
b over
assembler_add_4 ;子程序直接使用r0-r3这四个实参.
add r0,r0,r1
add r0,r0,r2
add r0,r0,r3
mov pc,lr
assembler_add_5 ;子程序直接使用r0-r3这四个实参和ip这个第5个实参.
add r0,r0,r1
add r0,r0,r2
add r0,r0,r3
add r0,r0,ip
mov pc,lr
;这个8位的汇编函数相当于之前我们讨论的8个参数的被调用C函数的反汇编代码.
assembler_add_8 ;前4个实参,子程序直接使用r0-r3这四个实参;后4个实参分别由ip,lr,v1-v2都是在栈里得来.
stmfd sp!,{v1-v2,lr}
add ip,r13,#0x14
ldmia ip,{v1-v2}
ldr ip,[r13,#0xc]
ldr lr,[r13,#0x10]
add r0,r0,r1
add r0,r0,r2
add r0,r0,r3
add r0,r0,ip
add r0,r0,lr
add r0,r0,v1
add r0,r0,v2
ldmfd sp!,{v1-v2,pc}
over
nop ;无用功.为了编译器不报警
end