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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
( k/ l, r4 G' O
对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回6 r, j: I% j6 I: t; C0 d0 b8 Y0 x
. Z& ]2 ^; |1 M
不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。
8 @5 U# [- J7 c! `9 Z* P. O: N) t1 U! W- c: W4 K
我们先讨论一下形参个数为4的情况., L! H" w' E, s. `- B* n% X
实例1:$ ]& v2 `- v* R& \$ w0 g  c
test_asm_args.asm- n* T& O9 ]+ ?+ n# x
//--------------------------------------------------------------------------------" \4 Z1 `9 L4 M4 O% N" `  s
        IMPORT test_c_args ;声明test_c_args函数( n( H- {) ], j! x
        AREA TEST_ASM, CODE, READONLY
4 ^  q5 U2 q  O$ V, x2 s( M- X        EXPORT test_asm_args
4 o8 B: z- C. j* k( n( n4 Y# Ttest_asm_args
; ]4 @. x+ [: I9 H  X- d' W       STR lr, [sp, #-4]! ;保存当前lr0 p+ F% q& f2 g  Z; m# F- ?
        ldr r0,=0x10       ;参数 1
  }/ g( n, L! i  m$ x/ C        ldr r1,=0x20        ;参数 2* T5 W7 [% n+ ~$ }3 \' C* E
        ldr r2,=0x30        ;参数 3+ @, V' ^- d0 O9 T2 _
        ldr r3,=0x40       ;参数 4
! E4 P$ U! n4 n4 O  y        bl test_c_args      ;调用C函数: @8 y3 H7 `8 T# w0 u
        LDR pc, [sp], #4  ;将lr装进pc(返回main函数)
, [% E) i# c8 u# ]& X        END# S9 k! ]9 |) z1 E9 S8 K
test_c_args.c1 g6 U* D0 ?5 u7 E6 ?& e& }
//--------------------------------------------------------------------------------
0 C% s' y# p2 e; U+ @$ Mvoid test_c_args(int a,int b,int c,int d)
; U( Y0 p/ N  ?& h. k+ g  c; ]{/ a# H. Y6 G* j; U( U) z% K' B) r
        printk("test_c_args:/n");
  N( Y. Y; r2 I        printk("%0x %0x %0x %0x/n",a,b,c,d);/ t) v5 w( O' l. k/ K
}
7 u# x  ]0 G" M: t  A  L: r, |6 tmain.c
" o. N9 J2 {8 I, v; k" d1 B' B//--------------------------------------------------------------------------------$ x$ U8 t5 n, F- ~
int main()
) C8 A! `) ?' a9 a7 `% t$ D: R{
, `2 [8 g+ s- u$ U& d, `     test_asm_args();- b! T* d) X3 w0 \& {* G
     for(;;);
5 i7 }4 E* }* ?- s}
- X3 U1 U. `: [0 t: h
' p; P3 `7 ]0 S程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.
! F! ^/ _0 @) |& L& K代码分别使用了汇编和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函数中。- [; Q7 f0 ?, O2 x

. [2 C( ?' x  w& a( b- Z
- C; S1 Y  i6 u4 v- D4 g7 N( v如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?
: O: D* I& S5 E8 s: j+ O* e实例2:) l* y: K; W8 y0 Y% z
test_asm_args.asm  e5 }2 c: L; |2 i. Y1 c
//--------------------------------------------------------------------------------
  |! ]0 c9 o4 {& |+ @, Z        IMPORT test_c_args ;声明test_c_args函数$ U+ e* x  S8 b/ S* u
        AREA TEST_ASM, CODE, READONLY
# O. p# N) q# Z5 U        EXPORT test_asm_args
6 U+ V  ~- ?  n' q1 M" Y- W5 Ttest_asm_args
* }+ [% n& b* Z# e) v" v       STR lr, [sp, #-4]! ;保存当前lr; r: p4 Z  N2 ^0 q/ J+ `* {
       ldr r0,=0x1 ;参数 10 i( U4 m. T$ p% h( K# g5 @
       ldr r1,=0x2 ;参数 2
# W; u9 q( z1 h3 x7 O) l( ?       ldr r2,=0x3 ;参数 3
/ s, L- y' x9 L6 `# S0 \       ldr r3,=0x4 ;参数 4
; R* W- E4 w: a0 R4 L$ R       ldr r4,=0x8
/ W0 I8 o4 E, o0 i3 t3 [       str r4,[sp,#-4]! ;参数 8 入栈
/ T! _2 I6 S6 x4 y1 _       ldr r4,=0x7+ v7 R0 K- o0 x& T4 E
       str r4,[sp,#-4]! ;参数 7 入栈
. T8 B/ @  K0 D) `- e1 A       ldr r4,=0x6
' y& N- S# O3 q+ Z8 u1 f       str r4,[sp,#-4]! ;参数 6 入栈; W- i% R, I8 A- W
       ldr r4,=0x5( n7 r% N2 v1 {$ x. C+ z. j
       str r4,[sp,#-4]! ;参数 5 入栈
8 ^) Q: Q7 A& B       bl test_c_args_lots
3 u4 T% ]7 T( P6 g* }) h3 Q       ADD sp, sp, #4     ;清除栈中参数 5,本语句执行完后sp指向 参数6
; B/ Y% |9 k+ p. S1 {       ADD sp, sp, #4     ;清除栈中参数 6,本语句执行完后sp指向 参数7
+ _& }& m% s3 N5 C7 f0 Y( I       ADD sp, sp, #4     ;清除栈中参数 7,本语句执行完后sp指向 参数8, ~6 S! J- Y* O$ H/ j) `
       ADD sp, sp, #4     ;清除栈中参数 8,本语句执行完后sp指向 lr; J% A8 @* D- H8 p* Q9 u* Q2 e
       LDR pc, [sp],#4    ;将lr装进pc(返回main函数)
  z% }# }, L5 W  f/ l        END
. Q8 [, }3 k  o# Btest_c_args.c+ @# T1 |. l. _% q
//--------------------------------------------------------------------------------- ?. @3 \4 Q5 [2 H" Q# `" f
void test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)8 t0 Z$ K$ u; U! M
{
2 z& C) I" V/ b' G  @$ s       printk("test_c_args_lots:/n");
; V8 X6 }$ O( x+ `- T/ ?3 C1 R) Q       printk("%0x %0x %0x %0x %0x %0x %0x %0x/n"," H5 O4 r9 n9 p4 c- H
              a,b,c,d,e,f,g,h);
2 i0 S+ A+ b  x/ y8 _}* ^# t3 C% O) {- I: a& [0 U& b. E& Q
main.c
3 V- j. `% m4 P- M: s//--------------------------------------------------------------------------------9 S: \0 E  t7 \% _8 d2 x" V( d2 f
int main(). D" @5 I* h$ z: z3 F
{8 V! l1 j3 w1 z3 P; R9 _. c
     test_asm_args();% ]" k, u6 O/ c0 q" X
     for(;;);
) P6 H2 x; ]' R}' I. W! {3 l( P, {" Z: _
0 `7 m7 F* k9 n8 q1 |  q2 }
这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。
( x0 U! ~$ N) x8 V( A在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。( z8 u, \5 \6 H9 x+ T) E
直到调用test_c_args之前,堆栈内容如下:
* [/ {  J: h5 k1 k) P* Osp->+----------+4 f2 L! b9 H5 Q- T3 X( J" |
        |  参数5  |5 s4 w! y$ b7 ~. P! E9 o! b5 Y0 D3 l
       +----------+
4 r3 o- h" I' H. R$ ?7 q7 l. a        |  参数6  |
! j5 _+ R1 F* d$ P4 ]/ ^: \& ]       +----------+
5 ^% o8 }7 v; f+ B$ Q" m( z        |  参数7  |
- K. n& B/ S  t& X8 h       +----------+
, U) v; I  S0 {# L6 ^' ?        |  参数8  |0 p' Z$ m3 {2 W1 E% u3 N- z' I
       +----------+
! N# O; o  r" b0 F( q% X/ P        |     lr      |
* p/ n! C" x; [3 h& \       +----------+7 h% O9 B3 G& v1 R( \  a& z" h
test_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:
) Z" l# ~8 j2 C( z       +----------+
) q- `# P/ B+ @- U. {/ X        |  参数5  |$ Q1 V8 ?! ?* [0 k/ ~. Y7 _& p
       +----------+* B- x" c$ E8 v: k1 D
        |  参数6  |! U- |/ r# W. [8 \$ p
       +----------+
: F+ s8 W; H/ V4 {- V        |  参数7  |
, s1 r; g, @& j       +----------+, o! ^8 D, o+ n5 x5 K
        |  参数8  |2 C! [: b$ W* U, h( b4 X. a
sp->+----------+
) U: D6 Z8 U1 U, m        |     lr      |6 c6 N+ b* I3 L. n4 M5 F0 O* b" i
       +----------+

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-24 21:36 , Processed in 0.171875 second(s), 23 queries , Gzip On.

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

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

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