1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 汇编语言调用c语言ads ADS1.2 在汇编代码中调用C函数

汇编语言调用c语言ads ADS1.2 在汇编代码中调用C函数

时间:2022-09-03 23:41:02

相关推荐

汇编语言调用c语言ads ADS1.2 在汇编代码中调用C函数

EDA365欢迎您登录!

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

x

, U) b) }+ U8 \" d/ v( \$ ~T对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回9 O; |6 z8 ?, g- u

" ?# B! P0 k+ [+ p1 d+ w$ U9 {

不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。

" e- U7 W" f3 ?3 o; N

9 _/ R1 ]2 \$ Y# D2 b# c& U$ X我们先讨论一下形参个数为4的情况.

/ u6 P5 t. W( Q- E( I实例1:) p2 U- M; [/ k& F

test_asm_args.asm0 \: b" C7 M7 q& }& l1 \2 @5 M. C

//--------------------------------------------------------------------------------( vu' l& a3 z* e

IMPORT test_c_args ;声明test_c_args函数/ G# A" s& _8 k; C

AREA TEST_ASM, CODE, READONLY

: D& M6 M6 y3 `* t" b EXPORT test_asm_args% g) p- L! c2 J8 m6 ]

test_asm_args( G+ m% Y, s' B# a% E1 V" }

STR lr, [sp, #-4]! ;保存当前lr# |. [1 x# YE* h* i( }

ldr r0,=0x10 ;参数 18 h* ^& r, s* j4 Z2 F2 P

ldr r1,=0x20 ;参数 2% J% I( |) Z- V* x& i

ldr r2,=0x30 ;参数 3* j) R3 H4 `a. G4 W/ k$ R% y

ldr r3,=0x40 ;参数 4

! @' T: w, i5 ?4 \ bl test_c_args ;调用C函数- [. P( O& r. [1 f; K( @

LDR pc, [sp], #4;将lr装进pc(返回main函数) 8 L/ C" U% g: s

END% ~0 |2 C, L" f" b! O0 Z% n9 P

test_c_args.c

1 aA5 z" `# U& b) M" M//--------------------------------------------------------------------------------( d1 FX4 \- S" h) h# R3 ]& o- [5 C

void test_c_args(int a,int b,int c,int d)

' u- j* f+ d* p6 d{& \2 Z- F- B1 u% w

printk("test_c_args:/n");

" `1 R9 K9 M5 V' s1 z, e printk("%0x %0x %0x %0x/n",a,b,c,d);7 D4 ~4 `3 r- d, j

}4 W! t2 ^2 Q, q' z: y: ]8 A

main.c

9 d& n/ K+ Z! q" Po//--------------------------------------------------------------------------------

1 h& J: a4 N2 _$ q7 f! [0 eint main()

3 O( `# U% E7 u2 [4 q3 U( V. L{

* `4 O5 |/ f! C5 L2 I3 b test_asm_args();

6 |) E1 c3 N7 Q9 g for(;;);" I( g$ W5 O. \0 t

}

" p1 ]; C, L; {3 l0 ^

4 g7 x4 X' OJ程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main." ^1 {5 `' [0 O8 h' 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函数中。% }6 \( Z$ L# g, ^

8 o" T" f" T7 e* d3 U" x, K; a+ m5 j, L/ c; K/ t; f2 d0 ?

如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?' F0 J" v0 F$ a7 n2 S

实例2:

, q; h! b, v+ ktest_asm_args.asm

7 B# `8 B6 K0 j; n4 Q//--------------------------------------------------------------------------------3 d0 C( `9 q' o% T

IMPORT test_c_args ;声明test_c_args函数

! [, @$ A3 B+ X/ W& K" P AREA TEST_ASM, CODE, READONLY

. K# I/ x# v# r& o( S EXPORT test_asm_args

- ?/ Q7 ^r: q+ k5 h7 ptest_asm_args+ C% V% E) W/ D8 K; J8 I

STR lr, [sp, #-4]! ;保存当前lr- J, Y, s. x9 D0 L

ldr r0,=0x1 ;参数 14 D, e/ @$ w' o, Y3 b6 O

ldr r1,=0x2 ;参数 2

0 p4 B9 A) z1 R" d ldr r2,=0x3 ;参数 3

7 [( l5 `( J- e" j- R; O; g# { ldr r3,=0x4 ;参数 4

: E5 T; d( l- ?9 T, n5 G6 T, X ldr r4,=0x8

! p% y% v# l: v str r4,[sp,#-4]! ;参数 8 入栈. Z% l# H; h) w1 Z, J" r% M; b: K

ldr r4,=0x7~+ K& N2 w1 y1 b# \

str r4,[sp,#-4]! ;参数 7 入栈% G( Q: ^+ y7 [( t1 J0 \1 s1 d; O

ldr r4,=0x6: X" c) A- c: BM. j) u

str r4,[sp,#-4]! ;参数 6 入栈

& y1 G* g$ u. e) a) x ldr r4,=0x5* H5 m4 L* N$ c

str r4,[sp,#-4]! ;参数 5 入栈, V* R/ v8 W$ G2 h, [' F- M$ `" ^

bl test_c_args_lots

8 i% t8 `0 Y! z& B9 F4 u0 h' e& Q ADD sp, sp, #4 ;清除栈中参数 5,本语句执行完后sp指向 参数6 # V0 D" b" d- {5 k1 V

ADD sp, sp, #4 ;清除栈中参数 6,本语句执行完后sp指向 参数75 q. l4 Y0 ^/ v+ }" ~* ^4 P, {' i

ADD sp, sp, #4 ;清除栈中参数 7,本语句执行完后sp指向 参数8

0 `8 U+ |' d2 ?; F1 S- X ADD sp, sp, #4 ;清除栈中参数 8,本语句执行完后sp指向 lr. _* ?! A8 ^* l

LDR pc, [sp],#4 ;将lr装进pc(返回main函数) % I6 f" K( y( R" h$ J( j

END, e9 |5 @/ re! D' }6 b$ Y

test_c_args.c

7 [x9 D/ J1 p3 w: R) L& ?! S! O8 g& {//--------------------------------------------------------------------------------

3 H: y' V2 C6 j' A" P& ^void test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)

& C" M5 p5 t, k- Z3 a6 L0 ?{0 X; v7 n" }5 M" O

printk("test_c_args_lots:/n");. |( @9 P, v# D. A# ^* k* k

printk("%0x %0x %0x %0x %0x %0x %0x %0x/n",/ L8 d. ID& Z+ p$ i4 ]

a,b,c,d,e,f,g,h);

" A$ u4 T! _+ f[( c}! b1 v! [6 F6 K" P. t

main.c! B8 N3 p5 [6 a$ J

//--------------------------------------------------------------------------------

& S# I1 z" F8 Q+ x+ @5 }9 y4 `- \int main()

: D4 U" k4 `/ P7 c! f{

# l! }4 b! r6 S1 r8 _( e- \H test_asm_args();

3 ~0 A3 R6 V- d- x' p for(;;);, B' T, [p& U* o& {

}' Z3 n: z) u. Y& @

) G4 d9 Z. Z% s% h" HB

这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。

5 g& H+ x& z- m在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。

) K, g+ ~7 F, p; @1 A直到调用test_c_args之前,堆栈内容如下:% f9 f3 x% m8 M8 b: ~

sp->+----------+

% W" N6 S5 \* c: p$ Q |参数5|0 V8 H8 r! _) |+ x2 Z- N

+----------+

/ b0 E* ?; U( ?: e |参数6|; p! gJ& O% }, j

+----------+, U3 k# ^& ~2 F: R! {Z

|参数7|$ `1 D+ Q2 j2 n- W: u

+----------+

( m6 i; E1 j* D! Q* `& v |参数8|+ c/ `, [& E# j6 ^

+----------+

& d5 P' Q" F" Rw7 A, \2 @ | lr |+ R8 bT+ _" G

+----------+

- o" S. J; @4 O1 W6 I& OI/ F- Ntest_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:) g$ w& @3 y$ r- ~

+----------+7 K. S, b& |. k; m$ ?

|参数5|

# v+ M' x: m' m$ E2 x8 ]. ` +----------+

, J- D% E* q9 k |参数6|

4 a! a7 x7 w2 `. Y1 t; f: N& @ +----------+0 R! MZ, Qd

|参数7|

" At( \5 J+ ]+ |1 R. @ +----------+- N: M4 H2 \1 n- K( X! C: |" Z1 t

|参数8|9 O! S/ I! W: j% n+ \" D. }

sp->+----------+% |! B3 Z) I5 ~: o2 d

| lr |* r1 q9 Q- V7 P, H

+----------+

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。