历史上的今天
返回首页

历史上的今天

今天是:2025年01月06日(星期一)

正在发生

2020年01月06日 | ARM 调用约定 calling convention

2020-01-06 来源:eefocus

int bar( int a, int b, int c, int d, int e, int f, int g )

{

  int array2[ 7 ];

  array2[ 0 ] = a + b;

  array2[ 1 ] = b + c;

  array2[ 2 ] = c + d;

  array2[ 3 ] = d + e;

  array2[ 4 ] = e + f;

  array2[ 5 ] = f + g;

  array2[ 6 ] = g + a;

  return array2[ 0 ] + array2[ 1 ] + array2[ 2 ] + array2[ 3 ] + array2[ 4 ]

    + array2[ 5 ] + array2[ 6 ];

}


int foo( int a, int b, int c, int d, int e, int f, int g )

{

  int array1[ 7 ];

  array1[ 0 ] = a + b;

  array1[ 1 ] = b + c;

  array1[ 2 ] = c + d;

  array1[ 3 ] = d + e;

  array1[ 4 ] = e + f;

  array1[ 5 ] = f + g;

  array1[ 6 ] = g + a;


  

  return bar( array1[ 0 ], array1[ 1 ], array1[ 2 ], array1[ 3 ], array1[ 4 ],

    array1[ 5 ], array1[ 6 ] );

}


int func( int * buffer )

{

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

  a = 1 + buffer[ 0 ];

  b = 2 + buffer[ 1 ];

  c = 3 + buffer[ 2 ];

  d = 4 + buffer[ 3 ];

  e = 5 + buffer[ 4 ];

  f = 6 + buffer[ 5 ];

  g = 7 + buffer[ 6 ];

  h = foo( a, b, c, d, e, f, g );


  return h;

}


int main( )

{

  int array0[ 7 ];

  array0[ 0 ] = 0;

  array0[ 1 ] = 1;

  array0[ 2 ] = 2;

  array0[ 3 ] = 3;

  array0[ 4 ] = 4;

  array0[ 5 ] = 5;

  array0[ 6 ] = 6;

  while ( func( array0 ) )


  {

  }

}

int main( )

{

main:

    0x8070252: 0xb500         PUSH      {LR}

    0x8070254: 0xb087         SUB       SP, SP, #0x1c

  array0[0] = 0;

    0x8070256: 0x2000         MOVS      R0, #0

    0x8070258: 0x9000         STR       R0, [SP]

  array0[1] = 1;


    0x807025a: 0x2001         MOVS      R0, #1

    0x807025c: 0x9001         STR       R0, [SP, #0x4]

  array0[2] = 2;

    0x807025e: 0x2002         MOVS      R0, #2

    0x8070260: 0x9002         STR       R0, [SP, #0x8]

  array0[3] = 3;

    0x8070262: 0x2003         MOVS      R0, #3

    0x8070264: 0x9003         STR       R0, [SP, #0xc]

  array0[4] = 4;

    0x8070266: 0x2004         MOVS      R0, #4

    0x8070268: 0x9004         STR       R0, [SP, #0x10]

  array0[5] = 5;

    0x807026a: 0x2005         MOVS      R0, #5

    0x807026c: 0x9005         STR       R0, [SP, #0x14]

  array0[6] = 6;

    0x807026e: 0x2006         MOVS      R0, #6

    0x8070270: 0x9006         STR       R0, [SP, #0x18]

  while ( func(array0) )

??main_0:

    0x8070272: 0xa800         ADD       R0, SP, #0x0

    0x8070274: 0xf7ff 0xffc3  BL        func                    ; 0x80701fe

    0x8070278: 0x2800         CMP       R0, #0

    0x807027a: 0xd1fa         BNE.N     ??main_0                ; 0x8070272

}

int main( )

{

main:

    0x8070252: 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:

    0x80701fe: 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:

    0x80701a2: 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[0], array1[1], array1[2], array1[3], array1[4], array1[5], array1[6] );

    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:

推荐阅读

史海拾趣

Fujitsu America公司的发展小趣事

为了更好地服务北美市场的客户,Fujitsu America实施了一系列本地化服务策略。公司不仅在当地建立了完善的销售和服务网络,还积极培养本地化的技术和服务团队,以更好地满足客户的实际需求。同时,Fujitsu America还注重与当地政府和行业协会的沟通与合作,积极参与行业标准的制定和推广工作,为公司在北美市场的长期发展奠定了坚实的基础。通过这些本地化服务策略的实施,Fujitsu America在北美市场树立了良好的品牌形象和市场地位。

Hokuriku公司的发展小趣事

进入21世纪后,环保和可持续发展成为全球关注的焦点。Hokuriku Electric积极响应这一趋势,将环保理念融入产品研发和生产过程中。公司投入大量资源研发绿色电子产品,减少生产过程中的能源消耗和废弃物排放。同时,Hokuriku Electric还积极参与行业内的环保倡议和合作项目,推动整个电子行业的可持续发展。这一举措不仅赢得了社会各界的广泛赞誉,还为公司带来了更多的商业机会和合作伙伴。

Elcos AG公司的发展小趣事

随着公司规模的扩大和业务的增长,Elcos AG面临着供应链管理的挑战。为了降低成本、提高效率和保证产品质量,公司决定对供应链进行优化。通过引入先进的供应链管理软件、加强与供应商的合作和建立严格的质量控制体系等措施,Elcos AG成功实现了供应链的优化和升级。这不仅提高了公司的运营效率和市场竞争力,还为客户提供了更加稳定可靠的产品和服务。

EPIGAP公司的发展小趣事

为了进一步扩大市场份额,EPIGAP公司开始实施国际化战略。公司先后在多个国家和地区设立了办事处和研发中心,以便更好地了解当地市场需求和技术发展趋势。通过与国际客户的深入合作,EPIGAP公司的产品逐渐打入国际市场,赢得了广泛的认可和赞誉。

Belden Wire & Cable公司的发展小趣事

随着市场的不断变化和客户需求的多样化,Belden公司开始实施产品多元化战略。除了传统的电线电缆产品外,公司还开发了一系列新型电缆产品,如光纤电缆、数据电缆等。这些新产品不仅拓宽了公司的产品线,还为公司带来了新的增长点。同时,Belden还加大了市场拓展力度,积极参与各类行业展会和论坛,提升品牌影响力。

G-Two Inc公司的发展小趣事

背景:在光伏胶膜领域取得成功后,福斯特开始寻求多元化发展。

发展:公司依托在光伏材料领域的技术积累和市场优势,逐步向电子电路、锂电等新材料领域拓展。同时,公司还成立了新材料研究院,专注于新材料的研发和创新。

成果:目前,福斯特在电子电路、锂电等领域也取得了显著成绩,为公司带来了新的增长点。

问答坊 | AI 解惑

section lma overlaps previous sections

大家好!最近因为某种原因,换了交叉编译工具链,以前是3.4.3,现在是4.2.3。 同样的源码,在编译应用程序模块时部分模块出现了类似如下的错误信息。 BFD: /home/***/HG553V100R001/targets/fs.src/bin/stALGP14: section .interp lma 0x4000f4 o ...…

查看全部问答>

论坛的兄弟姐妹,帮下忙

今天第一次发帖求助,有不恰当的地方,请各位见谅现在在做一个恒流源和恒压源,电流0-20MA,电压0-10V,分别有7个档位。我用LM124和2.5V基准源LM4140搭了一个,电压源没什么问题,但是恒流源接上公司的专用负载就会出现一个振铃,峰峰值大概300-400m ...…

查看全部问答>

怎样才能实现一个串口接收数据 然后另一个串口发送接收到的数据

怎样才能在M3上实现从一个串口接收数据 然后再将接收到的数据从另一个串口发送出去  而且完全是由中断自动触发完成 本质即如何由一个串口的接收中断去触发另一个串口的发送中断呢 请大家抽空给点建议  谢谢~…

查看全部问答>

zigbee的PHY层和MAC层产品疑问

想法是这样的:使用无线实现类似于以太网中的PTP时钟同步协议,想用zigbee来做无线收发部分。现在已经有了以太网转zigbee的产品,但是它的zigbee模块是整合在单芯片上的,那么就没法在类似于MII接口的接近硬件处取得数据。   所以,请问,有 ...…

查看全部问答>

把旅行变成修行之“装备篇(上)”

灵魂自行车的“心脏”——链条发电机及摩电发电机的原理   自行车骑行作为一项“绿色”环保的旅行方式,已经被越来越多的户外旅行爱好者所推崇。而在我的上一篇博文《把旅行变成修行--TI销售工程师的15天绿色环岛骑行梦》中也特别强调了这是 ...…

查看全部问答>

采用数字电源还是模拟电源?

作者:Chris Hossack 博士,德州仪器 (TI) Biricha 电源总监和 Richard Poley,TI 现场应用工程师 近几年,使用微处理器控制开关式电源不断发展。在数字电源相比模拟电源的优点方面仍存在许多争议,两大阵营你来我往、争论激烈。 实际上,每一种 ...…

查看全部问答>

EEworld下载中心鼎力奉献--proteus教程专辑(二)

本帖最后由 tiankai001 于 2014-1-4 11:10 编辑 EEworld下载中心鼎力奉献--proteus教程专辑(二) 说明:上接《EEworld下载中心鼎力奉献--proteus教程专辑(一)》,由于EEWORLD下载中心关于proteus的教程资源实在是太丰富了,并且这些教程都各 ...…

查看全部问答>

atmega16 AD采样问题

我AD用的是片内2.56V的基准电压,当输入电压大于2.56V是显示是2,56V,但是输入在2.56V以下的时候,是输入电压一半…

查看全部问答>

介绍一款高速过零比较器

我要把100M的正弦波转化成方波,大家有什么好的芯片介绍下 …

查看全部问答>

各位看一下,这个三极管开关的工作原理

下边这个P管有什么作用?P管有用么?我怎么觉得没有也一样呢? 各位怎么看,请不吝赐教,谢谢 …

查看全部问答>