汇编语言调用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

//--------------------------------------------------------------------------------( v  u' 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# Y  E* 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 a  A5 z" `# U& b) M" M//--------------------------------------------------------------------------------( d1 F  X4 \- 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" P  o//--------------------------------------------------------------------------------

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' O  J程序从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: B  M. 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 @/ r  e! 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. I  D& 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" H  B

这部分的代码和实例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! g  J& 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" R  w7 A, \2 @        |     lr      |+ R8 b  T+ _" G

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

- o" S. J; @4 O1 W6 I& O  I/ 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! M  Z, Q  d

|  参数7  |

" A  t( \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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言选择法排序案例,谁能给我一个c语言选择排序法的简单例子

满意答案evil83752014.02.27采纳率:51% 等级:11已帮助:7590人#include int main(){int array[100], n, c, d, position, swap;printf("Enter number of elements\n");scanf("%d", &n);printf("Enter %d inte…

huffman算法c语言实验报告,huffman二叉树实验报告--数据结构(c语言).doc

江海强 PAGE 7数 据 结 构 作 业 报 告——Huffman二叉树实验报告姓名:江海强班级:070921班学号上机时间:2010-报告时间:2010-10-26摘要1.实验目的本实验是为了让我们深入了解Huffman二叉树,学会使用Huffman编码…

《炉石传说》建筑设计欣赏(7):采用Google.ProtocolBuffers处理网络消息

这一次,琢磨了一下Unity3D网络游戏发展的网络信息处理。服务器的网络游戏一般都是自主研发,因此,相应的网络消息处理应该培养自己。client/现在使用的邮件服务器之间的价差JSON和Google.ProtocolBuffers有两种常见的方法。平炉码看其处理。代…

tarjan算法c语言,tarjan算法板子 - osc_e45irv7l的个人空间 - OSCHINA - 中文开源技术交流社区...

无向图概念时间戳\(dfn[x]\),在深度优先遍历中&#xff0c;按照每个节点第一次被访问的顺序&#xff0c;依次做整数标记追溯值\(low[x]\),通过非搜索边能到达的最小时间戳割边判定法则无向边\((x,y)\)是割边/桥&#xff0c;当且仅当存在x的一个子节点满足\(dfn[x] < low[y]\…

流和文件

流&#xff1a;流是数据的传输方式&#xff1b;C程序处理一个流而不是直接处理文件。你声明一个FILE *fp &#xff0c;并把fopen(某个文件)返回的值赋予fp这两个动作就相当于建立了一个水龙头&#xff0c;当你用getc(fp)之类的输入函数读取文件字符时就相当于拧开了水龙头&…

小球进盒子C语言,N个小球放进M个盒子算法-Go语言中文社区

N个小球放入M个盒子共有多少种方法&#xff0c;并输出的算法设计&#xff1a;算法思路1 &#xff1a;暴力填充盒子每个小球都可能放入M个盒子的任意一个&#xff0c;所以直接根据小球个数做递归即可,然后将存储放入hash中排重//TODO算法思路2 &#xff1a;递归填充盒子即&#…

r语言c5.0要求因子输出,R语言中因子的创建与使用

原标题&#xff1a;R语言中因子的创建与使用因子在R语言中可以用来表示名义型变量或有序变量。名义变量一般表示类别&#xff0c;如性别&#xff0c;种族等等。有序变量是有一定排序顺序的变量&#xff0c;如职称&#xff0c;年级等等。在R语言中&#xff0c;名义变量和有序变量…

WinForm中使用AnyCAD三维控件 の 初始化

在WinForm中可以方便的集成AnyCAD.Net三维控件&#xff0c;只需要以下几部即可完成。 一、添加DLL程序集 AnyCAD.Foundation.Net.dll AnyCAD.Presentation.Net.dll AnyCAD.Exchange.Net.dll 二、初始化控件 1.首先创建一个窗体 2.在窗体上放置一个Panel用来放置三维控件 3.初始…

linux中nodejs后台运行工具forever

forever让nodejs应用后台执行 命令如下&#xff1a; forever start ./bin/www nodejs一般是当成一条用户命令执行的&#xff0c;当用户断开客户连接&#xff0c;运用也就停了&#xff0c;很烦人。如何让nodejs应用当成服务&#xff0c;在后台执行呢&#xff1f; 最简单的办法(不…

android启动其他app的服务器,Android中通过外部程序启动App的三种方法

这篇文章主要介绍了Android中通过外部程序启动App的三种方法,本文讲解了直接通过包名、通过自定义的Action、通过Scheme三种方法,并分别给出操作代码,需要的朋友可以参考下第一种&#xff1a;直接通过包名&#xff1a;复制代码 代码如下:Intent LaunchIntent getPackageManage…

linux date 天之前,linux date命令前后几天的推导

linux date使用(前后几天时间推导)在Linux系统 中&#xff0c;可以采用如下方法&#xff1a;1) 取之前的时间&#xff1a;date -d "a day ago" %Y%m%d 取出前1天的系统时间date -d "2 days ago" %Y%m%d 取出前2天的系统时间2) 取之后的时间&#xff1a;dat…

各种封装——封装getClass

因为用Class获取元素时&#xff0c;有兼容性问题&#xff0c;需要分情况获取 显示判断是否可以用getElementsByClassName&#xff0c;若是不介意用就要先获取全部的元素&#xff0c;在用正则判断 function getClass(oParent,sClass){if(oParent.getElementsByClassName){return…

android提示程序正在执行,Android中获取正在运行的进程(一)

关于android中应用程序正在运行的进程有下面几种&#xff1a;1-包含services的进程&#xff0c;2-不包含services的进程&#xff0c;3-杀死应用时有些进程被init回收(类似于僵尸进程)&#xff0c;ppid变为1&#xff0c;无法通过android 应用层代码获得的进程。这些进程可能是应…

jta 知识

JTA知识&#xff08;转载原文地址&#xff1a;http://blog.csdn.net/it_man/article/details/7230215&#xff09; Java Transaction API&#xff0c;译为Java事务API。JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JTA主要用于分布式…

android l usb调试,你居然还不会手机usb调试?5个方法,让你轻松学会设置!

原标题&#xff1a;你居然还不会手机usb调试&#xff1f;5个方法&#xff0c;让你轻松学会设置&#xff01;最近有位朋友将手机连接电脑的时候&#xff0c;遇到了提示打开手机的USB调试模式&#xff0c;却不知道怎么操作。其实&#xff0c;不同手机的usb调试打开的方式都会有所…

深入沟通的重要性——《大道至简》第四章读后感

我们都知道&#xff0c;一个新发明如果不被人们所需要&#xff0c;那只是一个失败品。一篇文章的观点如果不被人们所接受&#xff0c;那么就算文笔再好&#xff0c;也只是一张废纸。同样的&#xff0c;一个与客户需求不符的程序&#xff0c;哪怕它的架构再好&#xff0c;都只是…

鸿蒙os芯片,没有了芯片,华为能靠鸿蒙OS系统打出差异化吗?

原标题&#xff1a;没有了芯片&#xff0c;华为能靠鸿蒙OS系统打出差异化吗&#xff1f;华为今天要和大家说的手机产品是华为&#xff0c;在目前的市场中&#xff0c;华为手机的影响力是非常大的&#xff0c;并且获得了十分不错的销量&#xff0c;甚至在最近一段时间销量超过三…

html5 canvas 不兼容safari浏览器_HTML5简介

HTML5 是继 HTML4.01 和 XHTML1.0 之后的超文本标记语言的最新版本。它是由一群自由思想者组成的团队设计出来&#xff0c;并最终实现多媒体支持、交互性、更加智能的表单&#xff0c;以及更好的语义化标记。HTML5 并不仅仅是 HTML 规范的最新版本&#xff0c;而是一系列用来制…

html5置顶标签css样式,html5 header标签 html header css布局教程 /header

在HTML5版本之前习惯使用div标签布局网页&#xff0c;在HTML5在DIV标签基础上新增header标签元素。也叫“”头部标签。以前我们在div css布局中常常把网页大致分为头部、内容、底部。对于大结构我们常常使用div里加id进行布局。而头部常常使用正应为大家公认html布局中对“head…

DML数据操作语言练习

--创建表T_HQ_BM2 --create table t_hq_bm2 as select * from t_hq_bm; commit;--添加行内容 --insert into t_hq_bm2 values (107,研发部,147258369); commit;--删除部门编码为107的行 --delete t_hq_bm2 where bumenbm 107; commit;--添加行内容 --insert into t_hq_bm2 (bu…