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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x

/ ?( o3 l  z* X& I7 D' C$ p对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回( y, `4 m6 c- a: I' |2 {! Q, L
0 U1 Y! e$ b( F  e5 X
不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。
( E* Z- @  r3 j- R
+ H2 O' p- E/ ~+ S我们先讨论一下形参个数为4的情况.4 Q4 T2 @3 m7 [
实例1:7 T$ l( Q) L/ d: E. K; B, J. u, R/ {
test_asm_args.asm# u/ M+ [: I* \; x0 N1 s
//--------------------------------------------------------------------------------9 r8 R1 u4 I3 \6 a) Z3 w
        IMPORT test_c_args ;声明test_c_args函数. Q2 x) K0 i# G  \7 d' s
        AREA TEST_ASM, CODE, READONLY
- O, X% n# p! H# D  }/ H        EXPORT test_asm_args
" D7 V  r, _1 N9 ^  B8 C+ N6 ktest_asm_args8 e: ~" o- ^; I' E3 l, o
       STR lr, [sp, #-4]! ;保存当前lr* \  x2 e) f3 x) t9 k
        ldr r0,=0x10       ;参数 1
. k; Y% z8 \0 u0 Y( J# l        ldr r1,=0x20        ;参数 29 f+ U# h6 I! ^7 U& c7 f
        ldr r2,=0x30        ;参数 3, w. p' a8 Y8 g5 V$ Y4 ^. C
        ldr r3,=0x40       ;参数 4
) m9 T6 U$ C8 h! ^1 a: B        bl test_c_args      ;调用C函数% ?# P' P1 k5 z# A' E/ J4 Y
        LDR pc, [sp], #4  ;将lr装进pc(返回main函数)
- r( f: u  w! j: j1 m        END
+ R8 n: v, T& n! I3 ]5 d( ntest_c_args.c
- H/ k% Y3 ~' n$ y2 @9 g//--------------------------------------------------------------------------------
3 y7 B: x+ K( k' G& ]0 |4 J# t' Cvoid test_c_args(int a,int b,int c,int d)* `. G$ ^3 `7 \1 K2 F
{; L/ f2 Q4 v+ T3 y
        printk("test_c_args:/n");
# G9 S: Z) U5 P& s: I9 L: Z        printk("%0x %0x %0x %0x/n",a,b,c,d);+ K# u  o9 a: N/ Z' h0 y% c7 F
}
9 e& }7 ]- ~/ m" P, Y0 l* Umain.c
0 G5 ?6 l% O: p  S  `//--------------------------------------------------------------------------------
# S$ l- ?4 h$ v( dint main()) [, N! n& C% o) ]
{
1 w/ W& ]7 u% x5 r; y0 m6 Q, T     test_asm_args();
0 ]! C' Y2 j" V! y' X6 v: d6 F& A     for(;;);
, N. E2 r- }, c8 J( u5 `" P}% K9 ?5 J0 x9 ?: \) E

- w+ C9 {$ r9 F) e3 S5 S程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.# A7 \5 u0 v. w4 R8 ~% 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函数中。
+ M% i% b- C. J( {0 v( ^5 [$ X2 ?) E
2 n) J3 g4 T/ }2 k
如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?, z4 [/ N9 n, Z
实例2:
% c9 G* B: [& J' f5 ~' |) Btest_asm_args.asm
+ V4 P+ c4 F$ O: _/ ?7 q% W7 F5 b& l//--------------------------------------------------------------------------------
; b2 p, @; h8 J/ E        IMPORT test_c_args ;声明test_c_args函数/ H5 Q0 L; x/ h
        AREA TEST_ASM, CODE, READONLY* a+ [6 K1 K. F9 Z* Z$ m8 ~: }
        EXPORT test_asm_args
& t9 P8 M  D* Y/ j+ t! E  e' stest_asm_args
9 y, _6 I+ V' T- Q( S0 B       STR lr, [sp, #-4]! ;保存当前lr
0 h; c( f0 M& K7 Z8 u       ldr r0,=0x1 ;参数 1
: h; _$ m: s: |- h       ldr r1,=0x2 ;参数 2
3 i+ I* P. z- b  f0 `7 g. x, c. d       ldr r2,=0x3 ;参数 3" N3 _0 i( }8 `$ }- a& ^& q
       ldr r3,=0x4 ;参数 4
4 B% H" r& V: N7 c# {$ V+ D+ D       ldr r4,=0x8
5 B. C& T& t0 y. t4 ?& z+ S5 E       str r4,[sp,#-4]! ;参数 8 入栈
4 ~$ l8 H. |7 m' S1 d* f9 O$ |       ldr r4,=0x7
+ _  f: C5 N9 F" n       str r4,[sp,#-4]! ;参数 7 入栈
; C) S5 ^; v2 p# @9 z       ldr r4,=0x6
5 t1 |( _! T9 L% s       str r4,[sp,#-4]! ;参数 6 入栈
8 q* Y0 ]7 _4 {/ y+ X7 j& z2 O       ldr r4,=0x58 t: O- m. C# O! F+ J8 X0 }$ w
       str r4,[sp,#-4]! ;参数 5 入栈( B( e) n  b/ ^% R" P
       bl test_c_args_lots
4 @- X3 N6 J. u* F       ADD sp, sp, #4     ;清除栈中参数 5,本语句执行完后sp指向 参数6
) P3 b8 @8 Z+ o9 }! t( v1 U       ADD sp, sp, #4     ;清除栈中参数 6,本语句执行完后sp指向 参数7, e2 u  t% k+ F( p3 T. K
       ADD sp, sp, #4     ;清除栈中参数 7,本语句执行完后sp指向 参数8
" R6 I% V& ^1 \! m; j, g: a) x       ADD sp, sp, #4     ;清除栈中参数 8,本语句执行完后sp指向 lr7 w, Y9 b2 g- b
       LDR pc, [sp],#4    ;将lr装进pc(返回main函数) 9 Q* n; n3 ]7 H) @* J$ }
        END7 l! Z: a6 n3 ^; f9 W' T
test_c_args.c1 e" }! J$ K# h0 {* n5 ~, l
//--------------------------------------------------------------------------------
/ W" Z- h& p  t* ?; Ivoid test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)
0 Y2 H8 P, h. V8 H# c$ Q{
7 C/ g; T$ F: P' v$ \       printk("test_c_args_lots:/n");4 H, J0 h3 t0 R- z+ R
       printk("%0x %0x %0x %0x %0x %0x %0x %0x/n",; h8 Q* b+ e: q" M3 G# U2 j
              a,b,c,d,e,f,g,h);2 [" O* B% D: y1 F
}4 _! }' C. E) @; j
main.c: j; w/ {4 }0 s# @: a7 Q
//--------------------------------------------------------------------------------% x0 Q: O# t  M) @# g- r
int main(), _- v( t) B) H/ ?6 U$ c
{
2 t% c; b/ h+ {" W$ Q     test_asm_args();9 O% o; @1 Z) p* r' R, [# H) q
     for(;;);
7 D$ [* k- W4 m+ Y6 P6 n# s: V}
9 @% v4 p% f/ N( n* w
7 @& ~5 w: ^7 F3 g* W# j1 p/ j这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。" F0 m% ]" \) T# x4 J
在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。+ j% \6 w' {, C2 }$ I
直到调用test_c_args之前,堆栈内容如下:$ R2 s' @* _" m" T# n) d
sp->+----------+
9 l- u+ \. i! @$ _6 L; N! C        |  参数5  |
! b7 b  v0 u" a, F       +----------+' O. l$ O. X. _" _5 D. t) J
        |  参数6  |5 j) R& Q8 n; H
       +----------+
$ m  |" L* u+ u* _        |  参数7  |7 T2 R! P( t! V* O3 ]* @3 h; C
       +----------+
; x* ]' E) h2 u( ]2 y" Y        |  参数8  |5 p& N( d1 C7 ?- O; Y
       +----------+1 k* x& T0 w  _; Z+ U) r
        |     lr      |4 w& N: g0 g( `: }4 y/ d2 H
       +----------+( i* T! P, R2 B* Y1 J) @2 ]7 X
test_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:
2 N1 C* [4 l4 q3 Q7 ~9 x% W) l2 }       +----------+' k* W' U( D2 ?
        |  参数5  |7 Y1 g& p$ R" Z8 M1 _* O+ O
       +----------+& ~) `! p: r6 J4 P5 ?5 ]! R
        |  参数6  |
, S. V- ^# `- G9 W       +----------+
0 }& o: e: {8 j  t( s        |  参数7  |9 R! u& m% n, t: ^3 g2 D. ^" x
       +----------+
8 n! N' @% j+ R- t: v        |  参数8  |
( ^3 G/ x- r% Y, \, O7 jsp->+----------++ N1 ~" }5 |' u/ w! A$ ]3 ^/ ^% q  O" R
        |     lr      |
8 {+ U) w- j% R( t' j- h       +----------+

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-25 00:54 , Processed in 0.140625 second(s), 23 queries , Gzip On.

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

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

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