上一篇讲到赋值运算,这篇讲讲子函数调用。先看最简单范例:test4.c

#include <stdio.h>
void f1()
{
}
void main()
{
int d = 4;
f1();
}

然后编译:arm-linux-gnueabihf-gcc test.c -o test4

然后看看汇编代码:

0000835c <f1>:

1    835c:       b480            push    {r7}

2    835e:       af00            add     r7, sp, #0

3    8360:       46bd            mov     sp, r7

4    8362:       bc80            pop     {r7}

直接跳到main函数里调用此函数时保存的LR值:

5    8364:       4770            bx      lr

6    8366:       bf00            nop



00008368 <main>:

程序用到了r7寄存器,所以须要保护以免破坏之前的数据,同一时候由于本函数调用子函数f1。须要用到lr寄存器保存返回值。故须要保存LR到栈里:



7    8368:       b580            push    {r7, lr}

8    836a:       b082            sub     sp, #8

9    836c:       af00            add     r7, sp, #0

10    836e:       f04f 0304       mov.w   r3, #4

11    8372:       607b            str     r3, [r7, #4]

跳转到函数f1的地址,同一时候把返回地址保存到LR寄存器:

12    8374:       f7ff fff2       bl      835c <f1>

13    8378:       f107 0708       add.w   r7, r7, #8

14    837c:       46bd            mov     sp, r7

注意:此时不再使用bx lr返回了!

而是直接把第7行保存的LR值弹到PC寄存器上,下一条取地址指令就是取main函数的下一个地址。

事实上。採用原来的方式:pop {r7, lr} 以及 bx lr 返回也是能够的。仅仅只是会多使用一条指令:

 15   837e:       bd80            pop     {r7, pc}

细心的人会发现。汇编代码8-11行与《从最简单的实例学习ARM 指令集(一)》中的范例test1.c一模一样。f1函数的机器指令十分简单,就是r7寄存器的压栈与出栈,相信大家都能看懂。

不知道大家有没有注意到,从main函数跳转到f1用的是bl指令,而从f1返回调用的是bx指令?

事实上这是由于涉及到arm处理器的两种工作状态:arm和thumb。子函数返回须要推断lr寄存器的[0]位来决定arm工作在那种状态,对子函数来说。偷懒的做法就是:无论主函数是什么。返回是虽然使用bx。让arm自己推断。而对main函数这样调用者来说。是知道当前处理器工作在thumb还是arm状态的,所以仅仅须要使用bl就能够了。

总结一下子函数的调用规则就是:bl用在函数内。bx用在返回。

下一篇讲讲函数调用过程中。參数是怎样传递的。

从最简单的实例学习ARM 指令集(三)的更多相关文章

  1. ARM指令集学习总结-转载

    ARM指令集比较简单,本文介绍ARM指令集中需要注意和不易理解的地方.       一.ARM指令集是32位的,程序的启动都是从ARM指令集开始,包括所有异常中断都是自动转化为ARM状态,并且所有的指 ...

  2. ARM_Instruction_Set_Encoding_hacking(ARM指令集编码格式解读)

    ARM指令集编码格式解读 说明: 1.本文参考的书籍<ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition>中的Cha ...

  3. 常用 ARM 指令集及汇编

    ARM7TDMI(-S)指令集及汇编 ARM 处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制 较为简单,ARM7TDMI(-S)具有 32 位 ARM 指令集和 16 位 T ...

  4. ARM指令集相关知识

    1.ARMv8引入了执行状态机制,分为AArch32和AArch64 AArch32为T32(Thumb)和A32(ARM). AArch64为A64一种指令集 A64和A32的指令都是32位宽,可以 ...

  5. 对arm指令集的疑惑,静态库运行,编译报错等问题

    转载自http://www.jianshu.com/p/4a70aa03a4ea?utm_campaign=hugo&utm_medium=reader_share&utm_conte ...

  6. 实例学习SSIS(三)--使用包配置

    原文:实例学习SSIS(三)--使用包配置 导读: 实例学习SSIS(一)--制作一个简单的ETL包 实例学习SSIS(二)--使用迭代 实例学习SSIS(三)--使用包配置 实例学习SSIS(四)- ...

  7. ARM指令集—SWP指令

    ARM指令集-SWP指令 SWP和SWPB是ARM指令集中对存储单元的原子操作.即对存储单元的一次读和一次不可被切割. SWP和SWPB分别完毕存储器和寄存器之间 一个字(32bit)和一个字节(8b ...

  8. 【基于Android的ARM汇编语言系列】之五:ARM指令集与Thumb指令集

    作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...

  9. Thumb指令集与ARM指令集的差别

    Thumb指令集          Thumb指令能够看做是ARM指令压缩形式的子集.是针对代码密度[1]的问题而提出的.它具有16为的代码密度.Thumb不是一个完整的体系结构,不能指望处理程序仅仅 ...

随机推荐

  1. PHPExcel 导出2003和2007的excel文档实例

    require_once 'common/excel/PHPExcel.php'; require_once 'common/excel/phpExcel/Writer/Excel2007.php'; ...

  2. Redis在Windows+linux平台下的安装配置(转)

    window平台Redis安装 下载地址: http://code.google.com/p/servicestack/wiki/RedisWindowsDownload Redis文件夹有以下几个文 ...

  3. Ext ComboBox 动态查询

    Ext中的combobox有属性typeAhead:true 可以实现模糊匹配,但是是从开始匹配的,如果需要自定的的匹配,则需要监听beforequery方法,实现自己的匹配查询方法: var gfx ...

  4. 如何让Oracle表及字段显示为区分大小写(转)

    http://www.itpub.net/thread-1703955-1-1.html

  5. MySQL必会的28条经典查询

    MySQL必会的28条经典查询   原创作品.转载请注明出处https://blog.csdn.net/kk123k 表结构及测试数据请看我上一篇文章:学生选修成绩表测试数据 Student(Sno, ...

  6. 启明星产品与微软Active Directory活动目录集成说明

    本文介绍启明星Helpdesk系统,如何和微软域集成. (1)确保在集成微软域之前,系统已经能够访问. (2)进入后台,用户管理页面,新加一个账户,此账户需要在微软域里(普通账户即可),然后在角色里设 ...

  7. iOS:UIImageView图像视图控件

    UIImageView:图像视图控件:    它是UIView的子类,因此也是视图控件,可以用来显示图像.因为它具有帧动画属性和操作方法,因此可以用来制作动画,其实动画就是很短的时间内,执行显示连续的 ...

  8. [18] 螺旋楼梯(Spiral Stairs)图形的生成算法

    顶点数据的生成 bool YfBuildSpiralStairsVertices ( Yreal radius, Yreal assistRadius, Yreal height, Yuint sli ...

  9. Informatica 常用组件Aggregator之四 创建聚合转换

    在 Mapping Designer 中选择"转换-创建".选择聚合转换. 为聚合输入一个名称,并单击"创建".然后单击"完成". Desi ...

  10. HTML中显示特殊字符,如尖括号 “<”,">"等等

    这几天,做个网页,之后进行解析,总是出错.最后发现是因为错误的使用了尖括号  “<”,">". 如下面的html代码: <body> 显示:<inpu ...