ARM汇编函数栈帧分析
实验环境
- 主机操作系统 : Ubuntu 22.04
- ARM虚拟机 : QEMU 10.2.0
- ARM CPU : ARM926EJ-S
- 交叉编译器 : ARM GNU GCC 15.2
链接脚本
ENTRY(_start)
MEMORY {
/* 0x0000 0000 - 0x0000 ffff */
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
/* 0x0001 0000 - 0x0801 0000 */
RAM (rw) : ORIGIN = 0x00010000, LENGTH = 128M
}
SECTIONS {
.text : { /* 未指定代码段LMA起始地址,默认LMA=VMA */
KEEP(*(.init)) /* 保留启动入口(通常含 _start) */
*(.text*) /* 所有代码段 */
*(.rodata*) /* 只读数据(如字符串常量) */
} > FLASH /* VMA:运行地址在 FLASH 区 0x0000 0000 开始 */
.data : AT(ADDR(.text) + SIZEOF(.text)) { /* 指定数据块LMA */
__data_load_addr = LOADADDR(.data); /* 数据段在LMA的起始地址 = 代码段LMA起始地址(此处等于VMA起始地址) + 代码段长度 */
__data_start = .; /* 数据段在VMA的起始地址 */
*(.data*) /* 所有数据段 */
__data_end = .; /* 数据段在VMA的结束地址 */
} > RAM /* VMA 指定在RAM区 0x0001 0000 开始 */
.bss : { /* bss段默认不加载到LMA */
__bss_start = .; /* bss在VMA的起始地址 */
*(.bss*) /* 所有bss段 */
__bss_end = .; /* bss在VMA的结束地址 */
} > RAM /* VMA 指定在RAM区 接着data段 开始 */
__stack_top = ORIGIN(RAM) + LENGTH(RAM); /* 定义栈顶地址 */
}
汇编启动程序
.section .init
.global _start
@ 入口
_start:
@ 设置栈指针
ldr sp, =__stack_top
@ 初始化.data区
ldr r0, =__data_load_addr @ 程序镜像中.data区
ldr r1, =__data_start @ RAM中.data区开始地址
ldr r2, =__data_end @ RAM中.data区结束地址
@ .data循环复制
data_loop:
cmp r1, r2
beq bss_init
ldr r3, [r0], #4
str r3, [r1], #4
b data_loop
@ 初始化.bss区
bss_init:
ldr r1, =__bss_start
ldr r2, =__bss_end
@ .bss循环清空
bss_loop:
cmp r1, r2
beq call_main
mov r3, #0
str r3, [r1], #4
b bss_loop
@ 调用main函数
call_main:
mov r0, #0
mov r1, #0
bl main
@ main返回后死循环
halt:
b halt
C入口文件
int sum(int a, int b, int c, int d, int e, int f) {
return a + b + c + d + e + f;
}
int main(int argc, const char *argv[]) {
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int f = 6;
int result = sum(a, b, c, d, e, f);
return result;
}
Makefile
# =============================================================================
# ARM 裸机开发 Makefile(适用于 QEMU 仿真)
# 功能:
# - 编译 C 和汇编源文件
# - 链接生成 ELF 和 raw binary
# - 支持反汇编、QEMU 仿真、GDB 调试
# =============================================================================
# ===== 工具链 =====
# 指定交叉编译工具链前缀
CROSS_COMPILE = arm-none-eabi-
CC = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
GDB = $(CROSS_COMPILE)gdb
# ===== 目标 =====
TARGET = main
# ===== 源文件 =====
# C 源文件(主程序)
SRCS_C = main.c
# 汇编源文件
SRCS_S = startup.S
# ===== 中间目标文件 =====
# 自动将 .c → .o,.S → .o
OBJS = $(SRCS_C:.c=.o) $(SRCS_S:.S=.o)
# ===== 编译选项 =====
# gcc参数
CFLAGS = \
-nostdlib \
-ffreestanding \
-g \
-mcpu=arm9e \
-Wall
# as参数
ASFLAGS = \
-g \
-mcpu=arm9e
# ===== 链接脚本 =====
LDSCRIPT = linker.ld
# ===== 默认目标 =====
# 执行 `make` 时,默认构建 bin 和 dump 文件
main: $(TARGET).bin $(TARGET).dump
# ===== 编译规则 =====
# 通用规则:将 .c 文件编译为 .o
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 通用规则:将 .S 文件汇编为 .o
%.o: %.S
$(AS) $(ASFLAGS) -c $< -o $@
# ===== 链接 ELF =====
$(TARGET).elf: $(OBJS)
$(LD) -T $(LDSCRIPT) -o $@ $^
# ===== ELF → BIN =====
$(TARGET).bin: $(TARGET).elf
$(OBJCOPY) -O binary $< $@
# ===== 反汇编 =====
$(TARGET).dump: $(TARGET).elf
$(OBJDUMP) -d $< > $@
# ===== QEMU =====
QEMU = qemu-system-arm
QEMU_OPTS = \
-M none \
-cpu arm926 \
-nographic \
-device loader,addr=0x00000000,file=$(TARGET).bin \
-m 256M \
-S \
-s
# ===== 运行 QEMU =====
qemu: $(TARGET).bin
sudo $(QEMU) $(QEMU_OPTS)
# ===== 运行GDB =====
gdb:
$(GDB) $(TARGET).elf
# ===== 清理 =====
clean:
rm -f *.o *.elf *.bin *.dump
# ===== 声明伪目标(phony targets)=====
# 防止与同名文件冲突
.PHONY: main clean qemu gdb
反汇编分析
main.elf: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: e59fd048 ldr sp, [pc, #72] @ 50 <halt+0x4>
4: e59f0048 ldr r0, [pc, #72] @ 54 <halt+0x8>
8: e59f1048 ldr r1, [pc, #72] @ 58 <halt+0xc>
c: e59f2048 ldr r2, [pc, #72] @ 5c <halt+0x10>
00000010 <data_loop>:
10: e1510002 cmp r1, r2
14: 0a000002 beq 24 <bss_init>
18: e4903004 ldr r3, [r0], #4
1c: e4813004 str r3, [r1], #4
20: eafffffa b 10 <data_loop>
00000024 <bss_init>:
24: e59f1034 ldr r1, [pc, #52] @ 60 <halt+0x14>
28: e59f2034 ldr r2, [pc, #52] @ 64 <halt+0x18>
0000002c <bss_loop>:
2c: e1510002 cmp r1, r2
30: 0a000002 beq 40 <call_main>
34: e3a03000 mov r3, #0
38: e4813004 str r3, [r1], #4
3c: eafffffa b 2c <bss_loop>
00000040 <call_main>:
40: e3a00000 mov r0, #0
44: e3a01000 mov r1, #0
48: eb00001c bl c0 <main>
0000004c <halt>:
4c: eafffffe b 4c <halt>
50: 08010000 .word 0x08010000
54: 0000013c .word 0x0000013c
58: 00010000 .word 0x00010000
5c: 00010000 .word 0x00010000
60: 00010000 .word 0x00010000
64: 00010000 .word 0x00010000
00000068 <sum>:
68: e52db004 push {fp} @ (str fp, [sp, #-4]!)
6c: e28db000 add fp, sp, #0
70: e24dd014 sub sp, sp, #20
74: e50b0008 str r0, [fp, #-8]
78: e50b100c str r1, [fp, #-12]
7c: e50b2010 str r2, [fp, #-16]
80: e50b3014 str r3, [fp, #-20] @ 0xffffffec
84: e51b2008 ldr r2, [fp, #-8]
88: e51b300c ldr r3, [fp, #-12]
8c: e0822003 add r2, r2, r3
90: e51b3010 ldr r3, [fp, #-16]
94: e0822003 add r2, r2, r3
98: e51b3014 ldr r3, [fp, #-20] @ 0xffffffec
9c: e0822003 add r2, r2, r3
a0: e59b3004 ldr r3, [fp, #4]
a4: e0822003 add r2, r2, r3
a8: e59b3008 ldr r3, [fp, #8]
ac: e0823003 add r3, r2, r3
b0: e1a00003 mov r0, r3
b4: e28bd000 add sp, fp, #0
b8: e49db004 pop {fp} @ (ldr fp, [sp], #4)
bc: e12fff1e bx lr
000000c0 <main>:
c0: e92d4800 push {fp, lr}
c4: e28db004 add fp, sp, #4
c8: e24dd030 sub sp, sp, #48 @ 0x30
cc: e50b0028 str r0, [fp, #-40] @ 0xffffffd8
d0: e50b102c str r1, [fp, #-44] @ 0xffffffd4
d4: e3a03001 mov r3, #1
d8: e50b3008 str r3, [fp, #-8]
dc: e3a03002 mov r3, #2
e0: e50b300c str r3, [fp, #-12]
e4: e3a03003 mov r3, #3
e8: e50b3010 str r3, [fp, #-16]
ec: e3a03004 mov r3, #4
f0: e50b3014 str r3, [fp, #-20] @ 0xffffffec
f4: e3a03005 mov r3, #5
f8: e50b3018 str r3, [fp, #-24] @ 0xffffffe8
fc: e3a03006 mov r3, #6
100: e50b301c str r3, [fp, #-28] @ 0xffffffe4
104: e51b301c ldr r3, [fp, #-28] @ 0xffffffe4
108: e58d3004 str r3, [sp, #4]
10c: e51b3018 ldr r3, [fp, #-24] @ 0xffffffe8
110: e58d3000 str r3, [sp]
114: e51b3014 ldr r3, [fp, #-20] @ 0xffffffec
118: e51b2010 ldr r2, [fp, #-16]
11c: e51b100c ldr r1, [fp, #-12]
120: e51b0008 ldr r0, [fp, #-8]
124: ebffffcf bl 68 <sum>
128: e50b0020 str r0, [fp, #-32] @ 0xffffffe0
12c: e51b3020 ldr r3, [fp, #-32] @ 0xffffffe0
130: e1a00003 mov r0, r3
134: e24bd004 sub sp, fp, #4
138: e8bd8800 pop {fp, pc}
1 _start
00000000 <_start>:
0: e59fd048 ldr sp, [pc, #72] @ 50 <halt+0x4>
4: e59f0048 ldr r0, [pc, #72] @ 54 <halt+0x8>
8: e59f1048 ldr r1, [pc, #72] @ 58 <halt+0xc>
c: e59f2048 ldr r2, [pc, #72] @ 5c <halt+0x10>
- 0
- 设置SP栈帧
- PC基址变址 -> 地址 50,存放栈底内存地址 -> 0x08010000
- 4
- r0 保存 .data段在加载程序镜像中的起始地址LMA
- 8
- r1 保存 .data段在运行内存中的起始地址VMA
- c
- r2 保存 .data段在运行内存中的结束地址VMA
2 data_loop
00000010 <data_loop>:
10: e1510002 cmp r1, r2
14: 0a000002 beq 24 <bss_init>
18: e4903004 ldr r3, [r0], #4
1c: e4813004 str r3, [r1], #4
20: eafffffa b 10 <data_loop>
- 10, 14
- r1 从.data段VMA起始地址开始,递增向结束地址移动
- 18, 1c, 20
3 bss_init
00000024 <bss_init>:
24: e59f1034 ldr r1, [pc, #52] @ 60 <halt+0x14>
28: e59f2034 ldr r2, [pc, #52] @ 64 <halt+0x18>
- 24
- r1 保存 .bss段在运行内存中的起始地址VMA
- 28
- r2 保存 .bss段在运行内存中的结束地址VMA
4 bss_loop
0000002c <bss_loop>:
2c: e1510002 cmp r1, r2
30: 0a000002 beq 40 <call_main>
34: e3a03000 mov r3, #0
38: e4813004 str r3, [r1], #4
3c: eafffffa b 2c <bss_loop>
- 2c, 30
- r1 从.bss段VMA起始地址开始,递增向结束地址移动
- 34, 38, 3c
5 call_main
00000040 <call_main>:
40: e3a00000 mov r0, #0
44: e3a01000 mov r1, #0
48: eb00001c bl c0 <main>
- 40
- LR保存下条指令地址
- PC跳转至main函数首条指令地址
6 halt
0000004c <halt>:
4c: eafffffe b 4c <halt>
50: 08010000 .word 0x08010000
54: 0000013c .word 0x0000013c
58: 00010000 .word 0x00010000
5c: 00010000 .word 0x00010000
60: 00010000 .word 0x00010000
64: 00010000 .word 0x00010000
- 44
- 48
- 4c
- __data_load_addr : .data段在LMA起始地址
- 50, 54
- __data_start : .data段在VMA起始地址
- __data_start : .data段在VAM结束地址
- 58, 5c
- __bss_start : .bss段在VMA起始地址
- __bss_end : .bss段在VAM结束地址
7 sum
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
00000068 <sum>:
68: e52db004 push {fp} @ (str fp, [sp, #-4]!) @ 保存入栈信息
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc4
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
sp -> 0x800ffc4 --------------------
6c: e28db000 add fp, sp, #0 @ 更新栈帧
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800ffc4
sp寄存器: 0x800ffc4
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
fp ->
sp -> 0x800ffc4 --------------------
70: e24dd014 sub sp, sp, #20 @ 栈顶指针偏移,准备构建当前栈帧内容
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800ffc4
sp寄存器: 0x800ffb0
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
fp -> 0x800ffc4 --------------------
0x800ffc0 --------------------
0x800ffbc --------------------
0x800ffb8 --------------------
0x800ffb4 --------------------
sp -> 0x800ffb0 --------------------
74: e50b0008 str r0, [fp, #-8] @ 保存入参0
78: e50b100c str r1, [fp, #-12] @ 保存入参1
7c: e50b2010 str r2, [fp, #-16] @ 保存入参2
80: e50b3014 str r3, [fp, #-20] @ 0xffffffec 保存入参3
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800ffc4
sp寄存器: 0x800ffb0
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
fp -> 0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
sp -> 0x800ffb0 -------------------- <- fp-20
84: e51b2008 ldr r2, [fp, #-8] @ 取a
88: e51b300c ldr r3, [fp, #-12] @ 取b
8c: e0822003 add r2, r2, r3 @ 计算得到a + b
90: e51b3010 ldr r3, [fp, #-16] @ 取c
94: e0822003 add r2, r2, r3 @ 计算得到a + b + c
98: e51b3014 ldr r3, [fp, #-20] @ 取d
9c: e0822003 add r2, r2, r3 @ 计算得到a + b + c + d
a0: e59b3004 ldr r3, [fp, #4] @ 取e
a4: e0822003 add r2, r2, r3 @ 计算得到a + b + c + d + e
a8: e59b3008 ldr r3, [fp, #8] @ 取f
ac: e0823003 add r3, r2, r3 @ 计算得到a + b + c + d + e + f
b0: e1a00003 mov r0, r3 @ 将计算结果保存到r0
r0寄存器: 0x15
fp寄存器: 0x800ffc4
sp寄存器: 0x800ffb0
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
fp -> 0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
sp -> 0x800ffb0 -------------------- <- fp-20
b4: e28bd000 add sp, fp, #0 @ 当前函数栈帧弹出
r0寄存器: 0x15
fp寄存器: 0x800ffc4
sp寄存器: 0x800ffc4
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
sp ->
fp -> 0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
b8: e49db004 pop {fp} @ (ldr fp, [sp], #4) 恢复当前函数调用者的栈帧
r0寄存器: 0x15
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
bc: e12fff1e bx lr @ 跳转回lr即当前函数调用者下条指令
r0寄存器: 0x15
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
pc寄存器: 0x128
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
8 main
fp寄存器: 0x00000000
sp寄存器: 0x8010000
lr寄存器: 0x4c
4c: eafffffe b 4c <halt>
栈: 空
000000c0 <main>:
c0: e92d4800 push {fp, lr} @ 保存信息入栈
fp寄存器: 0x00000000
sp寄存器: 0x800fff8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
0x800fffc --------------------
0x00000000 (fp)
sp -> 0x800fff8 --------------------
c4: e28db004 add fp, sp, #4 @ 更新栈帧
fp寄存器: 0x800fffc
sp寄存器: 0x800fff8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
sp -> 0x800fff8 --------------------
c8: e24dd030 sub sp, sp, #48 @ 0x30 @ 栈顶指针偏移,准备构建当前栈帧内容
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 --------------------
0x800fff4 -------------------- <- sp-4
0x800fff0 -------------------- <- sp-8
0x800ffec -------------------- <- sp-12
0x800ffe8 -------------------- <- sp-16
0x800ffe4 -------------------- <- sp-20
0x800ffe0 -------------------- <- sp-24
0x800ffdc -------------------- <- sp-28
0x800ffd8 -------------------- <- sp-32
0x800ffd4 -------------------- <- sp-36
0x800ffd0 -------------------- <- sp-40
0x800ffcc -------------------- <- sp-44
sp -> 0x800ffc8 -------------------- <- sp-48
cc: e50b0028 str r0, [fp, #-40] @ 0xffffffd8 @ 保存函数入参1 argc
d0: e50b102c str r1, [fp, #-44] @ 0xffffffd4 @ 保存函数入参2 argv
r0寄存器: 0
r1寄存器: 0
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
0x800fff4 -------------------- <- fp-8
0x800fff0 -------------------- <- fp-12
0x800ffec -------------------- <- fp-16
0x800ffe8 -------------------- <- fp-20
0x800ffe4 -------------------- <- fp-24
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
0x800ffcc --------------------
sp -> 0x800ffc8 --------------------
d4: e3a03001 mov r3, #1
d8: e50b3008 str r3, [fp, #-8]
dc: e3a03002 mov r3, #2
e0: e50b300c str r3, [fp, #-12]
e4: e3a03003 mov r3, #3
e8: e50b3010 str r3, [fp, #-16]
ec: e3a03004 mov r3, #4
f0: e50b3014 str r3, [fp, #-20] @ 0xffffffec
f4: e3a03005 mov r3, #5
f8: e50b3018 str r3, [fp, #-24] @ 0xffffffe8
fc: e3a03006 mov r3, #6
100: e50b301c str r3, [fp, #-28] @ 0xffffffe4
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
0x800ffcc --------------------
sp -> 0x800ffc8 --------------------
104: e51b301c ldr r3, [fp, #-28] @ 0xffffffe4
108: e58d3004 str r3, [sp, #4] @ 调用函数前传参准备,超过4个参数的局部变量f入栈
10c: e51b3018 ldr r3, [fp, #-24] @ 0xffffffe8
110: e58d3000 str r3, [sp] @ 调用函数前传参准备,超过4个参数的局部变量e入栈
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
114: e51b3014 ldr r3, [fp, #-20] @ 0xffffffec @ 调用函数前传参准备,前4个参数用寄存器传参,传参局部变量d
118: e51b2010 ldr r2, [fp, #-16] @ 调用函数前传参准备,前4个参数用寄存器传参,传参局部变量c
11c: e51b100c ldr r1, [fp, #-12] @ 调用函数前传参准备,前4个参数用寄存器传参,传参局部变量b
120: e51b0008 ldr r0, [fp, #-8] @ 调用函数前传参准备,前4个参数用寄存器传参,传参局部变量a
r0寄存器: 1
r1寄存器: 2
r2寄存器: 3
r3寄存器: 4
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x4c
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc --------------------
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
124: ebffffcf bl 68 <sum> @ 跳转调用函数sum,等待sum执行完成跳转回下条指令
r0寄存器: 0x15
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
pc寄存器: 0x128
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
128: e50b0020 str r0, [fp, #-32] @ 0xffffffe0 保存sum函数结果到result局部变量
12c: e51b3020 ldr r3, [fp, #-32] @ 0xffffffe0 将result作为返回值保存在r0中
130: e1a00003 mov r0, r3
r0寄存器: 0x15
fp寄存器: 0x800fffc
sp寄存器: 0x800ffc8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
pc寄存器: 0x128
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
#0x15 (局部变量result)
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
sp -> 0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
134: e24bd004 sub sp, fp, #4 @ 当前main函数栈帧弹出
r0寄存器: 0x15
fp寄存器: 0x800fffc
sp寄存器: 0x800fff8
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
pc寄存器: 0x128
栈:
0x8010000 --------------------
0x0000004c (lr)
fp -> 0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
sp -> 0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
#0x15 (局部变量result)
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20
138: e8bd8800 pop {fp, pc} @ 出栈当前函数调用者的栈帧fp,和lr,更新fp和pc
r0寄存器: 0x15
fp寄存器: 0x00000000
sp寄存器: 0x8010000
lr寄存器: 0x128
<main> 128: e50b0020 str r0, [fp, #-32]
pc寄存器: 0x0000004c
<halt> 4c: eafffffe b 4c <halt>
栈:
sp -> 0x8010000 --------------------
0x0000004c (lr)
0x800fffc -------------------- <- main函数栈帧栈底
0x00000000 (fp)
0x800fff8 -------------------- <- fp-4
#1 (局部变量a)
0x800fff4 -------------------- <- fp-8
#2 (局部变量b)
0x800fff0 -------------------- <- fp-12
#3 (局部变量c)
0x800ffec -------------------- <- fp-16
#4 (局部变量d)
0x800ffe8 -------------------- <- fp-20
#5 (局部变量e)
0x800ffe4 -------------------- <- fp-24
#6 (局部变量f)
0x800ffe0 -------------------- <- fp-28
#0x15 (局部变量result)
0x800ffdc -------------------- <- fp-32
0x800ffd8 -------------------- <- fp-36
r0 (函数入参0)
0x800ffd4 -------------------- <- fp-40
r1 (函数入参1)
0x800ffd0 -------------------- <- fp-44
f #6 (调用函数传参)
0x800ffcc --------------------
e #5 (调用函数传参)
0x800ffc8 --------------------
0x800fffc (fp)
0x800ffc4 --------------------
0x800ffc0 --------------------
a #1 (函数入参a)
0x800ffbc -------------------- <- fp-8
b #2 (函数入参b)
0x800ffb8 -------------------- <- fp-12
c #3 (函数入参c)
0x800ffb4 -------------------- <- fp-16
d #4 (函数入参d)
0x800ffb0 -------------------- <- fp-20