ARM汇编中调用C函数的参数传递方式

发布者:devilcore最新更新时间:2016-04-07 来源: eefocus关键字:ARM汇编  调用C函数  参数传递 手机看文章 扫描二维码
随时随地手机看文章
对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard)标准,ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回。

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

我们先讨论一下形参个数为4的情况:

实例1

s//>>test_asm_args.asm //-------------------------------------------------------------------------------- IMPORT test_c_args ;声明test_c_args函数 AREA TEST_ASM, CODE, READONLY EXPORT test_asm_args test_asm_args STR lr, [sp, #-4]! ;保存当前lr ldr r0,=0x10 ;参数 1 ldr r1,=0x20 ;参数 2 ldr r2,=0x30 ;参数 3 ldr r3,=0x40 ;参数 4 bl test_c_args ;调用C函数 LDR pc, [sp], #4 ;将lr装进pc(返回main函数) END  
c//>> test_c_args.c //-------------------------------------------------------------------------------- void test_c_args(int a,int b,int c,int d) { printk("test_c_args:\n"); printk("%0x %0x %0x %0x\n",a,b,c,d); }  
c//>> main.c //------------------------------------------------------------------------- int main() { test_asm_args(); for(;;); }  

程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main。代码分别使用了汇编和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函数中。

如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?

实例2

s//>>test_asm_args.asm //-------------------------------------------------------------------------------- IMPORT test_c_args ;声明test_c_args函数 AREA TEST_ASM, CODE, READONLY EXPORT test_asm_args test_asm_args STR lr, [sp, #-4]! ;保存当前lr ldr r0,=0x1 ;参数 1 ldr r1,=0x2 ;参数 2 ldr r2,=0x3 ;参数 3 ldr r3,=0x4 ;参数 4 ldr r4,=0x8 str r4,[sp,#-4]! ;参数 8 入栈 ldr r4,=0x7 str r4,[sp,#-4]! ;参数 7 入栈 ldr r4,=0x6 str r4,[sp,#-4]! ;参数 6 入栈 ldr r4,=0x5 str r4,[sp,#-4]! ;参数 5 入栈 bl test_c_args_lots ADD sp, sp, #4 ;清除栈中参数 5,本语句执行完后sp指向 参数6 ADD sp, sp, #4 ;清除栈中参数 6,本语句执行完后sp指向 参数7 ADD sp, sp, #4 ;清除栈中参数 7,本语句执行完后sp指向 参数8 ADD sp, sp, #4 ;清除栈中参数 8,本语句执行完后sp指向 lr LDR pc, [sp],#4 ;将lr装进pc(返回main函数) END  
c//>>test_c_args.c ... 略 ...  

后记

这段代码另外学到的是str作为入栈操作的新用法。

STR lr, [sp, #-4]! ;保存当前lr  

这条汇编指令所作的操作分别是:
将lr寄存器的内容 存入到 sp-4 所表示的内存空间中,然后执行 sp <- sp-4
作用是将lr入栈,保存当前lr的内容。
同理

LDR pc, [sp],#4 ;将lr装进pc(返回main函数)  

也是类似含义

关键字:ARM汇编  调用C函数  参数传递 引用地址:ARM汇编中调用C函数的参数传递方式

上一篇:arm 汇编指令--LDR
下一篇:uboot的relocation原理详细分析

推荐阅读最新更新时间:2024-03-16 14:49

有关arm汇编中的align
经常会看到arm-linux汇编中有如下的指令: .align n 它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或 2^n , 各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器, 必然要保持和原来汇编器的兼容,因此在gas中如何解释 .align指令会显得有些混乱,原因在于保持兼容。 arm-linu是按照2^n的方案对齐的,需要说明的是这个对齐和ld-script里的对齐不同,不是一会事。 下面的英文就不同平台的对齐进行了说明: 版本2.11.92.0.12的gas的info(Mandrake 8.2上的)这样说: The way the r
[单片机]
ARM汇编指令学习 - 实现数据块拷贝
程序要求: 设计一段程序完成数据块的复制,数据从源数据区snum复制到目标数据区dnum,数据量大小为NUM字(1个字=4个字节),复制时以8个字为单位进行,对于最后所剩不到8个字的数据,以字为单位进行复制。 程序清单: 1 ;============================================================================== 2 ; blocks.s: 将数据从源数据区snum复制到目标数据区dnum,数据量大小为NUM字 3 ; 复制时以8个字为单位进行,最后不够8个字的数据按1个字为单位复制 4 ;========================
[单片机]
灵活使用ARM汇编的WEAK关键字
//===================================================================== //TITLE: // 灵活使用ARM汇编的WEAK关键字 //AUTHOR: // norains //DATE: // Tuesday 20-October-2010 //Environment: // KEIL MDK 4.0 //===================================================================== ARM汇编中的WEAK关键字是一个很有意思的功能,如果能够灵活使用,能减轻不少繁琐。一般来说,这个关键字使用在IMP
[单片机]
ARM汇编中的LDR及ADR的区别及其在UBOOT中的应用
我在看U-BOOT的lowlevel_init.S文件时看到以下代码: lowlevel_init: ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 ldr r1, =BWSCON add r2, r0, #13*4 0: ldr r3, , #4 str r3, , #4 cmp r2, r0 bne 0b mov pc, lr 这段代码实现了U-BOOT的内存控制器部分的寄存器初始化,一共13个寄存器,对U-BOOT来最重要的就是SDRAM的初始化,显然没有这部分代码,当U-BOOT从NAND FLASH中启动的时候,START.S文件是无法完成代码的relocate的。因
[单片机]
第1天-ARM汇编指令MOV/MVN
MOV : 传送 (Move) MOV{条件}{S} , dest = op_1 MOV 从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。你可以指定相同的寄存器来实现 NOP 指令的效果,你还可以专门移位一个寄存器: MOV R0, R0 ; R0 = R0... NOP 指令 MOV R0, R0, LSL#3 ; R0 = R0 * 8 如果 R15 是目的寄存器,将修改程序计数器或标志。这用于返回到调用代码,方法是把连接寄存器的内容传送到 R15: MOV PC, R14 ; 退出到调用者 MOVS PC, R14 ;
[单片机]
ARM汇编语言入门(六)
Part 6:条件状态和分支 在探讨CPSR时我们已经接触了条件状态。我们通过跳转(分支)或者一些只有满足特定条件才执行的指令来控制程序在运行时的执行流。通过CPSR寄存器中的特定bit位来表示条件状态。这些位根据指令每次执行的结果而不断变化。例如,比较运算时如果两个数相等,那么就置CPSR中的Zero位(Z=1),实际上是因为:a - b = 0,这种情况下就是相等状态。如果第一个数大,那么就是大于状态。如果第二个数大,就是小于状态。除此之外,还有小于等于、大于等于等等。 下面的表格列出了可用的条件状态码,描述和标志位: 在下面代码片段中看一下执行条件加法时的实际用法L: .global main main:
[单片机]
<font color='red'>ARM汇编</font>语言入门(六)
关于arm汇编中的align
经常会看到arm-linux汇编中有如下的指令: .align n 它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或 2^n ,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释 .align指令会显得有些混乱,原因在于保持兼容。 arm-linu是按照2^n的方案对齐的,需要说明的是这个对齐和ld-script里的对齐不同,不是一会事。下面的英文就不同平台的对齐进行了说明: 版本2.11.92.0.12的gas的info(Mandrake 8.2上的)这样说: The way the re
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved