找回密码
 注册
关于网站域名变更的通知
查看: 422|回复: 1
打印 上一主题 下一主题

ADS1.2 在汇编代码中调用C函数

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-10-9 14:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

2 a. T5 ]' ]1 B, N对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回. D3 Q$ I: h8 z' w! e5 {% Y
8 d; J$ G! t# U  o9 z$ t3 Q! x
不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。: _: j% X4 z: _; \
8 N; U2 a8 ?+ u- ~  f; t" ~$ B
我们先讨论一下形参个数为4的情况.
2 \8 S- H0 m1 Q' \$ j& J" I7 _9 W3 t实例1:
6 T$ b" T, O1 otest_asm_args.asm* F4 i9 |6 {& t# S% z$ z" u
//--------------------------------------------------------------------------------: w7 ]4 x4 V/ \+ t# @9 U# u
        IMPORT test_c_args ;声明test_c_args函数2 N& P' D. u: f0 [5 p$ X
        AREA TEST_ASM, CODE, READONLY% r. @  G$ ]+ k) T' ^
        EXPORT test_asm_args( n4 K! c9 I4 H
test_asm_args
+ p: V" T$ ?$ i- B/ d, t- {* C) d       STR lr, [sp, #-4]! ;保存当前lr
8 c' H) p# p  V8 C        ldr r0,=0x10       ;参数 1- b$ ^+ k- m. b2 F
        ldr r1,=0x20        ;参数 2" C' ~; |6 q  W) P- e
        ldr r2,=0x30        ;参数 3
5 \8 T% `7 K; P" X, K8 |7 c        ldr r3,=0x40       ;参数 41 _( J+ ^; V7 G8 m2 c, {
        bl test_c_args      ;调用C函数3 r: }% o( G3 F4 u* I) W% Y
        LDR pc, [sp], #4  ;将lr装进pc(返回main函数) % y5 ]" u* n8 S9 T
        END
; U7 I& i% a6 r( ~# Jtest_c_args.c
4 D! e0 F( A4 b( w. D1 o//--------------------------------------------------------------------------------* d( h  j3 a* k, P9 r
void test_c_args(int a,int b,int c,int d)
5 y0 C% a; u0 q0 J; }" ^; b, {" T{
, B4 \7 P  i- {( m% v9 b6 F        printk("test_c_args:/n");
: ~) D: G8 [3 v- S) O        printk("%0x %0x %0x %0x/n",a,b,c,d);
' L5 ?. t% X# A5 f/ ~4 D9 f}
  u7 h1 `1 t7 N3 N% Amain.c
: Y. B) W6 z4 v9 V- m) w  U. Z//--------------------------------------------------------------------------------
  x; k/ v% N) O4 f& ?8 V+ Tint main()* ?8 Y9 P& K7 N( W+ p; r$ B: s
{6 X# N- F1 L/ _! Y9 c/ v, Y
     test_asm_args();
3 m! l/ L$ B5 R4 v     for(;;);4 }, C0 n0 B7 _* y8 a: l. ~
}: M7 z& n8 {8 w7 o! y# N

- f- d) M" j% u) ?程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.
& u0 J* N2 c# Z3 |4 P) Q代码分别使用了汇编和C定义了两个函数,test_asm_args 和 test_c_args,test_asm_args调用了test_c_args,其参数的传递方式就是向R0~R3分别写入参数值,之后使用bl语句对test_c_args进行调用。其中值得注意的地方是用红色标记的语句,test_asm_args在调用test_c_args之前必须把当前的lr入栈,调用完test_c_args之后再把刚才保存在栈中的lr写回pc,这样才能返回到main函数中。: |0 @4 a9 n; c- [7 d, ~4 V8 x
! h2 l- U; W( G6 \8 d; ]; S6 k6 x

0 w* X# H/ y# |; A9 b: F+ }如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?% r# r2 e+ \" ^2 x* E: G3 N
实例2:- v( [) d/ G) g
test_asm_args.asm
2 |$ X4 i1 Z) g! L//--------------------------------------------------------------------------------
2 O5 o  E+ ^& u0 a3 P  C' k2 |        IMPORT test_c_args ;声明test_c_args函数
: F& [0 L2 t9 u$ c) L' n) {! C        AREA TEST_ASM, CODE, READONLY
0 U. p* [: H1 _" u# c8 u' d* Y' l! n        EXPORT test_asm_args
6 }: g9 y* @' L1 z) |4 vtest_asm_args
7 ]5 {$ B" h( k6 D1 X) @! x0 \% K       STR lr, [sp, #-4]! ;保存当前lr" D0 Y" V- [0 K8 C. ]3 p9 k% k
       ldr r0,=0x1 ;参数 13 a6 z1 O8 U8 g) |( X( T
       ldr r1,=0x2 ;参数 20 A, D) T. Y/ [8 F2 I2 C. F, s
       ldr r2,=0x3 ;参数 3
  e8 J) L' u0 k& e5 k! E       ldr r3,=0x4 ;参数 42 U- k9 M# Q5 I! @, r3 ^- A4 \; ~7 ^
       ldr r4,=0x8
+ `0 \. V; s/ D8 p7 R       str r4,[sp,#-4]! ;参数 8 入栈
. a0 P$ C# K9 f  g& W3 ?       ldr r4,=0x7
9 {" G7 |- U# \* k       str r4,[sp,#-4]! ;参数 7 入栈) _  N+ [! w. r: G. e. b
       ldr r4,=0x6
# c8 |; |7 {/ p       str r4,[sp,#-4]! ;参数 6 入栈
/ ~% `* v- L1 d% s6 U( w       ldr r4,=0x5* z0 L, @: B% R0 @
       str r4,[sp,#-4]! ;参数 5 入栈, Y! N) n2 J# i* R; ~$ V
       bl test_c_args_lots
- Z" k& ]( E- r  I9 b: Z% {, d! N% a3 M       ADD sp, sp, #4     ;清除栈中参数 5,本语句执行完后sp指向 参数6
7 n8 N9 t# M- ?% k# q       ADD sp, sp, #4     ;清除栈中参数 6,本语句执行完后sp指向 参数75 L2 W: f. f! C  {6 Y7 K, a
       ADD sp, sp, #4     ;清除栈中参数 7,本语句执行完后sp指向 参数88 Y0 H3 A" i, U+ h4 f
       ADD sp, sp, #4     ;清除栈中参数 8,本语句执行完后sp指向 lr
9 [3 A& d+ p+ s8 b# h3 D8 T. v       LDR pc, [sp],#4    ;将lr装进pc(返回main函数)
2 M) r& K6 b4 }+ m& ]        END
) j6 t1 f) V! S; T, H( v. g* Atest_c_args.c
* s& g& t/ T, Z  X//--------------------------------------------------------------------------------
1 J% m* |+ F8 S2 ^6 h) Lvoid test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)
# v% l* k1 R  X( u% m( h{- b* N9 ~: Z& F2 F9 e$ f# ]" O% o* @. ]& c
       printk("test_c_args_lots:/n");
- L% _( d9 l8 q, A+ ~/ n: `       printk("%0x %0x %0x %0x %0x %0x %0x %0x/n",
. W8 v5 k' }7 x4 d+ X              a,b,c,d,e,f,g,h);
0 N+ D  ?, X: l}! E( Z) f# d. A( d( [
main.c) z# q5 q% T( Z& g/ @
//--------------------------------------------------------------------------------
& }1 q9 z7 L/ ^7 }; Q/ Oint main(); y, Q1 j) I8 ]' U3 K& ]
{3 ?& @& i" F4 C6 o: M" n
     test_asm_args();9 f$ N. M9 @2 @) F
     for(;;);
" X) o9 v  C; Z) a  k! z}* K6 O1 d9 F( v, s! H  V0 l

7 l* N1 n( S( Q4 n0 A* R' _这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。
6 O. D7 o% \4 b; f3 K" C7 e在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。
. A) p# k" r% G直到调用test_c_args之前,堆栈内容如下:. b6 i& Q& u5 {/ Q! h
sp->+----------+
5 b; a& w$ o- M) q        |  参数5  |  T' |9 b' k8 k, D* ?
       +----------+
1 B6 q( K5 z" t5 K4 m5 g0 y+ D        |  参数6  |
& q; J! @5 n% x" E       +----------+
7 p, v% q# h* W# _        |  参数7  |5 n$ d5 E) u! p  C
       +----------+9 e+ N0 F2 B2 P: `$ ~2 l
        |  参数8  |
8 N7 P5 K' a9 x/ N2 f       +----------+
) j5 T; y# ^2 |! [        |     lr      |8 r6 }" T! a, H' ]8 M; v
       +----------+! y& v# F" O! Q3 s
test_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:. U1 H$ A; x% ~$ ]
       +----------+
; v: {8 p% G) }+ P7 I9 J        |  参数5  |( X- V& L2 Y" O3 f5 |+ [1 i& P
       +----------+. B6 r3 w' c: G, O! ^& @
        |  参数6  |
. ~1 C1 p0 d& G% F# O       +----------+
( D; C7 P* b& |  ^  X2 h        |  参数7  |, J5 i4 T2 z/ R! V3 L% B
       +----------+
% ]8 `* k3 h$ I        |  参数8  |
0 f9 _  K0 @+ G, }sp->+----------+) c# ]* y- a' Y/ Q$ G( B7 Q
        |     lr      |3 o: B' p1 W1 G" g" m9 _
       +----------+

该用户从未签到

2#
发表于 2020-10-9 15:46 | 只看该作者
ADS1.2 在汇编代码中调用C函数
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-26 15:09 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表