ARM汇编函数栈帧分析

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
    • 从LMA向VMA按字大小(4B)拷贝

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
    • 将.bss段运行内存清空为0

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
    • main函数退出后进入死循环
  • 48
    • __stack_top : 栈顶地址
  • 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
posted @ 2025-12-26 10:56  L-ZH  阅读(0)  评论(0)    收藏  举报