结合ARM相关文档和在飞腾机器上使用gdb调试实际程序来研究ARM的指令和运行时栈帧布局。主要参考了三篇文档。
1. Procedure Call Standard for the ARM 64-bit Architecture。参考其中的过程调用标准和运行时栈帧布局。
2. ARMv8 Instruction Set Overview。参考其中的指令概述。
3. ARM Compiler Migration and Compatibility Guide。参考其中ARM汇编与GNU汇编格式的比较。
在文章1中,对ARM架构下运行时栈帧布局如图1所示。
图1 ARM运行时栈帧布局
其中,FP(x29)寄存器保存栈帧地址,LR(x30)保存当前过程的返回地址。栈是从高地址向低地址生长。为验证图中的布局形式,在飞腾机器上安装gdb,通过调试一个示例程序,来研究ARM的指令特点和栈帧结构。示例程序如图2所示,函数TestParam定义了两个局部变量,分别为数组和标量类型。
使用gdb调试图2中代码所产生的程序,然后再反汇编函数TestParam,可以得到如下结果。
=> 0x0000000000400680 <+0>:stpx29, x30, [sp,#-64]!
0x0000000000400684 <+4>:movx29, sp
0x0000000000400688 <+8>:strw0, [x29,#28]
0x000000000040068c <+12>:strw1, [x29,#24]
0x0000000000400690 <+16>:strw2, [x29,#20]
0x0000000000400694 <+20>:strw3, [x29,#16]
0x0000000000400698 <+24>:adrpx0, 0x411000 <__libc_start_main@got.plt>
0x000000000040069c <+28>:addx0, x0, #0x38
0x00000000004006a0 <+32>:ldrx1, [x0]
0x00000000004006a4 <+36>:strx1, [x29,#56]
0x00000000004006a8 <+40>:movx1, #0x0