EDA365电子论坛网

标题: ADS1.2 在汇编代码中调用C函数 [打印本页]

作者: mytomorrow    时间: 2020-10-9 14:57
标题: ADS1.2 在汇编代码中调用C函数

) P; X# O, D. L6 U对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回9 |& K; p% E: p

8 H/ L# N& ^" |' l6 l8 @. j0 c, I# J不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。* B  u, _" r/ G8 J
- S7 U( R/ U" s3 K
我们先讨论一下形参个数为4的情况.$ h3 ]0 a! f1 w# w5 h$ f# m
实例1:, a$ k2 P# v# z) W: _1 J' e3 L
test_asm_args.asm7 q6 L2 O7 Y  d
//--------------------------------------------------------------------------------% V3 l0 ~9 ^! r6 y
        IMPORT test_c_args ;声明test_c_args函数
7 v8 p" P2 `4 m! ^3 |# a        AREA TEST_ASM, CODE, READONLY
1 B4 _" `4 l8 x" q. c) y' G0 ]3 C        EXPORT test_asm_args4 q2 E' u( e: P4 J. b
test_asm_args7 J+ I' \. U" d% h: \) j
       STR lr, [sp, #-4]! ;保存当前lr
/ P: i8 f: |+ f- d/ Q5 E        ldr r0,=0x10       ;参数 1! d; ~/ g8 ~$ {
        ldr r1,=0x20        ;参数 2
4 ]* M. L! C7 H# S+ N* T        ldr r2,=0x30        ;参数 3
6 q' O  c5 R; v5 I/ g4 {        ldr r3,=0x40       ;参数 4
6 n8 N; S% x5 m% }        bl test_c_args      ;调用C函数$ U4 |8 l2 S$ ^& M- y
        LDR pc, [sp], #4  ;将lr装进pc(返回main函数)
- z3 u" \" B' X# r, O2 f        END
+ b8 O' h7 ^* r" F" A: mtest_c_args.c
$ p# u1 M+ L) f2 s. z( @//--------------------------------------------------------------------------------, L% c; j8 F) f
void test_c_args(int a,int b,int c,int d)
0 T+ j* v/ @2 ^  G0 F# z9 j{* W$ P6 q  |* W: |* E
        printk("test_c_args:/n");
  ^. y% f4 `" p4 g& K- W        printk("%0x %0x %0x %0x/n",a,b,c,d);: A4 u& _* B& e, ^& J4 j
}
6 n0 W7 u, ~" Fmain.c
# d( V" n- l- m8 P5 b/ b//--------------------------------------------------------------------------------
, X6 `# E0 ?0 t9 s: M# r8 I3 ]int main()
! v- O9 j9 d5 M* ~* F$ G3 b3 `{
+ C" ]- b4 l0 E' D  a     test_asm_args();, A- B( `6 u5 \, y5 }: ^
     for(;;);
: T6 j3 p& s0 X7 d}
# r6 E6 @2 i/ T8 s9 Q( l
6 K, h9 U! L2 b3 i8 C程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.
& v3 S4 u4 |* m( k4 ^代码分别使用了汇编和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函数中。
8 k, D1 o2 C) Z( B- H5 h( z! ~$ k% |2 q
7 F$ T2 k$ K0 u2 a
如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?
8 {& o: r/ E7 J8 g实例2:. e3 x5 x1 U% j
test_asm_args.asm3 z5 l: P0 K% {" q0 i8 S+ o" _
//--------------------------------------------------------------------------------- S1 ^* x6 t6 h" C8 d* @
        IMPORT test_c_args ;声明test_c_args函数
% x1 U) v. I" A# c% Q  l        AREA TEST_ASM, CODE, READONLY
9 r0 O  T6 j( p- Q        EXPORT test_asm_args7 x' {4 [3 S6 P
test_asm_args
9 f5 `0 k7 t5 s: x7 m, x6 l3 y       STR lr, [sp, #-4]! ;保存当前lr
5 k/ u0 I9 E6 Y* ]' z2 W       ldr r0,=0x1 ;参数 1( q: W  |  a% H9 t( y
       ldr r1,=0x2 ;参数 2
0 B/ h0 I9 h* b6 H/ d/ ?, B/ g       ldr r2,=0x3 ;参数 3' ?, |+ V* k5 g- I# G/ J  @0 B! ]
       ldr r3,=0x4 ;参数 4$ x2 k# a  Q0 L. t
       ldr r4,=0x8
' v- d7 @1 D  f; ?  Y( \7 v       str r4,[sp,#-4]! ;参数 8 入栈
; T0 {, @7 G' h) \1 H       ldr r4,=0x7) A2 p: i+ I$ U+ [9 U, }# m5 u( A
       str r4,[sp,#-4]! ;参数 7 入栈  S7 `2 L( r5 D2 O
       ldr r4,=0x62 c. @) @9 w- t$ U5 X9 g
       str r4,[sp,#-4]! ;参数 6 入栈
* G9 z; z6 f* h       ldr r4,=0x5
% {* O/ I3 S! p# v# S       str r4,[sp,#-4]! ;参数 5 入栈3 R: @2 t* w. j6 U
       bl test_c_args_lots+ A* |1 H1 v9 ?% J3 R, d, J  y
       ADD sp, sp, #4     ;清除栈中参数 5,本语句执行完后sp指向 参数6
( Z, [4 t* w8 a( P, |+ ?       ADD sp, sp, #4     ;清除栈中参数 6,本语句执行完后sp指向 参数7  f6 j6 J% ^0 }2 Z) z- ]
       ADD sp, sp, #4     ;清除栈中参数 7,本语句执行完后sp指向 参数8
' G9 \( P& \/ S5 c3 ~6 X       ADD sp, sp, #4     ;清除栈中参数 8,本语句执行完后sp指向 lr) q# L: T* m2 U
       LDR pc, [sp],#4    ;将lr装进pc(返回main函数)
) i2 g) E0 s) K. I8 r3 ]        END
) b8 N2 N6 S3 |$ T/ d  Atest_c_args.c
; r" e' O9 l/ M4 ?5 s! a//--------------------------------------------------------------------------------6 @5 n  \# i+ E# r: G9 ~
void test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)! u& R$ W3 v% j. o. `. N1 \
{
2 x1 \  v8 P" A8 E6 g+ {1 S( ~5 k* K       printk("test_c_args_lots:/n");
7 r4 O; F9 E/ c- \8 K; z  |' e% Z       printk("%0x %0x %0x %0x %0x %0x %0x %0x/n",5 D; m- v( Y* o3 g  K6 W; C2 K
              a,b,c,d,e,f,g,h);
+ g0 V4 q2 l+ C  _+ j}: w" r$ q) M  A2 V+ Z& g, f
main.c' B4 Y4 C! F, s9 ?
//--------------------------------------------------------------------------------
0 ?% d9 ~1 W9 s, h" b1 \5 |int main()
; ]+ i/ H6 Z5 }6 b{9 g% J3 i5 m; C- K
     test_asm_args();
4 U+ r1 b8 o, J7 n; `5 T     for(;;);
4 @% p6 X: W7 H$ Y}
7 F$ C# H" C- a3 u. ?, w7 D
3 T4 @, i6 f6 A0 b. }这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。
9 `7 }  P0 V: I- F. t5 j在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。) r, I* B2 V7 I, u
直到调用test_c_args之前,堆栈内容如下:
3 D/ F7 Y" E+ T5 P1 n) Z/ Ssp->+----------+
; N# F2 Q- @( ^; p        |  参数5  |+ a# |) @( }+ D& N+ [
       +----------+. ~8 Z- I% ~1 G" A% Q
        |  参数6  |
5 n; S; X: J* i' \2 g       +----------+
: W& J' p" i6 }: v2 Y' E. M# O        |  参数7  |/ y5 b) }1 J) @: k
       +----------+5 A7 b. R& }" {9 O: |# m
        |  参数8  |' F8 O% _+ A, i5 V( |
       +----------+- @8 q7 b0 o6 C1 s) X
        |     lr      |
# Y0 h( {' W% b  Q       +----------+
+ H' b' I) d+ S4 j, F. u% c$ K$ Ltest_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:
) B7 u. w6 w9 f5 t3 }6 ~4 p/ T$ y       +----------+
5 H- J* ?4 h2 y, [9 ^+ ?        |  参数5  |
' v8 l9 X- E$ Z& q% l       +----------+  @  b4 t- X; a9 c' c* t9 q% b
        |  参数6  |  j( p; Z6 @6 Q% C2 {# _+ y- E* H' ~
       +----------+3 |7 O) q; _3 L2 ?7 c7 q2 u4 j
        |  参数7  |
+ m/ F3 |$ F" v! o0 I       +----------+
9 R) }4 ?9 P1 k1 n: S# b        |  参数8  |
( T& P( C2 Q/ b* y' ~. I# Bsp->+----------+3 X6 X" j7 J4 ^5 m% R
        |     lr      |8 t; A4 Y+ d8 `5 E9 Q
       +----------+
作者: regngfpcb    时间: 2020-10-9 15:46
ADS1.2 在汇编代码中调用C函数




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2