单片机 > 单片机程序设计 > 详情

ARM 调用约定 calling convention

发布时间:2021-01-21 发布时间:
|

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]


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机按键切换下一首歌