int bar( int a, int b, int c, int d, int e, int f, int g )
{
int array2[ ];
array2[ ] = a + b;
array2[ ] = b + c;
array2[ ] = c + d;
array2[ ] = d + e;
array2[ ] = e + f;
array2[ ] = f + g;
array2[ ] = g + a;
return array2[ ] + array2[ ] + array2[ ] + array2[ ] + array2[ ]
+ array2[ ] + array2[ ];
} int foo( int a, int b, int c, int d, int e, int f, int g )
{
int array1[ ];
array1[ ] = a + b;
array1[ ] = b + c;
array1[ ] = c + d;
array1[ ] = d + e;
array1[ ] = e + f;
array1[ ] = f + g;
array1[ ] = g + a; return bar( array1[ ], array1[ ], array1[ ], array1[ ], array1[ ],
array1[ ], array1[ ] );
} int func( int * buffer )
{
int a, b, c, d, e, f, g, h;
a = + buffer[ ];
b = + buffer[ ];
c = + buffer[ ];
d = + buffer[ ];
e = + buffer[ ];
f = + buffer[ ];
g = + buffer[ ];
h = foo( a, b, c, d, e, f, g );
return h;
} int main( )
{
int array0[ ];
array0[ ] = ;
array0[ ] = ;
array0[ ] = ;
array0[ ] = ;
array0[ ] = ;
array0[ ] = ;
array0[ ] = ;
while ( func( array0 ) )
{
}
}

int main( )
{
main:x8070252: 0xb500 PUSH {LR}
0x8070254: 0xb087 SUB SP, SP, #0x1c
array0[] = ;
0x8070256: 0x2000 MOVS R0, #x8070258: 0x9000 STR R0, [SP]
array0[] = ;
0x807025a: 0x2001 MOVS R0, #x807025c: 0x9001 STR R0, [SP, #0x4]
array0[] = ;
0x807025e: 0x2002 MOVS R0, #x8070260: 0x9002 STR R0, [SP, #0x8]
array0[] = ;
0x8070262: 0x2003 MOVS R0, #x8070264: 0x9003 STR R0, [SP, #0xc]
array0[] = ;
0x8070266: 0x2004 MOVS R0, #x8070268: 0x9004 STR R0, [SP, #0x10]
array0[] = ;
0x807026a: 0x2005 MOVS R0, #x807026c: 0x9005 STR R0, [SP, #0x14]
array0[] = ;
0x807026e: 0x2006 MOVS R0, #x8070270: 0x9006 STR R0, [SP, #0x18]
while ( func(array0) )
??main_0:x8070272: 0xa800 ADD R0, SP, #0x0
0x8070274: 0xf7ff 0xffc3 BL func ; 0x80701fe
0x8070278: 0x2800 CMP R0, #x807027a: 0xd1fa BNE.N ??main_0 ; 0x8070272
}

int main( )
{
main:x8070252: 0xb500 PUSH {LR}
0x8070254: 0xb087 SUB SP, SP, #0x1c

执行 PUSH {LR} 之前, SP = 0x20000400, 执行 PUSH {LR} 之后, LR 入栈, SP = 0x200003FC

接着执行 SUB SP, SP, #0x1c, 为局部变量分配空间 28 bytes, SP = 0x200003E0

    0x8070272: 0xa800 ADD R0, SP, #0x0
0x8070274: 0xf7ff 0xffc3 BL func ; 0x80701fe

调用 func()

int func(int * buffer)
{
func:x80701fe: 0xe92d 0x4ff0 PUSH.W {R4-R11, LR}
0x8070202: 0xb085 SUB SP, SP, #0x14
0x8070204: 0x0004 MOVS R4, R0
... ... ... ...
h = foo(a, b, c, d, e, f, g);

PUSH .W {R4-R11, LR}, SUB SP, SP, #0x14, 保存寄存器, 为局部变量分配空间 a, 其他变量b,c,d,e,f,g 使用寄存器R5-R10

h 使用寄存器 R11 <图中没有显示>

同时分配3个变量的空间, 用于通过堆栈传递参数, 调用 foo(a, b, c, d, e, f, g)

  h = foo(a, b, c, d, e, f, g);
0x8070230: 0xf8cd 0xa008 STR.W R10, [SP, #0x8] g
0x8070234: 0xf8cd 0x9004 STR.W R9, [SP, #0x4] f
0x8070238: 0xf8cd 0x8000 STR.W R8, [SP] e
0x807023c: 0x003b MOVS R3, R7 d
0x807023e: 0x0032 MOVS R2, R6 c
0x8070240: 0x0029 MOVS R1, R5 b
0x8070242: 0x9803 LDR R0, [SP, #0xc] a
0x8070244: 0xf7ff 0xffad BL foo ; 0x80701a2
0x8070248: 0x4683 MOV R11, R0
return h;
0x807024a: 0x4658 MOV R0, R11
0x807024c: 0xb005 ADD SP, SP, #0x14
0x807024e: 0xe8bd 0x8ff0 POP.W {R4-R11, PC}

foo(a, b, c, d, e, f, g) : a -> R0, b -> R1, c -> R2, d -> R3, e -> [SP, #0x00], f -> [SP, #0x04], e -> [SP, #0x08]

foo:x80701a2: 0xe92d 0x47f0  PUSH.W    {R4-R10, LR}
0x80701a6: 0xb08a SUB SP, SP, #0x28
0x80701a8: 0x0004 MOVS R4, R0 a 通过寄存器传递
0x80701aa: 0x000d MOVS R5, R1 b 通过寄存器传递
0x80701ac: 0x0016 MOVS R6, R2 c 通过寄存器传递
0x80701ae: 0x001f MOVS R7, R3 d 通过寄存器传递
0x80701b0: 0xf8dd 0x8048 LDR.W R8, [SP, #0x48] e 通过堆栈传递
0x80701b4: 0xf8dd 0x904c LDR.W R9, [SP, #0x4c] f 通过堆栈传递
0x80701b8: 0xf8dd 0xa050 LDR.W R10, [SP, #0x50] g 通过堆栈传递

PUSH .W {R4-R10, LR}, SUB SP, SP, #0x28, 保存寄存器, 为局部变量分配空间 array1[7], 同时分配3个变量的空间, 用于通过堆栈传递参数, 调用

bar( array1[ 0 ], array1[ 1 ], array1[ 2 ], array1[ 3 ], array1[ 4 ], array1[ 5 ], array1[ 6 ] );

foo (a, b, c, d, e, f, g ) : a, b, c, d 通过寄存器传递, e, f, g 通过堆栈传递

获取参数, 运算之后, 存入局部变量 array1[7], 然后准备调用 bar()

array1[ 0 ], array1[ 1 ], array1[ 2 ], array1[ 3 ]  通过寄存器传递

array1[ 4 ], array1[ 5 ], array1[ 6 ] 通过堆栈传递

  return bar( array1[], array1[], array1[], array1[], array1[], array1[], array1[] );
0x80701e0: 0x9809 LDR R0, [SP, #0x24] array1[6]
0x80701e2: 0x9002 STR R0, [SP, #0x8]
0x80701e4: 0x9808 LDR R0, [SP, #0x20]      array1[5]      
0x80701e6: 0x9001 STR R0, [SP, #0x4]
0x80701e8: 0x9807 LDR R0, [SP, #0x1c] array1[4]
0x80701ea: 0x9000 STR R0, [SP]
0x80701ec: 0x9b06 LDR R3, [SP, #0x18] array1[3]
0x80701ee: 0x9a05 LDR R2, [SP, #0x14] array1[2]
0x80701f0: 0x9904 LDR R1, [SP, #0x10] array1[1]
0x80701f2: 0x9803 LDR R0, [SP, #0xc] array1[0]
0x80701f4: 0xf7ff 0xffa5 BL bar ; 0x8070142
0x80701f8: 0xb00a ADD SP, SP, #0x28
0x80701fa: 0xe8bd 0x87f0 POP.W {R4-R10, PC}

bar:x8070142: 0xb4f0         PUSH      {R4-R7}
0x8070144: 0xb087 SUB SP, SP, #0x1c
0x8070146: 0x0004 MOVS R4, R0 a <- array1[0]
x8070148: 0x9d0b LDR R5, [SP, #0x2c] e <- array1[4] -- 通过堆栈传递的参数
0x807014a: 0x9e0c LDR R6, [SP, #0x30] f <- array1[5] -- 通过堆栈传递的参数
0x807014c: 0x9f0d LDR R7, [SP, #0x34] g <- array1[6] -- 通过堆栈传递的参数

PUSH.W {R4-R7, LR}, SUB SP, SP, #0x1C, 保存寄存器, 为局部变量分配空间 array2[7]

ARM 调用约定 calling convention的更多相关文章

  1. X86调用约定 calling convention

    http://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A 这里描述了在x86芯片架构上的调用约定(calling con ...

  2. 调用惯例Calling Convention (或者说:调用约定)

    调用惯例影响执行效率,参数的传递方式以及栈清除的方式.   调用惯例 参数传递顺序 谁负责清除参数 参数是否使用暂存器 register 从左到右 被调用者 是 pascal 从左到右 被调用者 否 ...

  3. C++调用约定和名字约定

    C++调用约定和名字约定 转自http://www.cppblog.com/mzty/archive/2007/04/20/22349.html 调用约定:__cdecl __fastcall与 __ ...

  4. 调用约定__cdecl __fastcall与__stdcall

    __cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以 ...

  5. C&C++ Calling Convention

    tkorays(tkorays@hotmail.com) 调用约定(Calling Convention) 是计算机编程中一个比较底层的设计,它主要涉及: 函数参数通过寄存器传递还是栈? 函数参数从左 ...

  6. C/C++/动态链接库DLL中函数的调用约定与名称修饰

    参见:http://blog.twofei.com/cc/impl/calling-convension.html 调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用 ...

  7. C++调用约定和名字约定 thiscall

    调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数 ...

  8. C/C++:函数的调用约定(Calling Convention)和名称修饰(Decorated Name)以及两者不匹配引起的问题

    转自:http://blog.csdn.net/zskof/article/details/3475182 注:C++有着与C不同的名称修饰,主要是为了解决重载(overload):调用约定则影响函数 ...

  9. C C++ ARM X86 函数 方法 的调用约定

    参考:https://bbs.pediy.com/thread-224583.htm 整理成表格方便查询 cdecl(C规范), stdcall(WinAPI默认), fastcall, ATPCS( ...

随机推荐

  1. 【UOJ#38】【清华集训2014】奇数国

    考虑欧拉函数的性质,60很小,压位存下线段树每个节点出现质数. #include<bits/stdc++.h> ; ; typedef long long ll; using namesp ...

  2. 画弧线DrawArc的研究-我自己 -- 直线交接圆角

    procedure TForm4.Button7Click(Sender: TObject); var pwith: Integer; //画笔的宽度 hx1, hy1: Integer; //横线第 ...

  3. 使用CEPH RGW admin ops API 进行用户user AK/SK管理的秘诀

    需求: 云平台面板上需要支持为不同的用户创建不同的RGW 的AK/SK用户秘钥,以完成对象存储的用户隔离,并可以管理bucket和查看bucket容量信息. 分析:查阅CEPH官网文档 S3 API  ...

  4. JavaScript 执行环境 与 变量对象

    什么是JS的执行环境? function funA(){ //一段代码静静的躺在这里,不能叫执行环境 } funA(); //当代码开始执行以后,系统会将它存入执行栈,并为他准备好足够的内存空间使用 ...

  5. vs 单元测试

    vs 2010 NOget 包 安装NUnitTDNet,下载TestDriven.NET(http://www.testdriven.net/). 准备动作 先到http://www.testdri ...

  6. 现在就能投入使用的12个高端大气上档次的CSS3特性

    原文:http://tutorialzine.com/2013/10/12-awesome-css3-features-you-can-finally-use/ 原文中有demo展示及下载. 翻译开始 ...

  7. linux 笔记(一)

    1.Linux 安装3ython3 1.1 下载 wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz 1.2 解压 tar -z ...

  8. linux 把ls -R格式化成树状结构

    谁能写脚本把linux中的ls -R命令的结果格式化成树状结构? 最好是shell脚本!欢迎讨论! 参与讨论有可能意外获取iPhone6哦~~

  9. 关于 Unity 的一些小细节,不注意可能会被“坑”一些时间。

    关于 Unity 的一些小细节,不注意可能会被"坑"一些时间. 最近因为一些"小"问题,总是需要找很久的原因,总结一下 UnityEngine.Input 在使 ...

  10. MySQL 5.7 安装完成后,首次登陆的几个问题

    Server:CentOS 7.0 MySQL : 5.7.20 MySQL Community Server (GPL) 1.首次登陆后修改密码: 根据安装时的选择不同,有mysqld_safe用m ...